Я пытаюсь настроить 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
}
:
}