nat / switch external source port
When reproducing an issue with IP phones speaking SIP, I ran into the question of how to switch source port on my linux NAT router.
The problem the clients were having, were a result of a failing (or reset) NAT-gateway. The NAT-gateway would change the external source port mid-dialog (some SIP dialogs can persist for quite a long time).
So, how do you go about switching source port on an UDP connection on
your Linux NAT router without resetting it (or disturbing anyone else
using it)? The answer: conntrack(8)
Step (1): add a static SNAT mapping for a custom port, before the standard SNAT rules, for your specific application. In my case the phone is at 192.168.1.123, the destination at 123.123.123.123 and my external IP is 5.4.3.2.
# iptables -t nat -nvL POSTROUTING
Chain POSTROUTING (policy ACCEPT 25M packets, 1534M bytes)
pkts bytes target prot opt in out source destination
348K 31M SNAT 0 -- * eth2 0.0.0.0/0 0.0.0.0/0 to:5.4.3.2
# iptables -t nat -I POSTROUTING -o eth2 -s 192.168.1.123 -d 123.123.123.123 -p udp --dport 5060 -j SNAT --to 5.4.3.2:7060
Step (2): start the dialog. It is now connection tracked:
# conntrack -L -s 192.168.1.123 -p udp --reply-port-dst 7060
udp 17 165 src=192.168.1.123 dst=123.123.123.123 sport=5060 dport=5060 packets=15 bytes=7670 src=123.123.123.123 dst=5.4.3.2 sport=5060 dport=7060 packets=37 bytes=10179 [ASSURED] mark=0 use=1
Step (3): remove static NAT mapping, optionally replacing it with a new one and kill the tracked connection.
# iptables -t nat -D POSTROUTING -o eth2 -s 192.168.1.123 -d 123.123.123.123 -p udp --dport 5060 -j SNAT --to 5.4.3.2:7060
# iptables -t nat -I POSTROUTING -o eth2 -s 192.168.1.123 -d 123.123.123.123 -p udp --dport 5060 -j SNAT --to 5.4.3.2:7061
# conntrack -D -s 192.168.1.123 -d 123.123.123.123 -p udp --orig-port-src 5060 --orig-port-dst 5060
Step (4): watch how the dialog continues on the new external source port. You’re done.
# conntrack -L -s 192.168.1.123 -p udp --reply-port-dst 7061
udp 17 64 src=192.168.1.123 dst=123.123.123.123 sport=5060 dport=5060 packets=5 bytes=3208 src=123.123.123.123 dst=5.4.3.2 sport=5060 dport=7061 packets=6 bytes=2618 [ASSURED] mark=0 use=1