Running Tomcat on Privileged Ports
Tags: linux, security, sysadmin, tomcat
Published: 2022-06-06 20:11:12

---
title: Running Tomcat on Privileged Ports
published: true
description: How to configure Tomcat to listen on port 80 or 443 on Linux
tags: linux, security, sysadmin, tomcat
---

By default, Tomcat listens on port 8080 for HTTP and 8443 for HTTPS. If you want Tomcat to listen on the standard HTTP (80) and HTTPS (443) ports, it’s not easy, because ports below 1024 are considered privileged ports on Linux and only available to processes running as root. It’s a very (very!) bad idea to run Tomcat as root.

## Reverse Proxy

You can configure a reverse proxy or load balancer like HAProxy to proxy port 443 to 8443.

1. Install HAProxy (`sudo yum install haproxy` on Red Hat-derived distros and `sudo apt install haproxy` on Debian-derived distros).

2. Start HAProxy and configure it to restart at boot.

    ```console
    $ sudo systemctl start haproxy
    $ sudo systemctl enable haproxy
    ```

3. Edit `/etc/haproxy/haproxy.cfg` and add:

    ```config
    # Enable Access on 443 (SSL Passthrough)
    frontend tomcat-proxy
        mode            tcp
        bind            :443
        timeout client  5s
        default_backend tomcat

    backend tomcat
        mode            tcp
        timeout connect 5s
        timeout server  5s
        server          tomcat server.example.com:8443
    ```

4. Modify the Tomcat `server.xml` and add `proxyPort=443` to the `<Connector>`. The `proxyPort` attribute is used when Tomcat is run behind a proxy server. This attribute modifies the value returned to web applications that call the `request.getServerPort()` method, which is often used to construct absolute URLs for redirects. Without configuring this attribute, the value returned would reflect the port on which the connection from the proxy server was received, rather than the port to whom the client directed the original request. See [Proxy Support](https://tomcat.apache.org/tomcat-9.0-doc/config/http.html#Proxy_Support) in the Tomcat documentation for more info.

## Authbind

The authbind utility allows a program that would normally require superuser privileges to access privileged ports to run as a non-privileged user. It allows a system administrator to permit specific users and groups access to bind to TCP and UDP ports below 1024.

1. Install authbind. On Debian-derived distros, you can do this with `sudo apt install authbind`. It's not available in the repos of Red Hat-derived distros, but there is a [pre-rolled RPM](https://aaronsilber.me/2016/04/24/install-authbind-on-centos-7-x86_64-download-the-rpm/) available. Download it and install with `sudo yum *.rpm`.

2. Authorize the non-privileged user to access port 443. If you installed Tomcat from your distro's repos, it is probably run by the *tomcat* user.

    ```console
    $ sudo touch /etc/authbind/byport/443
    $ sudo chmod 500 /etc/authbind/byport/443
    $ sudo chown tomcat /etc/authbind/byport/443
    ```

3. Modify the Tomcat `server.xml` and configure Tomcat to listen to port 443.

4. Prefix the command to start Tomcat with `/usr/bin/authbind --deep`. If you are using systemd to start Tomcat, your `ExecStart` would look something like this:

    ```
    ExecStart=/usr/bin/authbind --deep /opt/apache-tomcat-8.5.30/bin/startup.sh
    ```

    Normally authbind arranges for only the program which it directly invokes to be affected by its special version of `bind`. If you specify `--deep`, then all programs which that program invokes directly or indirectly will be affected, so long as they do not unset the environment variables set up by authbind.

## Jsvc

Jsvc is a set of libraries and applications for making Java applications run on Unix more easily. According to the [documentation](https://commons.apache.org/proper/commons-daemon/jsvc.html), "Jsvc allows the application (e.g. Tomcat) to perform some privileged operations as root (e.g. bind to a port < 1024), and then switch identity to a non-privileged user." I tried it but was never able to get it to work, and documentation and examples online seem sparse, so I abandoned it.