Allow non-root process to bind to port 80 and 443?
Is it possible to tune a kernel parameter to allow a userland program to bind to port 80 and 443?
The reason I ask is I think its foolish to allow a privileged process to open a socket and listen. Anything that opens a socket and listens is high risk, and high risk applications should not be running as root.
I'd much rather try to figure out what unprivileged process is listening on port 80 rather than trying to remove malware that burrowed in with root privileges.
I'm not sure what the other answers and comments here are referring to. This is possible rather easily. There are two options, both which allow access to low-numbered ports without having to elevate the process to root:
Option 1: Use CAP_NET_BIND_SERVICE
to grant low-numbered port access to a process:
With this you can grant permanent access to a specific binary to bind to low-numbered ports via the setcap
command:
sudo setcap CAP_NET_BIND_SERVICE=+eip /path/to/binary
For more details on the e/i/p part, see cap_from_text
.
After doing this, /path/to/binary
will be able to bind to low-numbered ports. Note that you must use setcap
on the binary itself rather than a symlink.
Option 2: Use authbind
to grant one-time access, with finer user/group/port control:
The authbind
(man page) tool exists precisely for this.
Install
authbind
using your favorite package manager.-
Configure it to grant access to the relevant ports, e.g. to allow 80 and 443 from all users and groups:
sudo touch /etc/authbind/byport/80 sudo touch /etc/authbind/byport/443 sudo chmod 777 /etc/authbind/byport/80 sudo chmod 777 /etc/authbind/byport/443
-
Now execute your command via
authbind
(optionally specifying--deep
or other arguments, see the man page):authbind --deep /path/to/binary command line args
E.g.
authbind --deep java -jar SomeServer.jar
There are upsides and downsides to both of the above. Option 1 grants trust to the binary but provides no control over per-port access. Option 2 grants trust to the user/group and provides control over per-port access but older versions supported only IPv4 (since I originally wrote this, newer versions with IPv6 support were released).
I have a rather different approach. I wanted to use port 80 for a node.js server. I was unable to do it since Node.js was installed for a non-sudo user. I tried to use symlinks, but it didn't work for me.
Then I got to know that I can forward connections from one port to another port. So I started the server on port 3000 and set up a port forward from port 80 to port 3000.
This link provides the actual commands which can be used to do this. Here're the commands -
localhost/loopback
sudo iptables -t nat -I OUTPUT -p tcp -d 127.0.0.1 --dport 80 -j REDIRECT --to-ports 3000
external
sudo iptables -t nat -I PREROUTING -p tcp --dport 80 -j REDIRECT --to-ports 3000
I have used the second command and it worked for me. So I think this is a middle ground for not allowing user-process to access the lower ports directly, but giving them access using port-forwarding.