Thursday, 22 October 2015

Running Glassfish on port 80

Well, in short. Linux does not allow non-root programs to listen/occupy ports below 1024. It is a security feature.

So what can I do to make a server that is non-root (because of security) able to receive/send messages through a privileged port? Luckily the question has already been asked multiple times on the Internet.

To summarize:
  • Run the program as root anyway
  • Have a root daemon run the program as root, then change the rootrights automatically to something less
  • Kernel param CAP_NET_BIND_SERVICE
  • Run a proxy server in front of it
  • Software that performs what you want
  • Port-forwarding using IPTables

For the matter of this blog, I am going to assume that I wish to make my Glassfish instance available via both port 80 (the default web port) and port 443 (the default ssl web port). For that is the use case I was faced with.

Run the program as root anyway

Well, that should work, but is a huge security risk in most cases.

We would just need to change the ports of the HTTP Listeners in Glassfish administration console. It can be found in the default-config option.

Have a root daemon run the program as root, then change the rootrights automatically to something less

This seems to be one of the functions of the inetd daemon.


sudo setcap cap_net_bind_service=ep some-binary
In Linux, the things root can do have been broken up into a set of capabilities. CAP_NET_BIND_SERVICE is the ability to bind to ports <= 1024.

Unfortunately, we would need to set the binary to "java". This automatically means that any java program will have the ability to access any ports. This is not what we want.

Run a proxy server in front of it

That's what I did initially. There are lots of web servers that are perfectly capable of redirecting traffic to another port. For example the Apache HTTP server and Nginx. I choose Nginx, as it seems to be quite easy to setup and doesn't come with a lot of extras, extras I do not need.

The excellent part of this solution is that we can use Nginx to serve static webpages/images/files and not bother the Glassfish with it.

Tricky is that I need the original originating IP address of the client, and that is lost without some magic configuration.

The bad part is that a proxy server is another link in the chain that needs to be supported and maintained etc.

Software that performs what you want

For example authbind seems mentioned a lot.

Port-forwarding using IPTables

This is the solution I went for eventually.
iptables -t nat -A PREROUTING -p tcp -m tcp --dport 80 -j REDIRECT --to-ports 8080
iptables -t nat -A PREROUTING -p udp -m udp --dport 80 -j REDIRECT --to-ports 8080 

# Do the same thing for ssl:
iptables -t nat -A PREROUTING -p tcp -m tcp --dport 443 -j REDIRECT --to-ports 8181
iptables -t nat -A PREROUTING -p udp -m udp --dport 443 -j REDIRECT --to-ports 8181
Removing all the rules can be done with:
echo "Stopping firewall and allowing everyone..."

iptables -F

iptables -X
iptables -t nat -F
iptables -t nat -X
iptables -t mangle -F
iptables -t mangle -X
iptables -P INPUT ACCEPT
To save the configuration, you can use iptables-save and iptables-restore. Or try something like:
]# service iptables save
iptables: Saving firewall rules to /etc/sysconfig/iptables:[ OK ]


StackOverflow - Is there a way for non-root processes to bind to “privileged” ports (<1024) on Linux?
Debian Administration - Running network services as a non-root user
Ubuntu Help - Iptables HowTo
Oracle Blogs - Byron's Pointless Ramblings - Run GlassFish V3 as a non-root Service on Linux Ubuntu/Debian
The JavaDude Weblog - Glassfish and https running secure applications

No comments:

Post a Comment