Drop Root Privileges in Node.js after Binding to Port 80
thomashunter.name
thomashunter.name
sudo setcap 'cap_net_bind_service=+ep' /path/to/nodejs
Then you don't have to ever run it as root (at least not for the purpose of binding to the right port). sudo iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 80 -j REDIRECT --to-port 8080If your service gets a few thousand hits per day, it'll be okay. If you're trying to survive a few thousand hits per second, your clients will suffer less than optimal throughput.
In what use case would iptables give a performance penalty ?
I have iptable-setups running with hundreds of rules and 800-1000 concurrent(!) users. During traffic peaks times my 5-6(?) year old Xeon does a good job, cpu usage barely touches 3-4%. Throughput downstream at that point around 350Mbit/s (admitted, downstream just matched by conntrack:matched/established) and upstream around 20Mbit/s, working through hundreds of rules.
iptables runs in the kernel-space and is very, very, VERY performant. (well, I lied, iptables itself is just a configuration tool for the kernel - but it is incredibly fast).
Following that kind of traffic with tcpdump (userland) just drops about half of the packets because it maxes out that poor CPU instantly. (yes, that depends on the args). And don't even thinkg about using iptraf :-)
(That reminds me: please, some one, send me better server hardware :-x)
1. Don't use connection tracking
2. If you need to use it, make judicious use of -j NOTRACK
I use this on a few high traffic servers, with good results:
iptables -t raw -A PREROUTING -i lo -j NOTRACK
iptables -t raw -A OUTPUT -o lo -j NOTRACK
iptables -A INPUT -i eth0 -p tcp -m tcp --dport 80 -j ACCEPT
iptables -A INPUT -i eth0 -p tcp -m tcp --dport 443 -j ACCEPT
iptables -t raw -A OUTPUT -o eth0 -p tcp -m tcp --sport 443 -j NOTRACK
iptables -t raw -A OUTPUT -o eth0 -p tcp -m tcp --sport 80 -j NOTRACK iptables -t raw -A PREROUTING -i eth0 -p tcp -m tcp --dport 443 -j NOTRACK
iptables -t raw -A PREROUTING -i eth0 -p tcp -m tcp --dport 80 -j NOTRACKWhat would be more useful is the ability to allow a _user_ to open a privileged port. In my option mappu's answer is the right way to go, i.e. using authbind to allow a certain user to open a port or a range of ports.
The answer you are looking for in Solaris...
This limits it both on the basis of which user can open ports and which programs can.
(Hmm, did parent just edit his comment ? He didn't mention authbind when I hit reply, did he ?)
From the man page: authbind allows a program which does not or should not run as root to bind to low-numbered ports in a controlled way. The shared library loaded using LD_PRELOAD overrides the bind(2) system call. When a program invoked via authbind calls bind to bind a socket to a low-numbered TCP/IP port, and if the program doesn't already have an effective uid of 0, the version of bind supposed by authbind forks and executes a setuid-root helper program.
You can create configuration file like /etc/authbind/byport/port and use standard linux file permissions to allow certain non-root users to bind to ports < 1024
usermod -K defaultpriv=basic,net_privaddr ${user}
You can off course also assign the privileges to a role, and then assign the user that role so as required they can su to the role and use the privileges.Here is a pretty neat description of what is possible and why it is pretty awesome: http://www.c0t0d0s0.org/archives/4075-Less-known-Solaris-fea...
---
On FreeBSD if you have the MAC framework enabled, you can use the portacl module to give new privileges:
sysctl security.mac.portacl.rules=uid:$user_id:tcp:80
See http://www.freebsd.org/doc/en_US.ISO8859-1/books/handbook/ma... for more information.You probably won't handle every HTTP edge case as well as nginx defaults, and you don't really need the control at that level to implement a functional, high performance web app.
process.setgid('tlhunter');
process.setuid('users');
I'd expect that 'users' is the group here and 'tlhunter' the user 'thomas l. hunter'?Assuming a tcpserver-like program called tcplisten, this would look like
sudo tcplisten 0.0.0.0 80 setuidgid nobody \
program-that-accepts-on-stdin
FastCGI works similarly. Multiple workers can run underneath, calling accept(2) on stdin.A simple implementation of tcplisten:
"In production, one should create a specialized user to run any service." And if you have lots of money to waste, stick 'em all in separate VMs too.