Назад | Перейти на главную страницу

Как я могу DNAT пакет, приходящий через мост обратно к своему источнику с помощью iptables?

у меня есть host1 имеющий интерфейс WAN eth0 (1.2.3.4) и интерфейс LAN eth1 (10.41.82.1). Внутри LAN есть host2 с IP-адресом 10.41.82.2.

Входящие подключения к 1.2.3.4:22 пересылаются host2 используя следующие правила iptables для host1:

root@host1:~# iptables -t nat -A OUTPUT     -d 1.2.3.4 -p tcp --dport 22 -j DNAT --to 10.41.82.2:22
root@host1:~# iptables -t nat -A PREROUTING -d 1.2.3.4 -p tcp --dport 22 -j DNAT --to 10.41.82.2:22

Это отлично работает, кроме случаев, когда host2 пытается получить доступ 1.2.3.4:22:

root@host2:~# telnet 1.2.3.4 22
Trying 1.2.3.4...

root@host2:~# ping 1.2.3.4
PING 1.2.3.4 56(84) bytes of data.
64 bytes from 1.2.3.4: icmp_seq=1 ttl=64 time=0.125 ms
64 bytes from 1.2.3.4: icmp_seq=2 ttl=64 time=0.279 ms

root@host2:~# tcptraceroute 1.2.3.4 22
traceroute to 1.2.3.4, 30 hops max, 60 byte packets
 1  * * *
 2  * * *
 3  * * *
 4  * * *
 5  * * *
(and so on)

Похоже, пакеты пересылаются по кругу. Как видите, pinging работает, поэтому маршруты и IP-переадресация настроены правильно.

Что я сделал не так и как исправить проблему?


ОБНОВИТЬ:

Как упоминалось в ответе Билла Тора и как описано в Frozentux учебник по DNAT, Мне нужно добавить SNAT правило. Я сделал это сейчас (обратите внимание, что я добавил LAN-адрес host2 для -d, поскольку это правило применяется в POSTROUTING где место назначения пакета уже было изменено):

root@host1:~# iptables -t nat -A POSTROUTING -d 10.41.82.2 -p tcp --dport 22 -j SNAT --to 10.41.82.1

К сожалению, это не решает проблему, и все остается так же, как описано выше. Интересно, что SNAT правило никогда не выполняется, судя по счетчикам, показанным при запуске iptables -t nat -nvL.


ОБНОВЛЕНИЕ 2:

Я обнаружил, что когда я бегу tcpdump -i eth1, даже когда я запускаю его с параметрами, не имеющими отношения к этому случаю, такими как tcpdump -i eth1 port 34238, это вдруг работает. Но только пока tcpdump это работает.

Я пока не упомянул, потому что считал это несущественным, так это то, что eth1 на самом деле мост, и host2 это домен Xen. Я начинаю подозревать, что моя проблема может быть связана с этим.

Причина неудачи оказывается связана с тем, что eth1 фактически является мостовым интерфейсом. Фактически, host2 виртуальная машина Xen, работающая на host1 и eth1 это мост, который используется для связи между хостом и гостем.

Решил проблему позвонив bridge link set dev vif2.0 hairpin on (или альтернативно brctl hairpin eth1 vif2.0 on). vif2.0 представляет собой виртуальный сетевой интерфейс, созданный Xen и являющийся частью eth1 мост.

Итак, чтобы закрепить NAT на интерфейсе моста, обязательно включите закрепление моста для интерфейса (который является частью моста), на который входят пакеты.

Добавление SNAT правило в конце концов не понадобилось.


systemd-networkd также есть директива чтобы включить закрепление в файле * .network:

[Bridge]
HairPin=true

Я не был уверен, добавлять ли это в eth1.network или чтобы vif2.0.network (которого обычно не существует) в моем случае, но в конце концов ни один из них не работал.

То, что вы пытаетесь сделать, называется шпилькой NAT. Для host2 было бы лучше просто подключиться к host1.

Если вы хотите, чтобы это работало, используйте SNAT, а также DNAT для трафика, исходящего из локальной сети, идущего на внешний IP-адрес.

Другое решение, которое может сработать, - это добавить маршрут для хоста 2 - хост 1, который направляет трафик на маршрутизатор, а не в локальную сеть.