Motivation by example

Running Apache Tomcat as an unprivileged user means it should be bound to an unprivilleged port (such as 8080). But you want your pages being accessible not by http://anyhost.com:8080/yourapp/ but by an url http://anyhost.com/yourapp/

You can start tomcat with root privileges (a bad idea) and bind it to port 80 directly, or you can solve this problem using iptables (there are also other ways) and the REDIRECT target. This document describes the 'iptables' solution.

What is needed

Configuration by example

Configuration consists of redirecting incoming traffic (packets comming to your computer) and optionally redirecting locally generated packets. Obviously, if you are only serving pages for incoming clients (i guess this is true in most cases), you can easily live without redirecting localy generated packets.

To redirect locally generated packets, you must have the kernel option CONFIG_IP_NF_NAT_LOCAL set to Y. You will have to keep in mind, that without it, you will be unable to test this configuration from the localhost (meaning the computer where the redirection should take place) without special network setting (which is out of the scope of this document -- hint: a dummy module can help).

Also remember, that you redirect from port 80 to 8080, so 8080 should be still open and is functional as before.

Redirecting incoming traffic

All you need is this single rule:

iptables -t nat -I PREROUTING --src 0/0 --dst 127.0.0.1 -p tcp --dport 80 -j REDIRECT --to-ports 8080

This will insert into PREROUTING chain (?=-I) of the nat table (-t nat) the rule, that says:

Any incomming (-src 0/0) packets with destination address 127.0.0.1 (--dst 127.0.0.1) and tcp port 80 (-p tcp --dport 80) redirect to port 8080 (-j REDIRECT --to-ports 8080).

Things to remember are:

Redirecting locally generated packets

As said before, you can easilly live without that -- who will be accessing the pages from within that computer? Developers can still use the 8080 port, which is still functional.

But the manual wouldn't be complete without it :-)

iptables -t nat -I OUTPUT --src 0/0 --dst 127.0.0.1. -p tcp --dport 80 -j REDIRECT --to-ports 8080

This rule is the key -- it is much same as the one above, the only difference is, that you are using the OUTPUT chain.

Also remember, you need CONFIG_IP_NF_NAT_LOCAL=y in your kernel. Without it this rule can be inserted, but will have no effect.

Tips for Shorewall

Maybe you are using Shorewall and you are wondering where to put this custom setting? I used the file common (the recommended copy of the common.def). At the end of that file i put the lines:

run_iptables -t nat -I PREROUTING --src 0/0 --dst 127.0.0.1 -p tcp --dport 80 -j REDIRECT --to-ports 8080

run_iptables -t nat -I OUTPUT --src 0/0 --dst 127.0.0.1. -p tcp --dport 80 -j REDIRECT --to-ports 8080

(--dst was changed accordingly to my network interface of course.)

Another possibility is to use the Extension Scripts, like started and include a shell script like:

#
#!/bin/sh
#
# Redirect 127.0.0.1:53 to tor's DNSPort

/usr/sbin/iptables -t nat -I OUTPUT --protocol udp --out-interface lo --dport 53 \
    -j REDIRECT --to-ports 9053

I almost got this shorewall rule working, but I couldn't get it to do -o lo only -i lo:

REDIRECT-     $FW             ::9053          udp     53 # this almost works

Tips for Red Hat/Fedora

For Red Hat, one can edit /etc/sysconfig/iptables and add the following content (do not forget to replace the --dst section with correct ip address):

# ...
# NAT section
*nat
:PREROUTING ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
-A PREROUTING --src 0/0 --dst 127.0.0.1 -p tcp --dport 80 -j REDIRECT --to-ports 8080
-A PREROUTING --src 0/0 --dst 127.0.0.1 -p tcp --dport 443 -j REDIRECT --to-ports 8443
COMMIT
# ...