Sign up ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems. It's 100% free, no registration required.

I need to allow an user (different from root) to run a server listening on port 80.

Is there any way to do this?

share|improve this question
This question is open to interpretation. I'm hoping that you mean "you have created a new system service that you (as root) would like to run in an unprivileged account for security reasons" (considered good practice) and not "I have a user that's asked if they can run their own web server on my system, how do I allow them access?" (considered rather poor practice) –  Ptolemy Apr 6 '11 at 19:36
or perhaps even more worryingly, "There's this system that I have partially hacked into, that I can crash the web service on, and I want to put up my own website in its place, so I can capture every ones user name and password, but I am being thwated by this secure port thing..." –  Ptolemy Apr 6 '11 at 19:39
@Ptolemy, the actual reason is: my machine is behind a firewall that blocks any port but the 80. I want to host a server (which doesn't drop privileges!), thus need to have it listening on port 80, but don't trust it to run as root (for obvious security reasons). I'm allowed to do this, if you care. –  peoro Apr 6 '11 at 22:30

7 Answers 7

up vote 20 down vote accepted

setcap 'cap_net_bind_service=+ep' /path/to/program

this will work for specific processes. But to allow a particular user to bind to ports below 1024 you will have to add him to sudoers.

Have a look at this discussion for more.

share|improve this answer

(Some of these methods have been mentioned in other answers; I'm giving several possible choices in rough order of preference.)

You can redirect the low port to a high port and listen on the high port.

iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-ports 1080

You can start your server as root and drop privileges after it's started listening on the privileged port. Preferably, rather than coding that yourself, start your server from a wrapper that does the job for you. If your server starts one instance per connection, start it from inetd (or a similar program such as xinetd). For inetd, use a line like this in /etc/inetd.conf:

http  stream  tcp  nowait  username:groupname  /path/to/server/executable  argv[0] argv[1]…

If your server listens in a single instance, start it from a program such as authbind. Either create an empty file /etc/authbind/byport/80 and make it executable to the user running the server; or create /etc/authbind/byuid/1234, where 1234 is the UID running the server, containing the line,80.

If your server executable is stored on a filesystem that supports capabilities, you can give it the cap_net_bind_service capability. Beware that capabilities are still relatively new and still have a few kinks.

setcap cap_net_bind_service=ep /path/to/server/executable
share|improve this answer
In every case I've had to deal with, the executable was a script that launched java or python. As a guy without 10 hours to spend on the fine points, your iptables solution covers it painlessly. –  srking Mar 22 '12 at 19:35

You could use netcat or xinetd or iptables port forwarding, or use apache as a front end proxy and run the process on a non-privileged port.

share|improve this answer

The short answer is that this is not possible by design.

The long answer is that in the open source worlds there are lots of people playing with the design and coming up with alternate methods. In general it is widely accepted practice that this should not be possible. The fact that you are trying probably means you have another design fault in your system and should reconsider your whole system architecture in light of *nix best practices and security implications.

That said, one program for authorizing non-root access to low ports is authbind. Both selinux and grsecurity also provide frameworks for such fine tuned authentications.

Lastly, if you want specific users to run specific programs as root and what you really need is just to allow a user to restart apache or something like that, sudo is your friend!

share|improve this answer
Port "security" doesn't really give you very much in the modern world. –  pjc50 Apr 6 '11 at 16:47
@pjc50: Yes it does. It's about implied trust. Low port numbers imply high trust. SSH, POP, FTP and other daemons are expected to ask for system level passwords and other credentials when their ports are opened. If users were allowed to listen on low ports on a box, they could start phony daemons on unused (or crashed) ports and harvest passwords from unsuspecting users. Those passwords could then be used on that box to compromise other accounts, including root. –  Caleb Apr 7 '11 at 12:40
That's a pretty weak form of security. If you've connected to something and not done a certificate transaction then you have no idea of who you're talking to - ie MITM attacks. –  pjc50 Jun 13 '11 at 12:57
@pjc50: I'd be perfectly happy if you convinced the world that unauthenticated SMTP is a BadIdea™ along with every other protocol parading itself in the < 1024 port range with no security other than the assumption that the box is clean. Knock yourself out. –  Caleb Jun 13 '11 at 13:03
I suppose what's needed is chown for ports: then you could "chown mail port25" then (a) your mail daemon doesn't need to be started with root privs and (b) nobody else can hijack it. –  pjc50 Jun 13 '11 at 13:07

what about starting the program as root, bind the port, then drop privileges?

share|improve this answer
It is considered inappropriate to post an answer with so little information. Please expand, explain, illustrate your answer. –  Dominykas Mostauskis Aug 28 '14 at 17:05

Authbind, @Gilles already mentioned it, but I'd like to expand on it a bit.

It has convenient access control (details in man page): you can filter access by port, interface address, uid, ranges of address or port and combination of these.

It has very useful parameter --depth:

--depth levels

Causes authbind to affect programs which are levels deep in the calling graph. The default is 1.

"Levels deep" means when a script (or program), runs another script it descends a level. So if you have --depth 5 it means on levels 1 (or is it 0?) through 5 you have permission to bind, whereas on level 6 and on, you don't. Useful when you want a script to have access, but not programs that it runs with or without your knowledge.

To illustrate, you could have something like this: for sake of security, you have a user java that is meant to only run java and you want to give him access to port 80:

sudo echo > /etc/authbind/byport/80 &&
chown root:java /etc/authbind/byport/80
chmod 710 /etc/authbind/byport/80

I've created the ../byport/80 file, given it to java users group (each user has it's own group), and made it executable by group, which means it's executable by java user. If you're giving access by port, the file has to be executable by the user that should have access, so we did that.

This might be enough for the average Joe, but because you know how to use the --depth parameter, you run (as java user) authbind --depth [depth] my_web_app's_start_script starting at --depth 1 and working your way up until you find the smallest depth that works and use that.

Read the man page for details.

share|improve this answer

I tried the iptables PREROUTING REDIRECT method, but found that it also affects forwarded packets. That is, if the machine is also forwarding packets between interfaces (e.g. if it's acting as a Wi-Fi access point connected to an Ethernet network), then the iptables rule will also catch connected clients' connections to Internet destinations, and redirect them to the machine. That's not what I wanted—I only wanted to redirect connections that were directed to the machine itself.

One possibility is to use TCP port forwarding. E.g. using socat:

socat TCP4-LISTEN:www,reuseaddr,fork TCP4:localhost:8080

However one disadvantage with that method is, the application that is listening on port 8080 then doesn't know the source address of incoming connections (e.g. for logging or other identification purposes).

share|improve this answer

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.