17

I'm running a node.js server, that will serve requests on port 80 amongst others. Clearly this requires the application running as root (on Linux).

Looking at this post (http://syskall.com/dont-run-node-dot-js-as-root) as an example it's clear that there are simple ways to allow node to be run as a non-root user, but I'm wondering if anyone has views on the advantages/disadvantages of the different methods suggested:

  1. code: use setuid() to drop down from root to non-priviledged user after listening on port 80 is established.

  2. using a proxy server of some sort to redirect requests to a port >1024 (and so not need node to run as root)

  3. using IP tables to forward to another port (ditto node would not run as root)

Thanks

Daniel
  • 38,041
  • 11
  • 92
  • 73
user2208171
  • 183
  • 1
  • 1
  • 6

3 Answers3

23

Option 1 requires you launch the node server as root. Not ideal.

Option 2 adds overhead to every handled request and adds another failure point to your stack.

Option 3 Is the simplest and most efficient method.

To implement Option 3, add the following to your system init scripts. (/etc/rc.d/rc.local on RedHat based systems like AWS).

iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 80 -j REDIRECT --to-port 3000

That will redirect requests from port 80 to port 3000.

Daniel
  • 38,041
  • 11
  • 92
  • 73
  • 1
    Upvoted. Note that on Ubuntu at least, the above `iptables` command isn't permanent...to make sure that rule is retained on the next boot, you need to ensure that there's a startup script that restores the `iptables` rules using the `iptables-restore` command, as described here: http://www.rackspace.com/knowledge_center/article/ubuntu-setup – Matt Browne Jan 27 '14 at 02:35
  • Is option 3 the way most NodeJS devs deploy their finished websites? If not, how do they usually allow client browsers to connect to port 80? – trysis Sep 26 '14 at 22:29
  • Depends on your situation. Larger deployments use a front end load balancer which is the same as option 2. A lot of people use Heroku which uses a front end load balancer; again option 2. However, if you are deploying this on a server where you have root access then I recommend option 3. It's easy and you don't have to worry about configuring a reverse proxy. That said, definitely take a look at Heroku if that's an option for you. They make it super easy to do deployments. – Daniel Sep 27 '14 at 23:00
  • 2
    Is there any way to mark this answer as the accepted one? The OP is obviously not going to do it, and it's a huge shame. – Merc Mar 07 '16 at 06:54
  • and what? node process still ran from root user and if there is a bug attacker will take down whole system :) – Serhii Kuzmychov Sep 03 '16 at 18:12
5

(I haven't got enough reputation to add a comment the the one of Matt Browne, so I write this as an answer. Feel free to edit.)

There is a simpler method to load iptables rules automatically after a reboot than the one described in the link of Matt Browne: One can install iptables-persistent from the repositories using apt-get:

apt-get install iptables-persistent

Rules still need to be saved manually like this:

IPv4:

iptables-save > /etc/iptables/rules.v4

IPv6:

iptables-save > /etc/iptables/rules.v6

(Source: http://www.thomas-krenn.com/de/wiki/Iptables_Firewall_Regeln_dauerhaft_speichern (german))

pt1
  • 179
  • 1
  • 5
5

I love the simplicity of this workaround:

sudo setcap 'cap_net_bind_service=+ep' `which node`

It also works for programs other than nodejs btw.

Basically as 2nd parameter you type the path to the program executable (like /usr/bin/nodejs on Ubuntu), in the above case which node should provide it dynamically, thus making this work independently from Linux distro.

Beware though that when you upgrade nodejs or the executable gets overwritten for some other reason you would have to execute that same command again.

Sources:

Greenonline
  • 1,330
  • 8
  • 23
  • 31
code_gamer
  • 357
  • 5
  • 15