试图在以下非常简单的场景中找出我的错误:
|peerA|(Aip:Aport) <--> (Bdev:Bip:Bport)|NatNode|(Cdev:Cip:Cport) <--> (Dip:Dport)| peerD
(对等点 A 向 Bip:Bport 发送数据报,NatNode 将其转换为由 Cip:Cport 发送的数据报,并发往 Dip:Dport;反之亦然)
我使用空的 iptables 和“vanilla”路由表所做的是:
iptables -p udp -t nat -A PREROUTING -s Aip -d Bip -i Bdev --destination-port Bport -j DNAT --to-destination Dip:Dport
iptables -p udp -t nat -A POSTROUTING -s Aip -d Dip -o Cdev --destination-port Dport -j DNAT --to-source Cip:Cport
(加上反向规则,以及每个 -t nat 和 -t 过滤主要目标的一个 LOG 目标)
我期望的是: - 正确的重写(并且是OK的,如wireshark所示) - 每个传入数据包从PREROUTING(路由决策,可能到Cdev)遍历进入转发一次(路由决策,可能到 Cdev),然后后布线一次,然后它进入网络。
我得到的是(检查日志记录): 1.第一个数据包遍历 PREROUTING 一次,过滤器/前进一吨次(是的,相同的数据包 ID),然后后期制作很多次,然后发送到网络一次,远程对等点接收它。 2. 从第二个数据报开始,一切似乎都发生了,但翻译后的数据报是未发出在设备上。 3.如果我等待足够长的时间(比如>15秒)并再次重试,新序列的头部数据报的行为就像1.,从第二个开始就像2.
还尝试删除 -i 和 -o 选项,但似乎没有改变任何东西。
我在这里做错了什么?
我无法发现问题,在我看来,我“按预期”做了,本能地我怀疑路由决策点出了问题,也许像 2. 中那样的数据包不是由 linux 的某些保护行为发出的TCP/IP 堆栈...
我很确定这是我自己的错,但找不到哪里。
感谢您的帮助!
答案1
如果你想为 Dip 做经典的 NAT 并为其 Dport 实现端口转发,那么你不需要为它任何特制的 POSTROUTING 规则,只需添加通用的 -j MASQUERADE 即可。
还有.. POSTROUTING 中的DNAT?你打错字了吗?
我通常将经典 NAT 实现为(假设设置了阻止防火墙,并且 conntrack 收回所有“已应答”数据包):
iptables -I POSTROUTING -o ppp0 -j MASQUERADE
iptables -I FORWARD -i eth0 -o ppp0 -j ACCEPT
iptables -I PREROUTING -i ppp0 -p tcp --dport 80 -j DNAT --to local_ip:80
这里,eth0 是与 local_ip 位于同一子网中的本地 iface,ppp0 是互联网 iface。