Nftables DNAT, похоже, не работает

Nftables DNAT, похоже, не работает

Я пытаюсь настроить DNAT на моем новом Centos 8 с помощью nftables. Эта утилита (и Centos 8) для меня в новинку, я уже давно использую iptables (от Centos до 6).

Я предполагаю, что я что-то не настроил должным образом для срабатывания DNAT, однако я просто не использую инструменты должным образом. Или и то, и другое.

В любом случае, если это имеет значение, вот мой предыдущий вопрос о некоторых проблемах маршрутизации на том же самом устройстве:Несколько подключений к Интернету, входящие пакеты на неправильном порту сетевой карты (проблема входящей маршрутизации?)(проблема была в потоке ARP, решена).

Ниже представлен эскиз моей текущей установки, а синей линией отмечено то, что я хочу получить (ожидаемый «путь»).

введите описание изображения здесь

По сути, пакеты приходят из Интернета, проходят через интерфейс 2 (ens2), подвергаются ДНК-трансляции через локальный интерфейс (ens5, локальный IP 192.168.1.10) на 192.168.1.2. (Как только это заработает, то же самое будет настроено для ens 3 и 4, направляясь на несколько разных виртуальных машин в той же локальной сети)

Я проверил, что пакеты поступают на правильный интерфейс (ожидаемые срабатывания журнала nft), однако conntrack -Eничего не отображается.

Кроме того, журналирование iptables на компьютере Centos 6 (фактическая цель — 192.168.1.2) ничего не показывает (то же самое журналирование, созданное много лет назад, показывало ожидаемый вывод в последний раз, когда я проверял, несколько месяцев назад, так что теоретически с этим компьютером все должно быть в порядке).

Вот мой скрипт nftables «как есть» на данный момент, с IP/IF, переведенными для соответствия эскизу.

table ip nat {
    chain PREROUTING {
            type nat hook prerouting priority -100; policy accept;
            iif "ens2" goto PREROUTING_RDS2
            iif "ens3" goto PREROUTING_RDS3
    }

    chain PREROUTING_RDS2 {
            tcp dport { http, https } log prefix "RDS2_dnat-3 "
            tcp dport { http, https } dnat to IP_6
    }

    chain PREROUTING_RDS3 {
            tcp dport { http, https } log prefix "RDS3_dnat-3 "
            tcp dport { http, https } dnat to IP_6
    }
}

table inet filter {
    chain INPUT {
            type filter hook input priority 0; policy drop;
            #
            iif "lo" accept
            #
            # allow ping
            ip protocol icmp icmp type echo-request limit rate 1/second log prefix "PING "
            ip protocol icmp icmp type echo-request limit rate 1/second accept
            # following is required and must be BEFORE the ct state established otherwise the ping flooding will not be stopped
            ip protocol icmp drop
            #
            ct state established,related accept
            ct status dnat accept
            #
            iifname "ens5" goto INPUT_LOCAL
            #
            # now we drop the rest
            ct state invalid log prefix "INPUT_STATE_INVALID_DROP: "
            ct state invalid drop
            log prefix "INPUT_FINAL_REJECT: "
            reject with icmpx type admin-prohibited
    }

    chain FILTER {
            type filter hook forward priority 50; policy drop;
            iif "ens2" goto FILTER_RDS2
            iif "ens3" goto FILTER_RDS3
    }

    chain INPUT_LOCAL {
            tcp dport ssh goto INPUT_LOCAL_ssh
    }

    chain INPUT_LOCAL_ssh {
            ip saddr IP_MY_PC accept
    }

    chain FILTER_RDS2 {
            oifname "ens5" ip daddr IP_6 tcp dport { http, https } accept
    }

    chain FILTER_RDS3 {
            oifname "ens5" ip daddr IP_6 tcp dport { http, https } accept
    }
}

Заранее спасибо.

решение1

На самом деле, на этот вопрос трудно ответить, не взглянув хорошенько напредыдущий вопрос/ответрешение начальной настройки дляcentos8. Решение становится очень сложным. Учитывая тип конфигурации, которую необходимо для этого реализовать, вероятно, не стоит иметь один IP на интерфейс с несколькими интерфейсами в одной локальной сети, а не все IP на одном интерфейсе, особенно учитывая, что это виртуальная среда: не будет никакого ускорения. Любое изменение конфигурации должно быть отражено во всех командах ниже, поэтому управлять этим правильно будет сложно.


centos8маршрутизатор

Поскольку для решения проблемы с несколькими интерфейсами в одной локальной сети существуют дополнительные таблицы маршрутизации, то теперь, когда в этом разделе вопросов и ответовcentos8действует как маршрутизатор, необходимо продублировать больше записей маршрутов из основной таблицы в дополнительные таблицы маршрутизации:

# ip route add 192.168.1.0/24 dev ens5 table 1001 src 192.168.1.10 
# ip route add 192.168.1.0/24 dev ens5 table 1002 src 192.168.1.10 
# ip route add 192.168.1.0/24 dev ens5 table 1003 src 192.168.1.10 
# ip route add 192.168.1.0/24 dev ens5 table 1004 src 192.168.1.10 

в противном случае любой пакет, полученный наens1,ens2,ens3илиens4иДНКпрошел черезens5не удастсяфильтр обратного путитак как нет маршрута черезens5на этих столах.

Конечно, этого недостаточно: в ответных пакетах нет никакой информации (например: возвращение изcentos6) о том, какой интерфейс использовался и должен быть повторно использован наоборот. Поэтому эту информацию нужно запомнить для каждого потока, используя conntrack netfilter. В правилах nftables удалите всю ip natтаблицу:

# nft delete table ip nat

и замените ее этой новой таблицей ip markandnat:

# nft -f - << 'EOF'
table ip markandnat {
        map iif2mark {
                type iface_index : mark;
                elements = {
                        ens1 : 101,
                        ens2 : 102,
                        ens3 : 103,
                        ens4 : 104
                }
        }

        map mark2daddr {
                type mark : ipv4_addr;
                elements = {
                        102 : 192.168.1.2,
                        103 : 192.168.1.2, # same IP, as per OP's config
                        104 : 192.168.1.4  # some other VM
                }
        }
        chain premark {
                type filter hook prerouting priority -150; policy accept;
                meta mark set ct mark meta mark != 0 return
                meta mark set iif map @iif2mark meta mark != 0 ct mark set meta mark
        }

        chain prenat {
                type nat hook prerouting priority -100; policy accept;
                tcp dport { http, https } dnat to meta mark map @mark2daddr
        }
}
EOF

Это сопоставит интерфейс => отметку => пункт назначения dnat, при этом отметка сохранится как отметка conntrack (см. ссылку в конце оконнмаркиспользование). Теперь эта метка будет доступна и использована стеком маршрутизации путем добавления следующих правил, чтобы указать на те же дополнительные таблицы маршрутизации:

# ip rule add pref 11001 fwmark 101 table 1001
# ip rule add pref 11002 fwmark 102 table 1002
# ip rule add pref 11003 fwmark 103 table 1003
# ip rule add pref 11004 fwmark 104 table 1004

но все еще не хватает части: снова о фильтре обратного пути. Когда используются метки, фильтр обратного пути не перепроверяет, используя новые маршруты, измененные метками, и обычно не проходит проверку. На самом деле естьнедокументированная функция, добавленная в ядро ​​2.6.33/2.6.32.8 в 2009/2010, который решает эту проблему, без необходимости использования режима свободного обратного пути: src_valid_mark.

# sysctl -w net.ipv4.conf.ens1.src_valid_mark=1
# sysctl -w net.ipv4.conf.ens2.src_valid_mark=1
# sysctl -w net.ipv4.conf.ens3.src_valid_mark=1
# sysctl -w net.ipv4.conf.ens4.src_valid_mark=1

centos6сервер

Если вы хотите временно использовать альтернативный шлюз, даже если это снова добавит сложности и, вероятно, непредвиденных побочных эффектов, это возможно, опять же с помощью отметок. Поскольку это CentOS 6,nftablesнедоступен, поэтомуiptablesбудет использован.

Я буду считать, чтоcentos6Виртуальная машина имеет IP 192.168.1.2/24 на (уникальном) интерфейсеeth0, и по умолчанию gw 192.168.1.1. Давайте добавим новую таблицу маршрутизации и правило для альтернативного шлюза 192.168.1.10:

# ip route add table 10 default via 192.168.1.10
# ip rule add fwmark 10 lookup 10

Положитеiptablesправила (здесь толькоувечьетаблица нужна):

# iptables-restore << 'EOF'
*mangle
:PREROUTING ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
-A PREROUTING -j CONNMARK --restore-mark
-A PREROUTING -m mark ! --mark 0 -j RETURN
-A PREROUTING -i eth0 -p tcp -m tcp --dport 80 -j MARK --set-mark 10
-A PREROUTING -i eth0 -p tcp -m tcp --dport 443 -j MARK --set-mark 10
-A PREROUTING -m mark ! --mark 0 -j CONNMARK --save-mark
-A OUTPUT -m connmark ! --mark 0 -j CONNMARK --restore-mark
COMMIT
EOF

Теперь любой поток, полученный на портах 80 или 443, будет маркировать входящие пакеты и их ответы. Эта маркировка будет использоваться стеком маршрутизации для изменения шлюза на 192.168.1.10 для входящих и ответов (калечить/ВЫХОДзапускает проверку перенаправления, см. 2-ю ссылку ниже).

src_valid_markПохоже , в этом случае нет необходимости использовать , но просто установите его или установите rp_filter=2, если он не работает. Эта настройка не позволит также получатьДНКред. трафик через 192.168.1.1.


Некоторые ссылки:

решение2

Судя по комментариям, самое главное и важное упущение — отключение ip forwarding. Просто:

echo 1 > /proc/sys/net/ipv4/ip_forward

и проверьте, доходят ли теперь пакеты DNAT до IP6.

Вторая проблема — асимметричная маршрутизация. Пакеты DNAT приходят на IP6 через 192.168.1.10 (IP5), где они изменяются (адрес назначения изменяется). Обратные пакеты будут проходить через шлюз по умолчанию в локальной сети (182.168.1.1) и не будут изменены на пути к источнику соединения. Они, скорее всего, сохранят свой адрес RFC1918 или будут SNAT-преобразованы во что-то другое на 192.168.1.1 и никогда не будут соответствовать ни одному соединению в пункте назначения и, скорее всего, будут отброшены.

РЕДАКТИРОВАТЬ:

Итак, для решения проблемы цепочки FORWARD я бы переписал ее следующим образом (на мой взгляд, гораздо проще):

table inet filter {
:
    chain FORWARD {
            type filter hook forward priority 0; policy drop;
            ct state established,related accept
            ct status dnat accept
    }
:
}

Связанный контент