Can I run Node.JS with low privileges? - node.js

I would like to run node with a low privileges user, is it possible? I need to use the framework Express.js

Yes. There are many solutions available to do this, depending on your exact needs.
If you want to run node on port 80, you can use nginx (doesn't work with WebSockets yet) or haproxy. But perhaps the quickest and dirtiest is to use iptables to redirect port 80 to the port of your choice:
sudo iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-ports 8003
sudo iptables -t nat -L
When you’re happy, then save the config and make sure iptables comes on at boot
sudo service iptables save
sudo chkconfig iptables on
To automatically start your nodejs service as non-root, and restart it if it fails, you can utilize upstart with a script like this:
#!upstart
description "nodeapp"
author "you"
start on started mountall
stop on shutdown
# Automatically Respawn:
respawn
respawn limit 99 5
script
export HOME="/home/user/"
exec sudo -u user /usr/local/bin/node /home/user/app.js 2>&1 >> /home/user/app.log
end script
If you're on an Amazon EC2 installation, or you get an error that says sudo: sorry, you must have a tty to run sudo, then you can replace your exec command with this:
#!upstart
description "nodeapp"
author "you"
start on started mountall
stop on shutdown
# Automatically Respawn:
respawn
respawn limit 99 5
script
export HOME="/home/user/"
#amazon EC2 doesn’t allow sudo from script! so use su --session-command
exec su --session-command="/usr/local/bin/node /home/user/app.js 2>&1 >> /home/user/app.log" user &
end script
And, you didn't ask this question, but to keep it running forever, check out monit! Here is a useful guide to setting up node.js with upstart and monit.

Related

How to enable Linux firewall(ufw) for custom program running on random port

Written program in python, which chooses random port available for TCP and UDP communication. If I enable Linux firewall(ufw) by running sudo ufw enable. where we can allow any port by giving
sudo ufw allow port_number. As the program can take any random port on run, so can not tell ufw to allow any particular port. Is there any way to tell ufw to allow prog to access any random port by supplying program name to ufw like in windows. In windows firewall, we can supply the following command to allow access to all port for myprog
netsh advfirewall firewall add rule name=rule_name_udp dir=in action=allow protocol=UDP localport=any program=path/myprog.exe
is there any way to allow ufw for my custom program to access for udp/tcp communication with ufw enable?
Thanks to all in advance.
You can wrap your app into systemd service and use post-start hook to call extra bash script which punches holes in firewall.
/path/to/python/app/assistant-ufw-hole-puncher
#!/bin/bash
#extra sleep for prespawn script
sleep 2
#punch holes for TCP ports
ports=`sudo netstat -ntlp 2>&1 |grep yourapp | sed -r 's/(.*:)([0-9]*)(\s.*)/\2/'|sort|uniq`
for port in $ports ; do
sudo ufw allow $port
done
#punch holes for UDP ports
ports=`sudo netstat -nulp 2>&1 |grep yourapp | sed -r 's/(.*:)([0-9]*)(\s.*)/\2/'|sort|uniq`
for port in $ports ; do
sudo ufw allow $port
done
Also you could spawn this script before starting your script but you would need to add extra sleep to wait for python script to start.
#!/bin/bash
/path/to/python/app/assistant-ufw-hole-puncher &
python ./your-app.py

Why is my screen session terminating in the middle of a server startup?

Some background first, I am running Ubuntu 64-bit server on a machine running ESXi. I have just installed this VM today specifically for this task. This task is to run a tModLoader server with as little outside interference as possible.
I set up firewalld with a service for terraria that looks like this:
<?xml version="1.0" encoding="utf-8"?>
<service>
<short>Terraria</short>
<description>Open TCP port 7777 for incoming Terraria client connections.</description>
<port protocol="tcp" port="7777"/>
</service>
I set up UFW to allow only ssh and port 7777/tcp.
I added a rule for iptables with this command:
sudo iptables -A INPUT -p tcp --dport 7777 -j ACCEPT
I created a user called "terraria" with options -r -m -d
I set up the server files in /opt/terraria with the exception of the ModLoader files which are installed in two locations because they are dependent on the user that starts the process. The location of those are ~/.local/share/Terraria/ModLoader
I created a service for terraria in /etc/systemd/system/terraria.service that looks like this:
[Unit]
Description=server daemon for terraria
[Service]
Type=forking
User=terraria
KillMode=none
ExecStart=/usr/bin/screen -dmS terraria /bin/bash -c "/opt/terraria/tModLoaderServer -config /opt/terraria/serverconfig.txt"
ExecStop=/usr/local/bin/terrariad exit
[Install]
WantedBy=multi-user.target
I made a script that allows me to easily access the screen session the service starts in:
#!/usr/bin/env bash
send="`printf \"$*\r\"`"
attach='script /dev/null -qc "screen -r terraria"'
inject="screen -S terraria -X stuff $send"
if [ "$1" = "attach" ] ; then cmd="$attach" ; else cmd="$inject" ; fi
if [ "`stat -c '%u' /var/run/screen/S-terraria/`" = "$UID" ]
then
$cmd
else
su - terraria -c "$cmd"
fi
With all of that out of the way, the issue I am running into is that the service starts, and I can attach to the screen session while the service is running, however the screen session terminates after a few seconds while the server is starting up. I have no idea why that happens. Starting the server as my own user seems to work properly, but I need it to be able to run as a service with a system user so that the server will automatically run upon boot.
As a side note the config file doesn't work oddly.
Any ideas and help on this issue would be greatly appreciated.

EC2 ubuntu launch node server on reboot not working

I'm trying to launch an express app when my ec2 machine starts. I've a startup script that is:
#!/bin/bash
echo "will reroute traffic" >> /home/ubuntu/log.logs
sudo iptables -A PREROUTING -t nat -i eth0 -p tcp --dport 80 -j REDIRECT --to-port 8080
sudo iptables -A INPUT -p tcp -m tcp --sport 80 -j ACCEPT
sudo iptables -A OUTPUT -p tcp -m tcp --dport 80 -j ACCEPT
echo "will kill node" >> /home/ubuntu/log.logs
if pgrep node &> /dev/null ; then killall -KILL node ; fi
if pgrep nodejs &> /dev/null ; then killall -KILL nodejs ; fi
echo "will run node server" >> /home/ubuntu/log.logs
cd server && npm install && npm run build && npm run start </dev/null &>/dev/null &
echo "has run node server" >> /home/ubuntu/log.logs
If I launch it from the console, it starts the server, exits and the server runs fine.
To launch it, I've added those lines to /etc/rc.local:
rm -f /home/ubuntu/log.logs
echo "will run" >> /home/ubuntu/log.logs
/bin/bash /home/ubuntu/startup.sh
echo "has run" >> /home/ubuntu/log.logs
After rebooting, the server is not responding and it looks like it has not started (the server logs ticks when running that are not there)
the output in log.logs looks fine:
will run
will will reroute traffic
will kill node
will run node server
has run node server
has run
so everything seems to have been executed, but the node app is not running, which I confirmed by running top | grep node that returns nothing.
I found that the cheap (or free) AWS VMs got CPU/network throttled causing npm installs etc. to fail. Maybe use a VPS that is a better value or try yarn. Also make it log the npm stuff to a file instead of dev/null.
It turned out that I installed npm and node through nvm, and that nvm adds a script to .bashrc that will load those libraries. To start my script on reboot, I was using cron that is not sourcing .bashrc. Additionally, the default .bashrc on AWS EC2 ubuntu instances starts with a check on wether it's been run from a terminal or not, and escape it it's not been run from a terminal. So sourcing it from cron has no effect.
I didn't see that since the failing line
cd server && npm install && npm run build && npm run start
was not logging anything
I ended up manually sourcing the path to npm and node

How to configure ports on apache server for iperf3

I'm using my apache server for running TCP and UDP traffic using iperf3.
I manually execute a command on my server to listen to a port.
~# iperf3 -i 5 -s -p 7759
-----------------------------------------------------------
Server listening on 7759
-----------------------------------------------------------
I'm wondering if there is a way to configure my apache server to have few ports (say 7760,7761,7762,...7770) permanently open on my apache server for iperf traffic so that I don't have to manually execute the aforementioned command to open the port for iperf traffic
The answer depends on the definition of permanently open.
If ports remaining open after you log out from your webserver is sufficiently good approximation of permanently open. Then all you need is start iperf with nohup command.
nohup iperf3 -s -p 7759 >/tmp/log 2>&1
See this question for more details on keeping backround processes after the shell that spawned them terminates. In particular, check out the answers that suggest using the screen command.
If you need iperf server to keep the ports open between reboots you need to configure the init process to spawn iperf3 at boot up time. For this you need root access to your webserver.
As root you could add the following lines to /etc/rc.local file
iperf3 -s -p 7759 > /tmp/iperf-7759.log 2>&1 &
iperf3 -s -p 7760 > /tmp/iperf-7760.log 2>&1 &
...
iperf3 -s -p 7760 > /tmp/iperf-7770.log 2>&1 &
See also this question on how to ensure a command is run every time the machine starts.

Running a script on each reboot of EC2

I am running an Amazon Linux EC2 instance. It is a node.js server. I need to run the following command on each reboot/startup:
sudo iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to 8080
The command above redirects port 80 to port 8080.
How can I achieve this?
I've solved the issue by placing my script in the /etc/rc.local file
This file gets executed after all other init scripts which is what I needed.
After a lot of trials, below worked:
crontab -e
#reboot cd /home/ec2-user/somedir/ && ./run.sh > output1.txt
vi ./run.sh
./run2.sh 2>&1 > output2.txt &
./run2.sh
# this had actual commands, it also had a nohup command

Resources