Running Tomcat on Port 80

By default Tomcat's HTTP connector listens on port 8080. Changing to port 80 in Linux environment can be quite a tricky issue, since by default listening on any port under 1024 require a privileged user, and for security considerations it is not recommended to run Tomcat with elevated permissions. This article discusses how to use authbind to achieve this; it also describes the way all this configuration can be automated for the sake of the creation of a script which can be used to initialize a freshly installed Linux instance. This is especially advantageous on Amazon EC2, where we can use this init-script to initialize a fresh instance just launched from an AMI; and indeed, for the sake of this article Amazon's "Amazon Linux Image 1.0" was used for testing. Please note that this is a CentOS 6-based linux distribution, for other distributions there are slight changes, like replacing "sudo yum install tomcat7" with "sudo apt-get install tomcat7" on Debian-based systems like Ubuntu.

Listening on ports < 1024 in Linux with an unprivileged user

There are more options to achieve this:

  • By using authbind which authorizes specific users to specific ports under 1024
  • By using Jsvc, a set of libraries and applications for making Java applications run on UNIX more easily (Jsvc allows Tomcat application to perform some privileged operations as root (e.g. bind to a port < 1024), and then switch identity to a non-privileged user)
  • By configuring iptables to re-route the packets from port 80 to 8080

This article describes the authbind approach. But first, let's tell Tomcat to listen on port 80 instead of 8080

Changing Tomcat's default HTTP port

The default HTTP port is defined in /etc/tomcat7/server.xml:

<Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" />

We need to change this default port to 80 in server.xml. Either replace by hand, or automatically: to replace the occurrences of port="8080" to port="80", execute the following script:

sudo sed -i 's/port\=\"8080\"/port\=\"80\"/' /etc/tomcat7/server.xml

The same for port 8443, which will be replaced with port 443:

sudo sed -i 's/port\=\"8443\"/port\=\"443\"/' /etc/tomcat7/server.xml

We'll start Tomcat with authbind. This can be achieved by changing Tomcat's init-script in /etc/init.d, replacing the line

TOMCAT_SCRIPT="/usr/sbin/tomcat7"

with

TOMCAT_SCRIPT="exec authbind --deep /usr/sbin/tomcat7"

Again, it can be automated like this:

sudo sed -i 's/TOMCAT_SCRIPT=\"\/usr\/sbin\/tomcat7\"/TOMCAT_SCRIPT=\"exec authbind --deep \/usr\/sbin\/tomcat7\"/' /etc/i

We have to tell Tomcat to use the IPv4 stack by default. This can be done by appending the line CATALINA_OPTS="-Djava.net.preferIPv4Stack=true" to /etc/tomcat7/tomcat7.conf:

sudo sed -i '$ a\CATALINA_OPTS=\"-Djava\.net\.preferIPv4Stack=true\"\n' /etc/tomcat7/tomcat7.conf

Installing and configuring authbind

Authbind is installed the usual way, with the help of gcc and make. Please note: For this step to succeed, the gcc package is needed. It is already installed with the command sudo yum install gcc earlier, when tomcat was installed.

cd ~
wget http://www.chiark.greenend.org.uk/ucgi/~ijackson/cvsweb/authbind/authbind.tar.gz?tarball=1 -O authbind.tar
tar xf authbind.tar
cd authbind
make
sudo make install

Authbind is configured with some special files, for which we can assign our arbitrary permissions for the users we want to give access to. Since Tomcat is running with the Tomcat user, we'll tell authbind to allow connections to the HTTP port 80 and the HTTPS port 443 for this account:

sudo touch /etc/authbind/byport/80
sudo chmod 500 /etc/authbind/byport/80
sudo chown tomcat /etc/authbind/byport/80
sudo touch /etc/authbind/byport/443
sudo chmod 500 /etc/authbind/byport/443
sudo chown tomcat /etc/authbind/byport/443

For the changes to take effect, Tomcat has to be restarted:

sudo /etc/init.d/tomcat7 restart

To see if there is any error, the tomcat log can be consulted:

less -S /var/log/tomcat7/catalina.out

The whole script

Here is the whole script which automates all this:

sudo yum -y install tomcat7 gcc
sudo sed -i 's/port\=\"8080\"/port\=\"80\"/' /etc/tomcat7/server.xml
sudo sed -i 's/port\=\"8443\"/port\=\"443\"/' /etc/tomcat7/server.xml
sudo sed -i 's/TOMCAT_SCRIPT=\"\/usr\/sbin\/tomcat7\"/TOMCAT_SCRIPT=\"exec authbind --deep \/usr\/sbin\/tomcat7\"/' /etc/init.d/tomcat7
sudo sed -i '$ a\CATALINA_OPTS=\"-Djava\.net\.preferIPv4Stack=true\"\n' /etc/tomcat7/tomcat7.conf
cd ~
wget http://www.chiark.greenend.org.uk/ucgi/~ijackson/cvsweb/authbind/authbind.tar.gz?tarball=1 -O authbind.tar
tar xf authbind.tar
cd authbind
make
sudo make install
sudo touch /etc/authbind/byport/80
sudo chmod 500 /etc/authbind/byport/80
sudo chown tomcat /etc/authbind/byport/80
sudo touch /etc/authbind/byport/443
sudo chmod 500 /etc/authbind/byport/443
sudo chown tomcat /etc/authbind/byport/443
sudo /sbin/chkconfig --levels 235 tomcat7 on
sudo /etc/init.d/tomcat7 restart
cd ~

Comments

Popular posts from this blog

Reduce TIME_WAIT Socket Connections