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?
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'm trying to launch a flask app, which runs on default port: 5000. Initially, I tried to allow for open connections with ufw under the following configuration:
However, all remote requests were being refused. I eventually ran the following command: iptables -I INPUT -p tcp --dport 5000 -j ACCEPT, which then allows for all commands.
I have two separate questions.
1. Why did the iptables command work but the ufw configuration not work?
2. My current process for deploying the app is: 1) launch screen session 2) run IPTables command 3) run python app.py 4) detach from screen. This seems to do the job initially, but after a while, the app begins to refuse connections. Any thoughts on why this might happen?
The problem was that the VM was configured to use a puppet server, so ufw was being ignored/overwritten entirely.
I have been following the tutorials and been experimenting with Docker for a couple of days but I can't find any "real-world" usage example..
How can I communicate with my container from the outside?
All examples I can find ends up with 1 or more containers, they can share ports with their-others, but no-one outside the host gets access to their exposed ports.
Isn't the whole point of having containers like this, that at least 1 of them needs to be accessible from the outside?
I have found a tool called pipework (https://github.com/jpetazzo/pipework) which probably will help me with this. But is this the tool everyone testing out Docker for production what they are using?
Is a "hack" necessary to get the outside to talk to my container?
You can use the argument -p to expose a port of your container to the host machine.
For example:
sudo docker run -p80:8080 ubuntu bash
Will bind the port 8080 of your container to the port 80 of the host machine.
Therefore, you can then access to your container from the outside using the URL of the host:
http://you.domain -> losthost:80 -> container:8080
Is that what you wanted to do? Or maybe I missed something
(The parameter -expose only expose port to other containers (not the host))
This (https://blog.codecentric.de/en/2014/01/docker-networking-made-simple-3-ways-connect-lxc-containers/) blog post explains the problem and the solution.
Basicly, it looks like pipeworks (https://github.com/jpetazzo/pipework) is the way to expose container ports to the outside as of now... Hope this gets integrated soon..
Update: In this case, iptables was to blame, and there was a rule that blocked forwarded traffic. Adding -A FORWARD -i em1 -o docker0 -j ACCEPT solved it..
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?
I create and launch an app like this:
express -s -t ejs
npm install express
npm install ejs
node app.js
and it works (on port 3000). But when I go and change the port to 80, then running node app.js outputs this:
node.js:198
throw e; // process.nextTick error, or 'error' event on first tick
^
TypeError: Cannot call method 'getsockname' of null
at HTTPServer.address (net.js:746:23)
at Object.<anonymous> (/var/www/thorous/app.js:35:67)
at Module._compile (module.js:432:26)
at Object..js (module.js:450:10)
at Module.load (module.js:351:31)
at Function._load (module.js:310:12)
at Array.<anonymous> (module.js:470:10)
at EventEmitter._tickCallback (node.js:190:26)
This works too on my laptop, but not on my Amazon EC2 instance, where port 80 is open.
Can figure out what's wrong. Any tips?
If you really want to do this you can forward traffic on port 80 to 3000.
sudo iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-ports 3000
Are you starting your app as root? Because lower port numbers require root privileges.
Maybe a sudo node app.js works?
BUT, you should NOT run any node.js app on port 80 with root privileges!!! NEVER!
My suggestions is to run nginx in front as a reverse proxy to your node.js app running on port e.g. 3000
Keep it Stupid Simple:
setcap
systemd
VPS
On a normal VPS (such as Digital Ocean, Linode, Vultr, or Scaleway), where the disk is persistent, use "setcap". This will allow a non-root user to bind to privileged ports.
sudo setcap 'cap_net_bind_service=+ep' $(which node)
TADA! Now you can run node ./server.js --port 80 as a normal user!
Aside:
You can also use systemd to stop and start your service. Since systemd is sometimes a p.i.t.a., I wrote a wrapper script in Go that makes it really easy to deploy node projects:
# Install
curl https://webinstall.dev/serviceman | bash
# Use
cd ./my/node/project
sudo serviceman --username $(whoami) add npm start
or, if your server isn't called 'server.js' (de facto standard), or extra options:
cd ./my/node/project
sudo serviceman --username $(whoami) add node ./my-server-thing.js -- --my-options
All that does is create your systemd file for you with sane defaults. I'd recommend you check out the systemd documentation as well, but it is a bit hard to grok and there are probably more confusing and otherwise bad tutorials than there are simple and otherwise good tutorials.
Ephemeral Instances (i.e. EC2) are not for long-running servers
Generally, when people use EC2, it's because they don't care about individual instance uptime reliability - they want a "scalable" architecture, not a persistent architecture.
In most of these cases it isn't actually intended that the virtualized server persist in any sort of way. In these types of "ephemeral" (temporary) environments a "reboot" is intended to be about the same as reinstalling from scratch.
You don't "setup a server" but rather "deploy an image". The only reason you'd log into such a server is to prototype or debug the image you're creating.
The "disks" are volatile, the IP addresses are floating, the images behave the same on each and every boot. You're also not typically utilizing a concept of user accounts in the traditional sense.
Therefore: although it is true that, in general, you shouldn't run a service as root, the types of situations in which you typically use volatile virtualization... it doesn't matter that much. You have a single service, a single user account, and as soon as the instance fails or is otherwise "rebooted" (or you spin up a new instance of your image), you have a fresh system all over again (which does mean that any vulnerabilities persist).
Firewalls: Ephemeral vs VPS
Stuff like EC2 is generally intended to be private-only, not public-facing. These are "cloud service" systems. You're expected to use a dozen different services and auto-scale. As such, you'd use the load balancer service to forward ports to your EC2 group. Typically the default firewall for an instance will deny all public-network traffic. You have to go into the firewall management and make sure the ports you intend to use are actually open.
Sometimes VPS providers have "enterprise" firewall configurators, but more typically you just get raw access to the virtual machine and since only the ports that you actually listen on get access to the outside world in the first place (by default they typically don't have random services running), you may not get any additional benefit from a firewall. Certainly a good idea, but not a requirement to do what you need to do.
Don't use EC2 as a VPS
The use case you have above may be a much better candidate for a traditional VPS service (as mentioned above: Digital Ocean, Linode, Vultr, Scaleway, etc) which are far easier to use and have much less management hassle to get started. All you need is a little bash CLI know-how.
And, as an extra bonus, you don't have to guess at what the cost will be. They tell you in simple $/month rather than ยข/cpu/hour/gb/internal-network/external-network/etc - so when something goes wrong you get a warning via email or in your admin console rather than an unexpected bill for $6,527.
Bottom line: If you choose to use EC2 and you're not a "DevOps" expert with an accountant on staff... you're gonna have a hard time.
Perhaps there is something else running on port 80 previously?
Perhaps do a port scan and confirm that it is not being used already?
nc -z <<your IP>> 80