Webserver – Allow Unprivileged User to Start on Port 80

privilegesrootsudowebserver

I understand the security implications of allowing a non-root user to start a webserver on ports 80 and 443.

I would like to remove the privilege check to allow any non-root user to invoke a webserver on ports 80 and 443 on Ubuntu 16 and CentOS 7.

I have root access on the machine, but I need the webserver to be run as a different username to address NFS permission issues; this alternative username cannot have root access.

So far, I've looked at:

  • setcap cap_net_bind_service=ep /path/to/the/executable (doesn't stick because the executable is recompiled remotely and stored on NFS)
  • editing the sudoers file to enable passwordless sudo as the user from root (still has NFS access issues)

Ideally, I'd like something like setcap, but on the ports, rather than the executable, to drop the privilege check entirely.

Related:
https://stackoverflow.com/questions/413807/is-there-a-way-for-non-root-processes-to-bind-to-privileged-ports-on-linux

authbind looked promising, but it doesn't seem to work with GoLang webservers

Ubuntu 16 is too old to allow changing the unprivileged port start range:

> sudo sysctl net.ipv4.ip_unprivileged_port_start=80
sysctl: cannot stat /proc/sys/net/ipv4/ip_unprivileged_port_start: No such file or directory

Best Answer

I think setcap will be your answer. I think the real question here is: How will my system recognize when the webserver on the NFS has been touched so it can run a setcap command on it?

I think you'll want to set up an inotify or systemd.path to monitor this webserver. When that binary gets replaced, you'll detect it and trigger the setcap command that works for you. This works especially well if your webserver runs via systemd already.

Here's an example with systemd.path assuming your server runs as systemd service webserver.service

# /etc/systemd/system/webcap.path
[Unit]
Description=Watching changes in the webserver binary
# Start monitoring only after the webserver is running.
After=webserver.service

[Path]
# Whenever someone writes to this path (binary is replaced), do something
PathModified=/path/to/webserver
# This is the service you launch when the above condition is met
Unit=webcap.service

[Install]
#Whenever the webserver is started, this monitor will also start
WantedBy=webserver.service
# /etc/systemd/system/webcap.service
[Unit]
Description=Update caps of webserver

[Service]
Type=oneshot
ExecStart=ssetcap cap_net_bind_service=ep /path/to/webserver
Related Question