IPtables SNAT 吃掉数据包

IPtables SNAT 吃掉数据包

我正在尝试将源端口为 X 的传出 UDP 数据包转换为源端口为 Y 的传出 UDP 数据包。

我使用以下 iptables 规则完成了此操作:

iptables -t nat -A POSTROUTING -s 10.0.0.1 -p udp --sport X -j SNAT --to-source 10.0.0.1:Y

当生成源端口为 X 的数据包时,此规则的计数器会增加,但之后会完全消失。我无法在任何其他链或表的计数器中找到它们,也无法使用 tcpdump 在任何接口上看到它们。

如果我删除该规则,那么数据包就可以通过源端口 X 正常接收。但是当我重新设置规则时,数据包就消失了。

我正在使用在 Voyage Linux 上运行的 iptables 版本 v1.2.11。我无法轻松更新,因为这需要在几百台远程设备上进行。

我究竟做错了什么?

编辑:下面添加了 iptables 配置,与无法影响此配置的特定应用程序相关的规则已被删除。

# Clear any existing rules 
iptables -v -t filter   -F
iptables -v -t nat      -F
iptables -v -t mangle   -F

iptables -v -t filter   -X
iptables -v -t nat      -X
iptables -v -t mangle   -X

# Policies
iptables -t mangle      -P PREROUTING   ACCEPT
iptables -t nat         -P PREROUTING   ACCEPT
iptables -t filter      -P INPUT        DROP
iptables -t filter      -P OUTPUT       ACCEPT
iptables -t filter      -P FORWARD      DROP

# Allow established connections.
iptables -t filter      -A INPUT      -m state --state ESTABLISHED -j ACCEPT
iptables -t filter      -A INPUT      -m state --state ESTABLISHED,RELATED -j ACCEPT  
iptables -t filter      -A FORWARD      -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -t filter      -A FORWARD      -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -t filter      -A OUTPUT       -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -t filter      -A OUTPUT       -m state --state ESTABLISHED,RELATED -j ACCEPT

# Allow localhost to talk to itself.
iptables -t filter  -A INPUT      -i lo -j ACCEPT

# Drop stealth scan. 
iptables -t filter      -A INPUT      -p tcp -s 0/0 -d 0/0 --tcp-flags ALL NONE -j DROP                      
iptables -t filter      -A INPUT      -p tcp -s 0/0 -d 0/0 --tcp-flags ALL ALL -j DROP                       
iptables -t filter      -A INPUT      -p tcp -m tcp --tcp-flags FIN,SYN,RST,PSH,ACK,URG NONE -j DROP
iptables -t filter      -A INPUT      -p tcp -m tcp --tcp-flags SYN,FIN SYN,FIN -j DROP
iptables -t filter      -A INPUT      -p tcp -m tcp --tcp-flags SYN,RST SYN,RST -j DROP
iptables -t filter      -A INPUT      -p tcp -m tcp --tcp-flags FIN,RST FIN,RST -j DROP 
iptables -t filter      -A INPUT      -p tcp -m tcp --tcp-flags ACK,FIN FIN -j DROP
iptables -t filter      -A INPUT      -p tcp -m tcp --tcp-flags ACK,URG URG -j DROP

# Allow forwarding from LAN to WAN.
iptables -t filter      -A FORWARD      -i lanif -o wanif -j ACCEPT

# The NAT, strict with fixed IP address - might be different with a DHCP assigned WAN_IP
iptables -t nat         -A POSTROUTING  -o wanif -j SNAT --to-source $WAN_IP
iptables -t nat         -A POSTROUTING  -m mark --mark 11 -j ACCEPT

# Change source port X to Y - why does this not work???
iptables -t nat     -A POSTROUTING  -s lanif -p udp --sport X -j SNAT --to-source wanif:Y

答案1

我究竟做错了什么?

可能没什么。这是数据包穿过 Netfilter 的方式。

请检查此图作为参考:

(来源:Iptables 教程 1.2.1作者:Oskar Andreasson,2006 年)

我在其他连锁店或餐桌上都找不到它们

SNAT是最终的 Netfilter 目标,数据包之后不会出现在同一个链中。 -tablePOSTROUTING中的 -chainnat是数据包可以遍历 Netfilter 框架的绝对最终表。Tcpdump 附加到相当早的阶段,我思考mangle/POSTROUTING

并且无法使用 tcpdump 在任何接口上看到它们。这是因为 tcpdump 在数据包被编辑之前就看到了它们SNAT

有事吗事实上出了问题? 这听起来就像是完全正常的 Netfilter-tcpdump-oddities。

编辑:您的 SNAT 语句最后发生。也许您需要插入它声明-o wanif -j SNAT --to-source $WAN_IP。由于我没有更多细节,我无法判断这是错误还是故意的。

答案2

我原本期望看到这样的结果:

iptables -t nat -A POSTROUTING -s 10.0.0.1 -p udp --dport X -j SNAT --to-port Y

答案3

也许有服务已经监听该端口。iptables的 SNAT 在进行转换时会尝试保持与原始数据包中相同的端口。 如果此端口不可用,它将使用另一个端口。

我在尝试对 DNS 服务器的回复进行 SNAT 时遇到了这个问题。这导致回复从端口 1 发送,因为 DNS 服务器已经在使用端口 53。

解决方案是让 DNS 服务器监听不同的端口,将传入流量从目标端口 53 重定向到目标端口 X,然后 SNAT 将端口从 X 重写为 53。

相关内容