у меня есть 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, который направляет трафик на маршрутизатор, а не в локальную сеть.