Saturday, June 22, 2013



One of my projects uses a self hosted executable that is accepting incoming connections on port 80. The package has an embedded Jetty so I didn't need to deal with any low level TCP stuff. That is the good part. The bad part is that it turned out that the hosting environment (Ubuntu linux) for security reasons by default does not allow a non-root user to use any TCP port below 1024 - so the first free for all port is 1024.
                                                                                                                         
One easy solution would be to set up Nginx and forward the traffic it receives on port 80 to my self hosted app on a different port. Quite easy to set up but why waste a network hop when I didn't really need any feature Nginx could offer?
                                                                                                                         
Installing authbind

Luckily I'm not the only one with this kind of issue out there. In fact, authbind was released in 1998. To install, I simply did an apt-get install authbind and that's about it. The configuration is a bit trickier as we need to create a file in /etc/authbind/byport directory by the user who wants to access the specific port. So, in my case I needed a file called 80 owned by the user who is allowed to access that port.

Convincing Java to play nice with authbind

After creating the file we can test it right away whether we have permission to open that port. Simply using netcat: authbind nc -l 80 should not throw an error. So far, so good. Unfortunately by default Java will try IPv6 so it won't be able to use this port (authbind is IPv4 only). The only easy solution is to force Java to use IPv4 stack instead of v6:
                                               
authbind --deep /usr/bin/java -Djava.net.preferIPv4Stack=true -jar mypack.jar       
                                                                                 
(The --deep option allows any child process to inherit the permission for the port)

Another solution - iptables

Some people dislike setting up iptables on production as it can cause really funky errors and if done remotely it's quite easy to lock out ourselves from the machine. However, iptables can forward traffic from any port to any other port simply using:

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

Again, it's a bit hard-wired solution, so probably setting up Nginx to forward the traffic is a bit more user friendly setup.

No comments:

Post a Comment