Server Fault is a question and answer site for system and network administrators. It's 100% free, no registration required.

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I have googled about it for quite some time, but couldn't find it.

I am on Ubuntu Linux and want to run a server on port 80, but due to security mechanism of Ubuntu, I get the following error: Permission denied:80

I think it should be simple enough to either disable this security mechanism so that port 80 is available to all users, or to give necessary privilege to the current user to access port 80; but shame on me, can't figure that out.

share|improve this question

migrated from Feb 14 '10 at 20:47

This question came from our site for professional and enthusiast programmers.

What is the problem to run the server on another port that is unprivileged? You are thinking about something as harsh as disabling the security mechanism without providing at least a very serious reason for running a server on that port. Is the server hardcoded to bind to port 80? If so, throw it away. – Anonymous Feb 20 '10 at 17:00
Or a Python error message: socket.error: [Errno 13] Permission denied – Kazark Nov 15 '11 at 15:15
possible duplicate of Regular user using ports below 1024 – Roman Jul 7 '13 at 13:19
You can't. Ports below 1024 are privileged and only root can open listening sockets on them. The appropriate thing to do is to drop permissions after opening it. – Falcon Momot Jul 7 '13 at 17:38
"Anonymous" - the users in the world have been trained to look for certain services at certain ports. In some instances, its been standardized. For example, HTTP on port 80 and HTTPS on port 443. Its kind of hard to change the users and standards of the world. – jww Feb 2 '14 at 9:25

20 Answers 20

Short answer: you can't. Ports below 1024 can be opened only by root.

The long answer: you can redirect connections on port 80 to some other port you can open as normal user.

Run as root:

# iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 8080

As loopback devices (like localhost) do not use the prerouting rules, if you need to use localhost, etc., add this rule as well (thanks @Francesco):

# iptables -t nat -I OUTPUT -p tcp -d --dport 80 -j REDIRECT --to-ports 8080

NOTE: The above solution is not well suited for multi-user systems, as any user can open port 8080 (or any other high port you decide to use), thus intercepting the traffic. (Credits to CesarB).

EDIT: as per comment question - to delete the above rule:

# iptables -t nat --line-numbers -n -L

This will output something like:

num  target     prot opt source               destination         
1    REDIRECT   tcp  --             tcp dpt:8080 redir ports 8088
2    REDIRECT   tcp  --             tcp dpt:80 redir ports 8080

The rule you are interested in is nr. 2, so to delete it:

# iptables -t nat -D PREROUTING 2
share|improve this answer
@Sunny: upvotes are not for the fastest gun in the west, but for the best responses. Yours is the best so far (I only mentioned iptables; you actually provided the full command line). The only thing mine has yours doesn't is the caveat about other users also being able to bind to port 8080. – CesarB Nov 10 '08 at 14:45
Note that this doesn't work with IPv6. – Emmanuel Bourg Apr 2 '12 at 12:12
Could anybody explain how I can remove this rule later when I want to? After running it, it works, but it's apparently not a "rule" because it doesn't show up when i do sudo iptables --list. I know what iptables is and does, but i've never really used it before this. – Encoderer Apr 2 '12 at 18:31
Thanks for your answer... whenever I reboot Ubuntu, this rule disappears and I have to run it again. Is there a way to save it forever? – Coderji Sep 18 '14 at 8:16
@Coderji: check the "save" section in the community documentation: – Sunny Sep 18 '14 at 12:54

Use authbind.

It even works with Java if you enable Java's IPv4-only stack. I use:

authbind --deep $JAVA_HOME/bin/java …
share|improve this answer
thanks for this! – jldupont Oct 9 '09 at 15:02
If the server is Tomcat you can use authbind automatically by setting AUTHBIND=yes in /etc/default/tomcat6 – Emmanuel Bourg Apr 2 '12 at 12:16
I couldn't get this to work on Ubuntu server with the default Java package... – Ashley Steel Jun 20 '12 at 17:17
Me neither, any known solution? – mark Aug 16 '12 at 10:10
Note that you must configure authbind to actually allow this to happen. From the man page: "/etc/authbind/byport/port is tested. If this file is accessible for execution to the calling user, according to access(2), then binding to the port is authorised.", e.g. for port 80, sudo touch /etc/authbind/byport/80 ; sudo chmod 777 /etc/authbind/byport/80. The initial install of authbind does not generally have any pre-configured authorizations. – Jason C Mar 21 '15 at 20:57

Traditionally on Unix, only root can bind to low ports (<1024).

The simplest way to work around this is to run your server on a high port (for instance, 8080) and use a simple iptables rule to forward the connections from port 80 to port 8080. Note that with this you lose the extra protection from the low ports; any user on your machine can bind to port 8080.

share|improve this answer

Approach proposed by Sunny and CesarB:

iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 8080

works fine but it has a small drawback -- it does not prevent user from connecting directly to port 8080 instead of 80.

Consider the following scenario when this can be a problem.

Let's say we have a server which accepts HTTP connections on port 8080 and HTTPS connections on port 8181.

We use iptables to establish the following redirections:

80  ---> 8080
443 ---> 8181

Now, let's suppose our server decides to redirect user from a HTTP page to a HTTPS page. Unless we carefully rewrite the response, it would redirect to https://host:8181/. At this point, we are screwed:

  • Some users would bookmark the https://host:8181/ URL and we would need to maintain this URL to avoid breaking their bookmarks.
  • Other users would not be able to connect because their proxy servers do not support non-standard SSL ports.

I use the following approach:

iptables -t mangle -A PREROUTING -p tcp --dport 80 -j MARK --set-mark 1
iptables -t mangle -A PREROUTING -p tcp --dport 443 -j MARK --set-mark 1
iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 8080
iptables -t nat -A PREROUTING -p tcp --dport 443 -j REDIRECT --to-port 8181
iptables -I INPUT -m state --state NEW -m tcp -p tcp --dport 8080 -m mark --mark 1 -j ACCEPT
iptables -I INPUT -m state --state NEW -m tcp -p tcp --dport 8181 -m mark --mark 1 -j ACCEPT

Combined with default REJECT rule on the INPUT chain this approach prevents users from connecting directly to ports 8080, 8181

share|improve this answer
This is good, but why not just bind the daemon to localhost:8080 instead of ? I want to do that, but I need the iptables for that. – Amala Dec 15 '11 at 17:20
It works, really cool. – xtian Oct 8 '15 at 20:26

Another solution is to make your app setuid so that it can bind with port 80. As root, do the following

chown root ./myapp
chmod +S ./myapp

Keep in mind that doing this, unless it's done absolutely right, will expose you to potential security holes, because your app will be talking to the network, and will be running with full root priviledges. If you take this solution, you should look at the source code for Apache or Lighttpd or something similar, where they use the root privileges to open up the port, but then immediately give up those privs and "become" a lower privileged user so that a hijacker can't take over your whole computer.

Update: As seen in this question, it appears that Linux kernels since 2.6.24 have a new capability that allow you to mark an executable (but not a script, of course) as having the "CAP_NET_BIND_SERVICE" capability. If you install the debian package "libcap2-bin", you can do that by issuing the command

setcap 'cap_net_bind_service=+ep' /path/to/program
share|improve this answer
That is the same as running as root, unless the app knows how to drop priviledges. – CesarB Nov 10 '08 at 14:48
This is dangerous. This means that any request will run as root. It's for a reason that even apache starts as root to bind, and then drops the privileges to another user. – Sunny Nov 10 '08 at 14:49
Subverting the restrictions Unix has on binding to port 80 is dangerous, whether you do it with setuid or with iptables hackery. – Paul Tomblin Nov 10 '08 at 14:53
Paul: the iptables is not so dangerous, because even if the app is compromised, it will not expose the system on attacks, at least not with root privileges. Running the app as root is another story. – Sunny Nov 10 '08 at 14:55
lol, love how the accepted answer has a -15 – Evan Teran Dec 17 '08 at 18:53

If your system supports it you could maybe use capabilities. See man capabilities, the one you need would be CAP_NET_BIND_SERVICE. No, I`ve never used them myself and I don't know if they really work :-)

share|improve this answer
they do work, I use CAP_NET_RAW to run tools like tcpdump as a normal user. – Justin Feb 15 '10 at 0:32

I simply use Nginx in front. It can run on localhost too.

  • apt-get install nginx

.. or ..

  • pkg_add -r nginx

.. or what ever suits your OS.

All you need in nginx.conf, if running on localhost, is:

server {
        listen  80;
        location / {
            proxy_set_header    Host $host;
            proxy_set_header    X-Real-IP   $remote_addr;
            proxy_set_header    X-Forwarded-For $proxy_add_x_forwarded_for;
share|improve this answer
I really like this solution. – thomasfedb Dec 6 '12 at 16:05
This is (one of) the suggested solution from JFrog themselves: – stolsvik Jan 1 '14 at 23:27

If your system supports it you could maybe use capabilities. See man capabilities, the one you need would be CAP_NET_BIND_SERVICE.

On newer Debian/Ubuntu you can run:

sudo apt-get install libcap2-bin 
sudo setcap 'cap_net_bind_service=+ep' /path/to/program
share|improve this answer
this works for nodejs: setcap 'cap_net_bind_service=+ep' /usr/bin/nodejs – JasonS Jun 4 '15 at 22:20
This. I wonder why this answer hasn't more upvotes. Much easier than the iptables option imho. – Dominik R Jan 4 at 1:54

Use a reverse proxy (nginx, apache+mod_proxy) or a caching reverse proxy (Squid, Varnish) in front of your application servers!

With a reverse proxy you can achieve a lot of interesting things like:

  • Load-balancing
  • Restarting your application servers with users receiving a fancy error page
  • Speed up things with cache
  • Fine-grained settings that you normally do with a reverse-proxy and not with an application server
share|improve this answer

You can use redir program:

sudo redir --lport=80 --laddr= --cport 9990 --caddr=
share|improve this answer

Use sudo.

Configure sudo so that the regular user can run appropriate commands:

/etc/init.d/httpd start


apachectl stop


/usr/local/apache2/apachectl restart


/myapp/myappbin start

(Or whatever other command/script you use to start/stop you particular webserver/app)

share|improve this answer
This has the same issue -- running a service as root is a bad practice. – Kevin Panko Sep 9 '09 at 18:44

With Linux, you have some two other options:

Both extensions to the Linux kernel allow to grant access rights on a very fine grained level. This would allow you to grant this process to open port 80 but it wouldn't inherit any of the other root rights.

From what I've heard, grsecurity is much more simple to use but SELinux is more secure.

share|improve this answer

One solution is to use iptables to perform PAT on packets for port 80. You can use this to route the packets to local port 8080, for example. Be sure and adjust the outgoing packets back to port 80.

In my experience the fine-grained permissions features of Linux are not compiled into standard kernels because of security issues.

share|improve this answer

If you are trying to do this so that a user-run command can use port 80, then your only solutions are the iptables tricks or setting the executable setuid-to-root.

The way something like Apache does this (it binds to port 80, but is running as someone other than root) is to run as root, bind to the port, then change the ownership of the process to the non-privileged user after the port is set up. If the app you are writing can be run by root, you can make it change owner to the non-priv user after the ports are set up. But if this is just for an average user to run from the command line, then you'll have to use one of the other solutions.

share|improve this answer

When I have various web serving applications (python scripts, tomcat engines, ...) that I don't want to run as root I usually configure an apache web server in front of them. Apache listens to port 80, and tomcat listens to 8080.

In apache:s config:

ProxyPass /webapp http://localhost:8080/webapp
ProxyPassReverse /webapp http://localhost:8080/webapp

See the mod-proxy documentation for more info:

share|improve this answer
The drawback of this solution is the loss of the incoming IP in the Tomcat logs. – Emmanuel Bourg Apr 2 '12 at 12:22

I think the best solution is to sgid your app and as soon as it has its port bound it should drop the privileges by switching to another user.

share|improve this answer

answer of sunny is correct, but you may face additional issues as loopback interface don't use the PREROUTING table,

so the iptables rules to add are two:

iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 8080
iptables -t nat -I OUTPUT -p tcp -d --dport 80 -j REDIRECT --to-ports 8080
share|improve this answer

As an aside, FreeBSD and Solaris (anyone remember that one?) let you do this (bind to low ports) without privilege escalation (ie, using programs to switch to root). Since you specified Linux, I'm just posting this as a notice to others that might find this question.

share|improve this answer

Some hostsystems are not allowing to use the NAT module, 'iptables' does not solve the problem in this case.

How about xinetd?

In my case (ubuntu 10.04)

# apt-get install xinetd
# touch /etc/xinetd.d/my_redirect
# vim /etc/xinetd.d/my_redirect

Paste the configuration:

service my_redirector_80
 disable = no
 socket_type = stream
 protocol = tcp
 user = root
 wait = no
 port = 80
 redirect = localhost 8080
 type = UNLISTED


# service xinetd restart explains better.

share|improve this answer
This is basically equivalent to putting a reverse proxy in front of the server, but it's rather inefficient compared to dedicated solutions like HAproxy, Pound or Varnish that understand the HTTP protocol and can add useful headers likes X-Forwarded-For. – Emmanuel Bourg Apr 2 '12 at 21:49


Simple. With a normal or old kernel, you don't.
As pointed out by others, iptables can forward a port.
As also pointed out by others, CAP_NET_BIND_SERVICE can also do the job.
Of course CAP_NET_BIND_SERVICE will fail if you launch your program from a script, unless you set the cap on the shell interpreter, which is pointless, you could just as well run your service as root...
e.g. for Java, you have to apply it to the JAVA JVM

sudo /sbin/setcap 'cap_net_bind_service=ep' /usr/lib/jvm/java-8-openjdk/jre/bin/java

Obviously, that then means any Java program can bind system ports.
Dito for mono/.NET.

I'm also pretty sure xinetd isn't the best of ideas.
But since both methods are hacks, why not just lift the limit by lifting the restriction ?
Nobody said you have to run a normal kernel, so you can just run your own.

You just download the source for the latest kernel (or the same you currently have). Afterwards, you go to:


There you look for this line

/* Sockets 0-1023 can't be bound to unless you are superuser */
#define PROT_SOCK       1024

and change it to

#define PROT_SOCK 0

if you don't want to have an insecure ssh situation, you alter it to this: #define PROT_SOCK 24

Generally, I'd use the lowest setting that you need, e.g 79 for http, or 24 when using SMTP on port 25.

That's already all.
Compile the kernel, and install it.
Finished - that stupid limit is GONE, and that also works for scripts.

Here's how you compile a kernel:

# You can get the kernel-source via package linux-source, no manual download required
apt-get install linux-source fakeroot

mkdir ~/src
cd ~/src
tar xjvf /usr/src/linux-source-<version>.tar.bz2
cd linux-source-<version>

# Apply the changes to PROT_SOCK define in /include/net/sock.h

# Copy the kernel config file you are currently using
cp -vi /boot/config-`uname -r` .config

# Install ncurses libary, if you want to run menuconfig
apt-get install libncurses5 libncurses5-dev

# Run menuconfig (optional)
make menuconfig

# Define the number of threads you wanna use when compiling (should be <number CPU cores> - 1), e.g. for quad-core
# Now compile the custom kernel
fakeroot make-kpkg --initrd --append-to-version=custom kernel-image kernel-headers

# And wait a long long time

cd ..

In a nutshell, use iptables if you want to stay secure, compile the kernel if you want to be sure this restriction never bothers you again.

share|improve this answer
Would somebody please explain the downvotes ? Kernel-compilation not working ? Or is it just because afterwards, you can't do a kernel-upgrade from the normal repositories anymore ? – Quandary Sep 1 '15 at 9:35

protected by Chris S Jan 2 '14 at 4:46

Thank you for your interest in this question. Because it has attracted low-quality or spam answers that had to be removed, posting an answer now requires 10 reputation on this site.

Would you like to answer one of these unanswered questions instead?

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