Sunday, March 28, 2010

Binding to port 80 without running as root

I've been looking for a way to allow server programs like Apache httpd, memcached, Couchdb, Qpid etc to bind to privileged IP ports under 1024 like 80 or 443 for example, without running them as the root user. Normally, on Linux you need to run as root to be allowed to bind to these standard privileged ports

I don't like to run anything as root on a server as it makes it vulnerable to security holes in untrusted application code... and stupid mistakes. Has anybody ever completely messed up a server with a stupid mistake like rm -rf of the wrong directory? :)

To mitigate the risks you can run as root in chroot jails, but placing everything you need in a chroot jail and communicating with what's running in the jail quickly gets complicated.
Apache httpd has built-in support for dropping root privileges after binding to a privileged IP port, to run untrusted application code as a normal user (see the User configuration directive.) I don't like that either as the httpd parent process still runs as root. Also, some of the log files are still created under root and I have to become root again to process them (if running with a tight 0007 umask) or relax the file permissions and make them visible to other users on the server.

So, I've been trying to run a tight compartmentalized ship and run most server programs under normal user accounts. That makes it really easy to maintain isolated sandboxes with different configurations of programs, replicate them across machines, control resource consumption with user quotas, run scripts to monitor each sandbox activity, setup emergency procedures to shutdown everything running in a particular sandbox, etc.

... Then I found privbind!

Privbind is a nice little utility that allows a program to bind to privileged IP ports without running as root. With privbind I'm now able to run all my server programs as regular users, and still bind them to privileged IP ports.

Here's how to use it to start Apache httpd: sudo privbind -u foo apachectl -k start
That runs Apache httpd under user foo, but still allows it to bind to privileged port 80.

More info on how privbind works can be found in the privbind Manual.

P.S. An alternative is to bind the server programs to non-standard unprivileged ports (8080 instead of 80 for HTTP for example.) and use an iptables firewall configuration to forward the IP traffic from port 80 to port 8080. I'll talk more about that in another post...

No comments:

The postings on this site are my own and don’t necessarily represent positions, strategies or opinions of my employer IBM.