Pierre Palatin's corner

Random posts about some stuff I’ve been doing.

Redirecting a port to another one with iptables, including local packets.

Posted at — Jan 1, 2008

For some reason, I have a smtp server running completely as user and which cannot open port 25; it listens to port 2225 instead. So, I want to redirect port 25 to port 2225, using iptables.

The standard redirection is simple and can be easily found on your favorite search engine:

iptables -t nat -A PREROUTING -p tcp --dport 25 -j REDIRECT --to-port 2225

However, due to the way iptables works, this redirection won’t work if you’re trying to connect to port 25 from the machine itself, through localhost or through one of the IPs of the machine.

The problem is that there’s no INPUT chain in the nat table, so we cannot modify the packets when they arrive on the host. A classic option is to use the CONNMARK jump target to mark appropriate packets when you can detect them and act on it later just by detecting the mark. In this case, it would mean marking the packet in the INPUT chain of the filter table and modifying the packet in the OUTPUT chain of the nat table. However, the INPUT chain for packets going to the machine is obviously taken after the OUTPUT chain for packets issued by the machine.

The solution I’ve kept is to simply do a maching based on the IPs of the machine. It means doing basically one rule per IP of the machine, which is not that great but probably ok as long as you don’t often change of IPs.

In my case, this machine has 2 IPs and of course the localhost interface. In pratice, for the two IPs:

iptables -t nat -A OUTPUT -p tcp -d 1.2.3.4 --dport 25 -j REDIRECT --to-port 2225 iptables -t nat -A OUTPUT -p tcp -d 5.6.7.8 --dport 25 -j REDIRECT --to-port 2225

And for localhost:

iptables -t nat -A OUTPUT -p tcp -d 127.0.0.0/8 --dport 25 -j REDIRECT --to-port 2225