Running network services as a non-root user.
Posted by Steve on Wed 19 Apr 2006 at 07:48
There are many times when it is convenient to allow non-root users to run services, or daemons, which bind to "privileged ports". There are several approaches to this problem each with its own set of pros and cons. Read on for a brief look at the most common approaches.
A common task is to allow a user to run a Webserver, or other process, which needs to listen upon a network socket which is privileged. Traditionally only the root user is allowed to bind() to a port with a number lower than 1024. There are many services which require root privileges specifically for binding to a low-numbered port, rather than anything else. Are you sure you trust them to drop privileges after setting up the listening socket..?
There are some kernel patches which will allow different security models to be used, these may allow local users who are members of a special group to bind to a low port - however using these patches is quite a lot of effort.
The simpler alternatives include the following:
- Using a firewall to redirect packets.
- Using authbind.
- Using sudo.
Essentially you'll tell your user to bind their server to a port which they do have permission to use - anything over 1024 should be fine. In our example we'll use tell our user to setup their webserver to use port 2080. then add the following iptables rule to our firewall script:# Redirect *:2080 -> *:80 iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to 2080
This rule will allow incoming connections to the standard HTTP port (80) to be seamlessly redirected to port 2080; the port the user is actually using.
If you're not using a firewall right now simply create the file /etc/network/if-up.d/firewall (make it executable) and give it the following contents:#!/bin/sh PATH=/sbin:/bin:/usr/sbin:/usr/bin # Flush any existing firewall rules we might have iptables -F iptables -t nat -F iptables -t mangle -F iptables -X # Perform the rewriting magic. iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to 2080
The authbind package is designed to allow users to bind servers upon a low-numbered port. The package may be easily installed upon Debian systems by executing:root@lappy:# apt-get install authbind .. ..
Once installed the software is configured via files located beneath /etc/authbind. There are three subdirectories:
The manpage to the authbind program explains how these subdirectories are used. But as a simple example we can allow the user skx to bind to port 80 by running the following commands:root@lappy:~# touch /etc/authbind/byport/80 root@lappy:~# chown skx:skx /etc/authbind/byport/80 root@lappy:~# chmod 755 /etc/authbind/byport/80
Here we have created a file with the name 80 (which is used to specify that the user may bind to port 80). This file is executable to the user skx - this is sufficient for the user to bind to port 80 - if they prefix their command with authbind.
For example the skx user could run something like the following:skx@lappy:~$ authbind nc -l -p 80 -e "/usr/bin/uptime"
(This listens for incoming connections on port 80 and sends the output of the uptime command to connecting clients. It is the simplest test of binding a socket I could think of! The netcat utility has been introduced previously.)
Using the sudo package it is possible to delegate privileges to local users in a controlled manner.
If you wish to allow a user to execute a daemon you might be able to simply grant them permission to execute the startup file for it. For example the following snippet from /etc/sudoers allows the user skx to restart the Apache2 server:# User alias specification User_Alias FULLTIMERS = skx # Cmnd alias specification Cmnd_Alias APACHE=/etc/init.d/apache2 # full time sysadmins can restart Apache: FULLTIMERS ALL = NOPASSWD: APACHE
However this solution does have a problem: Whilst the given user can start and stop the service they cannot edit the configuration file(s):skx@lappy:~$ sudo /etc/init.d/apache2 reload Reloading web server config...done.
To handle this case you could use a server-specific setting - such as adding the following to /etc/apache2/apache2.conf :Include /home/skx/apache2/server.conf
This may or may not cause even more problems. It really depends upon the server, and how liable you think they are to try to leverage their elevated privileges to a root compromise ...
sudo is an exellant utility in most regards, but this is a situation where I think it is less useful than usual.