I am trying to translate outgoing UDP packets with a source port of X to a source port of Y.
I have done this using the following iptables rule:
iptables -t nat -A POSTROUTING -s 10.0.0.1 -p udp --sport X -j SNAT --to-source 10.0.0.1:Y
The counters for this rule increase when packets with a source port of X are generated, but completely vanish after that. I cannot find them in the counters of any other chain or table, and cannot see them on any interface using tcpdump.
If I remove that rule, then the packets are received fine with the source port of X. But as soon as I put the rule back, the packets vanish.
I am using iptables version v1.2.11 running on Voyage Linux. I am unable to easily update as this will need to be done on a few hundred remote devices.
What am I doing wrong?
Edit: iptables config added below, rules related to specific applications that can't affect this have been removed.
# 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
Best Answer
Probably nothing. It's the way packets traverse Netfilter.
Check this diagram as a reference:
(Source: Iptables Tutorial 1.2.1 by Oskar Andreasson, 2006)
SNAT
is a final Netfilter target, packets will not show up in the same chain afterwards. ThePOSTROUTING
-chain in thenat
-table is the absolute final table a packet can traverse the Netfilter-framework. Tcpdump is attached to a fairly ealier stage, I think inmangle/POSTROUTING
.Is something actually going wrong? It sounds like perfectly normal Netfilter-tcpdump-oddities.
Edit: Your SNAT statement happens in the end. Maybe you need to insert it before the
-o wanif -j SNAT --to-source $WAN_IP
statement. Since I have no more details, I can't tell if it's a mistake or intentional.