我正在尝试将源端口为 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。