- there are lots of useful things you can do without root
- you don’t need root to bind to port numbers below 1024 on Linux, just CAP_NET_BIND_SERVICE
- when you do need root, you can usually drop it either partially or completely
- there are lots of useful things you can do without root
- you don’t need root to bind to port numbers below 1024 on Linux, just CAP_NET_BIND_SERVICE
- when you do need root, you can usually drop it either partially or completely
How do you do that if you're not root?
And if you are building an executable with that capability, how do you enable your Makefile to set it?
I think we might need "CAP_SET_CAP_NET_BIND_SERVICE" as well.
In fact, I might want to allow a user to bind to port 200 only.
So in this case "CAP_SET_CAP_NET_BIND_SERVICE_PORT_200" is needed.
And here we see the inflexibility of the entire approach :)
Alternatively, if you're only concerned about other privileged ports, with a systemd socket unit, you could have systemd do the binding and pass your unprivileged process the socket, so that your process no longer needs the privileged-bind capability at any time; that'd probably be the easiest way if you're willing to modify the application code a bit. If you don't like systemd, you could have another helper program do it.
Or you could put your process in its own network namespace which has a filtered bridging or routing configuration between it and whichever namespace has the ‘real’ connectivity, which is complex and awkward but allows your process to ‘think’ it has full access, which might help if the code would otherwise balk.
Or you could use various other userspace sandboxing frameworks that let you install a BPF syscall filter, which I like a lot in theory but don't currently have personal experience with.
> And if you are building an executable with that capability, how do you enable your Makefile to set it?
The goal is to bind without passing through root, not to never have root at all, so you could run the service with it as an ambient capability (supported by e.g. systemd). Or setcap as root after building.
> In fact, I might want to allow a user to bind to port 200 only.
Program with the capability on its file to check the user, bind the socket, drop the capability, and exec. (I’m sure something existing does that, but I don’t have one to recommend since I’ve never needed it.)
But there’s also iptables and friends as alternative solutions to the same problem that still don’t require giving the process root at any point.
Can you combine that with nohup?
nohup setcap 'cap_net_bind_service=+ep' blabla...
You should probably run production services using something other than nohup, though, like systemd.