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