I have, among others, the following iptables NAT rules on the machine with IP addresses 192.168.1.71 and a.b.c.d, where a.b.c.d represents a public IP address:
iptables -t nat -A PREROUTING -p udp --dport 20001 -j DNAT --to-destination 192.168.1.72:20000
iptables -t nat -A POSTROUTING -p udp -s 192.168.1.72 --sport 20000 -j SNAT --to-source a.b.c.d:20001
When, thru STUN, I try to find the public IP address assigned to the socket with local port 20000 on local machine 192.168.1.72, I do not get 20001, I consistently get 32018. I, however, do get the correct IP address a.b.c.d. What do I need to change in my iptables rules?
UPDATE: The problem was in my computation of the port number from the STUN response. Related question: The rule:
iptables -A INPUT -p udp -j LOG --log-prefix "iptables: "
does not log the packets for matched packets but does log for other packets. Placing this rule above or below the above two rules did not make a difference.
If the first packet is always sent from inside the network, then you only need rule in
POSTROUTING
. Linux connection tracking also handles UDP "associations", so it knows how to handle return packets.For example, DNS over UDP reply packets are relayed to clients behind NAT using Linux connection tracking.
Your
LOG
rule is put into theINPUT
chain infilter
table, which is used only for packets where destination is the router itself. The packets handled byPREROUTING
/POSTROUTING
chains never go toINPUT
chain.Your rules should look like:
https://upload.wikimedia.org/wikipedia/commons/3/37/Netfilter-packet-flow.svg is a comprehensive image how packets flow inside Linux network stack and different IPTables chains / tables.