Dashboard > Jetty > ... > Connectors > port80
port80 Log In | Sign Up   View a printable version of the current page.

Added by Greg Wilkins , last edited by Dexter Ang on Feb 19, 2008  (view change)
Labels: 
(None)

Contact the core Jetty developers at www.webtide.com
private support for your internal/customer projects ... custom extensions and distributions ... versioned snapshots for indefinite support ... scalability guidance for your apps and Ajax/Comet projects ... development services from 1 day to full product delivery

How do I use port 80 as a non root user?

On Unix based systems, port 80 is protected and can only be opened by
the superuser root. As it is not desirable to run the server as root (for
security reasons), the solution options are as follows

  • Start Jetty as the root user, and use Jetty's setuid mechanism to switch to a non-root user after startup.
    or
  • Configure the server to run as a normal user on port 8080 (or some other non protected port).Then, configure the operating system to redirect port 80 to 8080 using ipchains, iptables, ipfw or a similar mechanism.

The latter has traditionally been the solution, however Jetty 6.1 has added the new setuid feature.

Using Jetty's setuid (and setumask) feature

Create a jetty config file like so:

<?xml version="1.0"?>
<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "http://jetty.mortbay.org/configure.dtd">
<Configure id="Server" class="org.mortbay.setuid.SetUIDServer">
  <Set name="umask">UMASK</Set>
  <Set name="uid">USERID</Set>
</Configure>

Where you replace:

  • UMASK with the umask setting you want the process to have, or optionally remove this line if you don't want to change this at runtime
  • USERID with the id of the user you want the process to execute as once the ports have been opened.
    Hint

    For your convenience, you'll find one of these ready made in the $jetty.home/extras/setuid/etc/jetty-setuid.xml.

    Then, you need to build the setuid feature for your operating system, as it requires native libraries. Go to the $jetty.home/extras/setuid directory and follow the instructions in the README.txt file, summarized here as:

    > mvn install
    
    > gcc -I$JDK_HOME/include/ -I$JDK_HOME/include/linux/  \
         -shared src/main/native/org_mortbay_setuid_SetUID.c \
         -o ../../lib/ext/libsetuid.so
    
    > cp target/jetty-setuid-6.1-SNAPSHOT.jar ../../lib/ext/
    > cp etc/jetty-setuid.xml ../../etc

    Where:

  • $JDK_HOME is same as $JAVA_HOME
  • linux should be replaced by the name of your operating system.
    On Solaris

    Leave out the -shared argument.

    Then to run jetty as the root user, switching to the userid of your choice (and setting the umask of your choice if you chose to do that) you do:

    sudo java -Djava.library.path=lib/ext -jar start.jar etc/jetty-setuid.xml etc/jetty.xml
    Note!

    You must ensure that the etc/jetty-setuid.xml file is first in the list of config files.

Using ipchains

On some Linux systems the ipchains REDIRECT mechanism can be used to redirect from one port to another inside the kernel:

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

This basically means, "Insert into the kernel's packet filtering the following as the first rule to check on incoming packets: If the protocol is TCP and the destination port is 80, redirect the packet to port 8080." Your kernel must be compiled with support for ipchains. (virtually all stock kernels are.) You must have the "ipchains" command-line utility installed. (On RedHat the package is aptly named "ipchains".) You can run this command at any time, preferably just once since it inserts another copy of the rule every time you run it.

Once this rule is set up, a Linux 2.2 kernel will redirect all data addressed to port 80 to a server such as Jetty running on port 8080.This includes all RedHat 6.x distros. Linux 2.4 kernels, e.g. RedHat 7.1+, have a similar "iptables" facility.

Using iptables

You need to add something like the following to the startup scripts or your firewall rules:

/sbin/iptables -t nat -I PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 8080

The underlying model of iptables is different to that of ipchains so the forwarding normally only happens to packets originating off-box. You will also need to allow incoming packets to port 8080 if you use iptables as a local firewall.

Be careful to place rules like this one early in your "input" chain. Such rules must precede any rule that would accept the packet, otherwise the redirection won't occur. You can insert as many rules as needed if your server needs to listen on multiple ports, as for HTTPS.

Using usermod

On Solaris 10 (maybe earlier versions too) the OS allows you to grant privileged ports binding to "normal" users:

usermod -K defaultpriv=basic,net_privaddr myself

Now the myself user will be able to bind to port 80.

On Solaris, the option -shared, could led to the following error:

Text relocation remains                         referenced
    against symbol                  offset      in file
setuid                              0xd         /var/tmp//cc8s3iAX.o
umask                               0x1d        /var/tmp//cc8s3iAX.o
umask                               0x26        /var/tmp//cc8s3iAX.o
ld: fatal: relocations remain against allocatable but non-writable sections
collect2: ld returned 1 exit status

Just remove that option and the library will be compiled.

Thanks Claudio, I've updated the wiki instructions with this.

I tried compiling libsetuid.so with your compiling command, but got a linking error, with 'main' being an undefined symbol.  The solution is to add a -c to the command!

One other thing: in the example, it says that you want etc/jetty-setuid.xml to be first--but when i tried that, i got permission denied errors.  When i put it AFTER jetty.xml, everything as fine.

Normally the command-line arguments to Jetty are the names of xml files that create Server instances. The jetty-setuid.xml file creates a subclass of Server: org.mortbay.setuid.SetUIDServer. Assuming none of the Servers do anything strange, like starting themselves, Jetty starts Servers in the order they are passed to it on the command line. The SetUIDServer class doesn't actually modify the UID until it starts.

Therefore, if you have a jetty.xml that creates a Server that must start as root because it listens on port 80, then you will want to list it before jetty-setuid.xml on the command line.

By the way, in addition to being able to listen on port 80, running Jetty initially as root is also useful for reading in property files containing keys and passwords, since then you can make the files only readable by root.

Another way to have Jetty open port 80 but then change users would be to use commons-daemon (http://jakarta.apache.org/commons/daemon/). Commons-daemon is what Tomcat uses to run as a daemon. To use it with Jetty, you would probably write a small application that embeds your Jetty server, and your application would implement the org.apache.commons.daemon.Daemon interface, which has init() and start() methods. Commons-daemon calls init() with superuser privileges, and then start() with the downgraded privileges. Since Jetty's Server.start() requires superuser privileges to open port 80 (I think), you would call it from your init() method. (This is not ideal, since the Server starts accepting connections while still running as superuser, but I think that's a problem even with Jetty's "setuid" feature.) Commons-daemon includes an init script that can be used in an "init.d"-style directory.

There are some advantages to using commons-daemon instead of the new "setuid" feature:

  • It can be used with any version of Jetty
  • It lets you keep your container pure java (commons-daemon has a native component, but it calls Jetty..not the other way around)
  • You don't have to worry about the order that Jetty loads config files
  • Commons-daemon will restart Jetty if it crashes (I don't know if that happens in the real world)

The main disadvantage is that you would have to write a (small) wrapper application. Perhaps someday Jetty will come with such a wrapper.

When using this feature, some JVM instrumentation like jps, jstat will not work, I found this unresolved bug

# ./java -version
java version "1.6.0_02"
Java(TM) SE Runtime Environment (build 1.6.0_02-b05)
Java HotSpot(TM) Server VM (build 1.6.0_02-b05, mixed mode)
# ps -ef|grep java
webservd   555   916   0 01:49:26 pts/1       1:08 /opt/jdk1.6.0_02/bin/java -Xmx96m -Djava.library.path=lib/ext -Dfile.encoding=U
    root  6032   670   0 02:50:09 pts/1       0:00 grep java
# id
uid=0(root) gid=0(root)
# ./jps -l
6034 sun.tools.jps.Jps
555 -- process information unavailable
Contact the core Jetty developers at www.webtide.com
private support for your internal/customer projects ... custom extensions and distributions ... versioned snapshots for indefinite support ... scalability guidance for your apps and Ajax/Comet projects ... development services from 1 day to full product delivery
Site running on a free Atlassian Confluence Open Source Project License granted to The Codehaus. Evaluate Confluence today.
Powered by Atlassian Confluence, the Enterprise Wiki. (Version: 2.6.2 Build:#919 Nov 26, 2007) - Bug/feature request - Contact Administrators