Search code examples
linuxrootipv6iptableslinux-capabilities

Is there a way for non-root processes to bind to "privileged" ports on Linux?


It's very annoying to have this limitation on my development box, when there won't ever be any users other than me.

I'm aware of the standard workarounds, but none of them do exactly what I want:

  1. authbind (The version in Debian testing, 1.0, only supports IPv4)
  2. Using the iptables REDIRECT target to redirect a low port to a high port (the "nat" table is not yet implemented for ip6tables, the IPv6 version of iptables)
  3. sudo (Running as root is what I'm trying to avoid)
  4. SELinux (or similar). (This is just my dev box, I don't want to introduce a lot of extra complexity.)

Is there some simple sysctl variable to allow non-root processes to bind to "privileged" ports (ports less than 1024) on Linux, or am I just out of luck?

EDIT: In some cases, you can use capabilities to do this.


Solution

  • For some reason no one mention about lowering sysctl net.ipv4.ip_unprivileged_port_start to the value you need. Example: We need to bind our app to 443 port.

    sysctl net.ipv4.ip_unprivileged_port_start=443
    

    Some may say, there is a potential security problem: unprivileged users now may bind to the other privileged ports (444-1024). But you can solve this problem easily with iptables, by blocking other ports:

    iptables -I INPUT -p tcp --dport 444:1024 -j DROP
    iptables -I INPUT -p udp --dport 444:1024 -j DROP
    

    Comparison with other methods. This method:

    • from some point is (IMO) even more secure than setting CAP_NET_BIND_SERVICE/setuid, since an application doesn't setuid at all, even partly (capabilities actually are). For example, to catch a coredump of capability-enabled application you will need to change sysctl fs.suid_dumpable (which leads to another potential security problems) Also, when CAP/suid is set, /proc/PID directory is owned by root, so your non-root user will not have full information/control of running process, for example, user will not be able (in common case) to determine which connections belong to application via /proc/PID/fd/ (netstat -aptn | grep PID).
    • has security disadvantage: while your app (or any app that uses ports 443-1024) is down for some reason, another app could take the port. But this problem could also be applied to CAP/suid (in case you set it on interpreter, e.g. java/nodejs) and iptables-redirect. Use systemd-socket method to exclude this problem. Use authbind method to only allow special user binding.
    • doesn't require setting CAP/suid every time you deploy new version of application.
    • doesn't require application support/modification, like systemd-socket method.
    • doesn't require kernel rebuild (if running version supports this sysctl setting)
    • doesn't do LD_PRELOAD like authbind/privbind method, this could potentially affect performance, security, behavior (does it? haven't tested). In the rest authbind is really flexible and secure method.
    • over-performs iptables REDIRECT/DNAT method, since it doesn't require address translation, connection state tracking, etc. This only noticeable on high-load systems.

    Depending on the situation, I would choose between sysctl, CAP, authbind and iptables-redirect. And this is great that we have so many options.