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
kernel with NAT support, recommended (but not necessary) is CONFIG_IP_NF_NAT_LOCAL=y, use will be explained below
iptables v1.26a at least
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:
To redirect incomming traffic means inserting rules into PREROUTING chain of the nat table.
Use the REDIRECT target, which allows you to specify destination port(s) (--to-ports)
Change the --dst ip to an ip of the interface of yours (such as eth0).
Redirection is done only for specified interface.
More in man iptables, search for REDIRECT keyword.
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 # ...