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

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

Related

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

Listening on multiple ports?

Can't you listen on a port range with netcat? You can scan a range, but not listen it appears. So only solution is scripting?
I know this post is old, but I recently found a decent solution for this in the form of a nice one-liner.
Shell = bash, OS = Redhat 7.
for j in 202{0..5}; do nc -lvnp $j & done
This should open up a number of listening ports from 2020 to 2025, or whatever range you want.
If you are not a root user but a sudoer and have to listen to ports below 1024 add sudo before nc command.
for j in 101{0..5}; do sudo nc -lvnp $j & done
Edited : n/c: The local port parameter was missing. {-p}
I don't think it supports that functionality. If you are happy with any old solution, you could use the ncat edtition of netcat, and set up forwarding for each port. You can spawn a forwarder for all but the first port, then listen on the first port:
first_port=2999
last_port=3004
for (( i = first_port+1; i <= last_port; i++ )) do
ncat -l -k -p $i -c "nc localhost $last_port" &
done
ncat -l -k -p $first_port
I admit, it's grungey.
If you are looking to scan your destination through multiple local ports, you can use the -p <PORT> option[1]. That tells netcat to look through that local port, much similar to when telling it to setup a backdoor listener on said port. You can also string a bunch of those ports together if they are split up. Here is an example I just used.
$ nc -vvz -p 80 -p 8080 -p 443 testserver.mycompany.com 3066
That did my trick. Of course you can also list multiple destination ports to make it scan those also through each of your local ports.
[1] http://www.instructables.com/id/More-Fun-with-netcat/step2/Basic-Netcat-commands/
or iptables,
iptables -t nat -A INPUT -p tcp --dport 8080 -j REDIRECT --to-port 80

Can I run Node.JS with low privileges?

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.

Why does Capistrano lock up when executing a specific iptables command?

I'm trying to remotely open a port in a iptables firewall using Capistrano. Here's my task:
desc "Open up a port in the firewall"
task :open_port, :roles => :all do
port = variables[:port] || nil
if (!port)
puts "You must specify the port number"
next
end
run "#{sudo} /sbin/iptables -I RH-Firewall-1-INPUT 1 -p tcp --dport #{port.to_s} -j ACCEPT"
run "#{sudo} /sbin/service iptables save"
run "#{sudo} /etc/init.d/iptables restart"
end
The problem is that the first command in the task locks up. I've tried running this rule using a variety of port numbers and target machines, always with the same result.
I've got literally many dozens of other rules that look much like this but that work fine. In fact, I've got a similar task where the first command is a call to iptables to create a port mapping and that task works just fine.
What's more, I can successfully run this command on the Capistrano host:
ssh -l deployer core sudo /sbin/iptables -I RH-Firewall-1-INPUT 1 -p tcp --dport 2424 -j ACCEPT
This works fine. This should be exactly what Capistrano is attempting to do.
Why is this command locking up Capistrano?
TIA for a solution or any clue whatsoever.
Have Fun All!!!
Figured this one out myself the other day. The problem was that I was using the name 'port' as the parameter to my task. The 'parameter' port is recognized by the 'run' command, and causes the system to try to connect to the target machine via that port rather than the normal ssh port. Hence the lockup.
I changed my parameter name to 'dport', and the task started working as I expected.

Resources