This site is now 100% read-only, and retired.

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.
Using a firewall to redirect packets

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:



# 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
Using authbind

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:

  • /etc/authbind/byport
  • /etc/authbind/byuid
  • /etc/authbind/byaddr

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 sudo

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:

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.



Re: Running network services as a non-root user.
Posted by chris (217.8.xx.xx) on Wed 19 Apr 2006 at 12:38
[ View Weblogs ]
I can't see that the problem with sudo is solved easily for the other two. With authbind and firewall you still can't edit the config files?

Of course - with those two you can have a local install of the app in your home directory - but you could have that with sudo too.

[ Parent ]

Re: Running network services as a non-root user.
Posted by Steve (212.20.xx.xx) on Wed 19 Apr 2006 at 12:41
[ View Weblogs ]

The assumption is that if you're using sudo you're giving control of the system installation of a service - such as Apache.

Whereas if you're using an authbind, or iptables, solution it is more natural to have a local copy the user has in their own home directory - since they still need to edit configuration files, etc.

I guess you could use any solution in either approach though. That is just the way I was thinking about it.


[ Parent ]

Re: Running network services as a non-root user.
Posted by simonw (84.45.xx.xx) on Wed 19 Apr 2006 at 21:36
[ View Weblogs ]

perhaps you can answer a question I've long had, "why don't we fix the kernel for this?".

I've read the relevant code, it basically says "if port less than 1024 then check calling process uid is 0", and it would appear simple to me to change the check such that the calling process has the same uid as a user defined in "/etc/service_owner".


Then there would be no need for a root privilege to bind to ports below 1024, and great swathes of weird solutions, and whole classes of root exploit would "just die".

This always struck me as application programmers working around a broken design, but maybe I'm being naive?

[ Parent ]

Re: Running network services as a non-root user.
Posted by Anonymous (65.211.xx.xx) on Fri 21 Apr 2006 at 16:21
I've never used it but it looks like this patch could do that job.

It creates a virtual fs to represent ports which you then chown to whatever user you want to be able to bind the port. I wish I had a spare machine lying around right now to try it on.

[ Parent ]

Re: Running network services as a non-root user.
Posted by Anonymous (193.62.xx.xx) on Fri 12 Dec 2008 at 16:39
"allows the user skx to restart the Apache2 server"

Looks like it's the user "steve".

[ Parent ]

Re: Running network services as a non-root user.
Posted by Steve (89.16.xx.xx) on Fri 12 Dec 2008 at 16:41
[ View Weblogs ]

Good catch. I've updated it now.


[ Parent ]

Re: Running network services as a non-root user.
Posted by Xan (2001:0xx:0xx:0xxx:0xxx:0xxx:xx) on Fri 19 Feb 2010 at 07:16
Don't the file permissions in your authbind example give everybody the ability to bind to the port? Shouldn't they be, for example, 750 rather than 755?

[ Parent ]

Re: Running network services as a non-root user.
Posted by Anonymous (217.72.xx.xx) on Mon 8 Aug 2011 at 12:57
If you want to redirect packages locally, add this line too:

iptables -t nat -A OUTPUT -p tcp -d --dport 80 -j REDIRECT --to-port 2080

The OUTPUT chain checks for locally created packages.

[ Parent ]