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:
code: use setuid() to drop down from root to non-priviledged user after listening on port 80 is established.
using a proxy server of some sort to redirect requests to a port >1024 (and so not need node to run as root)
using IP tables to forward to another port (ditto node would not run as root)
Thanks
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.
(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))
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:
How to: Allow Node to bind to port 80 without sudo,
Is there a way for non-root processes to bind to "privileged" ports on Linux?
Related
I'm trying to redirect my port 80 to 8080 because the user need not type the url as webapp:8080 to access the web site.
Here's the command that I came across to redirect from port 80 to 8080 :
sudo iptables -A PREROUTING -t nat -i enp0s25 -p tcp --dport 80 -j REDIRECT --to-port 8080
I'm now able to access the page as webapp/. But the problem now I'm facing is that I'm not able to access the page if I give webapp/ after I restart the system.
How do I fix this?
You can try this :
iptables-save > /etc/sysconfig/iptables
"/etc/sysconfig/iptables " is for centos, you need to find the same file on your linux OS :)
An other solution is to create a conf' file and use this file when the system boot :
Create a file like "Conf_iptables".
Add your rules to this file.
Add execute privilege to root
chkconfig Conf_iptables on
Moreover you have to create 2 iptables rules (for IPv4 and IPv6) if you want to use IPv6 :)
If you need help use this site (sorry but it's in french) : http://blog.sephirots.fr/?p=123
The only thing you need is to save iptables rules permanently. It can be various depend on linux distribution.
For Debian/Ubuntu see for instance here:
https://www.thomas-krenn.com/en/wiki/Saving_Iptables_Firewall_Rules_Permanently
Ubuntu:
Install iptables-persistent. This will create 2 files in /etc/iptables/rules.v4 and rules.v6
Run netfilter-persistent save.
Try rebooting the machine.
I have a node app already deployed on ec2 that redirects port 80 to 3000 using:
sudo iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 80 -j REDIRECT --to-port 3000
Now I want to add a Wordpress blog in a subfolder mydomain.com/blog.
Must I use apache's ProxyPass as explained here? Won't it slow down node.js?
The example in the link also seems to be more suitable for cases where one wants to add node to apache and not the other way around..because of the URL distinction (/node) and port 8000, or it can fit both cases?
Is there any other way to allow node and apache work on the same server? Also, how should the ports be managed?
I would suggest that you re-think your server architecture a bit. Here is what I would recommend.
Use Nginx server since its lightweight, free, and can run both PHP and NodeJS applications.
You will need to install Nginx's PHP module to make the PHP code work and you can also setup Nginx to proxy requests to your NodeJS application.
All this can be achieved by simply installing Nginx and configuring it using the many guides available online.
Updated on March 11, 2015
Here are the links to get these set up:
https://www.digitalocean.com/community/tutorials/how-to-set-up-a-node-js-application-for-production-on-ubuntu-14-04
https://www.digitalocean.com/community/tutorials/how-to-install-wordpress-with-nginx-on-ubuntu-14-04
https://www.digitalocean.com/community/tutorials/how-to-host-multiple-node-js-applications-on-a-single-vps-with-nginx-forever-and-crontab
I'm using node.js for my webserver, and I would like forever (or something like it) to run the server.
I'm also using git to manage the website. I have a bare repository on the server that I can push to/pull from on my local machine. I would like the repository to do three things when I push to it.
CD to my working directory (on the server)
Have the working directory pull from the bare repo
Restart the running webserver.
The following script seems like it's what I should use as a post-receive hook in my bare repo.
cd ~/site
git pull
sudo forever stopall
sudo forever start main.js
However, I don't think it's smart to have the git hook use sudo like that. The script needs elevated to run on port 80.
How should I be doing this? What should my git post-receive look like?
Thanks!
Well, for my particular case, it turns out I shouldn't be running node as a super user for security reasons. I wanted it to be elevated to run on port 80, but it didn't need to be elevated to run on port 8000.
So I forwarded port 80 to port 8000, and now am running node on port 8000. It still works identically to how it did before.
The command that I used in particular to forward port 80 to 8000 is
sudo iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-ports 8000
Is it possible for a Node.JS program that is running as root, to downgrade its authority while it is running? This would be one of the first things it does, and the purpose is of course to limit possible damage it could cause, in the unlikely event that there is a vulnerability, or mis-trusted code that runs in this process.
Alternatively, is there a way for Node.JS process that is running as root, to start a separate process which is non-root? (preferably without adding a layer in between, such as sudo)
Try process.setuid (and likewise, process.setgid).
Yes, use process.setuid(id) and process.setguid(id) to change the effective user/group id of the current process.
#mabako's answer looks great, but there should be operating system tricks that are easier.
What I've seen people do a lot with node is to either
Add the user that runs the node code to the www-data group to allow it to bind to privileged ports.
ex: http://kvz.io/blog/2009/12/15/run-nodejs-as-a-service-on-ubuntu-karmic/
Use iptables to redirect privileged ports to an unprivileged node program, which listens on a high port.
iptables -A PREROUTING -t nat -i eth0 -p tcp --dport 80 -j REDIRECT --to-port 3000
Do you have any non-port-binding reasons to run a node server as root?
EDIT: More tricks here: Is there a way for non-root processes to bind to "privileged" ports on Linux?
I'm using the npm package express version 2.5.2 with node version .0.6.5. I appear to be running bash version 4.1.5 on Debian 4.4.5.
I'm trying to run my server in production mode but it still runs in development mode.
I run these commands in my bash shell:
$ export NODE_ENV=production
$ echo $NODE_ENV
production
$ sudo echo $NODE_ENV
production
$ sudo node bootstrap.js
I have this code inside bootstrap.js:
var bootstrap_app = module.exports = express.createServer();
//...
console.log(bootstrap_app.settings.env);
and here's what I see printed to standard out:
development
Is this a problem with my usage, or my system?
EDIT:
Thanks to ThiefMaster for his properly identifying that this issue stems from my running node as root. ThiefMaster suggested using iptables to forward from port 80 to an unprivileged port, but my system gives me an error. Moving this discussion to superuser.com or serverfault.com (link to follow)
Most environment variables are unset when using sudo for security reasons. So you cannot pass that environment variable to node without modifying your sudoers file to allow that variable to passt through.
However, you shouldn't run node as root anyway. So here's a good workaround:
If you just need it for port 80, run node on an unprivileged port and setup an iptables forward to map port 80 to that port:
iptables -A PREROUTING -d 1.2.3.4/32 -i eth0 -p tcp -m tcp --dport 80 -j DNAT --to-destination 2.3.4.5:1234
Replace 1.2.3.4 with your public IP, 2.3.4.5 with the IP node runs on (could be the public one or 127.0.0.1) and 1234 with the port node runs on.
With a sufficiently recent kernel that has capability support you could also grant the node executable the CAP_NET_BIND_SERVICE privilege using the following command as root:
setcap 'cap_net_bind_service=+ep' /usr/bin/node
Note that this will allow any user on your system to open privileged ports using node!
sudo NODE_ENV=production /usr/local/bin/node /usr/local/apps/test/app.js