3 Ways to Run a Servlet Container on Port 80 as Non-Root

Published: 17 Feb 2007

This is a very brief outline of how to run the Apache Tomcat servlet container on port 80 (the standard web server port) on a Linux operating system. The steps illustrated here are specific to Tomcat but similar steps can be implemented for other servlet containers.

The issue is that the linux kernel has a security precaution built in to the kernel to only allow the root user to bind to a port under 1024. Since it's a bad idea to run a network server as root, most startup scripts bind to the initial listening socket, then drop down to a non-privileged user. Since Tomcat is written in Java, it does not have the ability to switch users like this.

Note: This is a platform-specific issue and these steps are not necessary on Microsoft Windows.

Disclaimer: I am also not responsible if your network configuration is FUBAR. I have written this post from a novice sys admin perspective and largely put the following solutions together from my own research.

Introduction, special considerations and disclaimer out of the way :)...Here are the three ways around this limitation:

1. Use Apache httpd server to "pass" requests to Tomcat

2. IPtables

This requires a kernel version of 2.4.x or higher. If you're running an older version of the kernel take a look at IPChains and consider a command something like:

ipchains -I input --proto TCP --dport 80 -j REDIRECT 8080

The IPtables solution allows Tomcat to run as an independent server as a non-privileged user and listen on port 80. IPtables will redirect all requests coming in on port 80 to port 8080 or whatever port you have Tomcat running under.The first step for this solution is to make sure your firewall allows TCP requests on port 8080 (or whatever port your Tomcat configuration has specfied). Essentially you need to duplicate all the firewall rules you have configured for port 80 since you will be redirecting those requests to 8080. The second step is to use the iptables command (usually installed by default on linux distributions) to redirect all packets on port 80, to port 8080. Here is a an example of the command you would use to do this:

iptables -t nat -A PREROUTING -p tcp --dport 80 -i eth0 -j REDIRECT --to-port 8080

To redirect local requests use the following command:

iptables -t nat -A OUTPUT -p tcp -d 127.0.0.1 --dport 80 -j REDIRECT --to-port 8080

This is handy if you're running Tomcat on your workstation and debugging an application that's required to run on port 80.

3. rinetd

rinetd is a dedicated port redirector program that receives a packet and redirects it to a different port or address. Since rinetd redirects packets after they've gone through IPtables, this solution can be used for local and non-local requests.There are two things you should consider when using rinetd. First, rinetd cannot be used to redirect FTP requests because FTP requires more than one socket. Secondly, rinetd makes all packets appear as though they originated from the local machine. This obviously will impact things like web server logs and setting permissions based on IP address. Although rinetd has these side effects, using a combination of iptables and rinetd may be another option but seems like a more complicated solution from a debugging and maintenance perspective.