Killing Socat and restarting it via a bash script - linux

I need a bash script which kills als SOCAT-Proccesses and restarts them again. I managed it via crontab after a reboot, but this produces too much downtime to reboot again after there are too many SOCAT-Proccesses.
I used
#!/bin/sh
killall socat &
sleep 3s
socat UDP4-LISTEN:PORT,fork,su=nobody UDP6:[IPV6]:PORT & disown
socat TCP4-LISTEN:PORT2,fork,su=nobody TCP6:[IPV6]:PORT2 & disown
exit
Now I have the problem that the script
does not run completely in background
often stops after executing the first SOCAT-Command.
I also tried nohup, but it also does not run completely in background.

What exactly should instigate this script to run?
Do you want to run it periodically, manually or when socat fails?
We certainly should understand why socat is failing in the first place.
I think it would be a good idea to output some logging from your script and kill socat with SIGKILL (-9).
A starting point here:
$ cat /usr/local/bin/restart_ip_addr_fam_bridge.sh
#!/bin/sh
IPV6="::1"
PORT=10001
PORT2=10002
while [ true ]; do
killall -9 socat 2> /dev/null
socat -T3600 UDP4-LISTEN:$PORT,reuseaddr,fork,su=nobody UDP6:[$IPV6]:$PORT &
socat TCP4-LISTEN:$PORT2,reuseaddr,fork,su=nobody TCP6:[$IPV6]:$PORT2 &
# Wait for a request to run or you could wait for a fixed time here
while [ ! -f /tmp/req_restart_ip_addr_fam_bridge ]; do
sleep 3
done
rm -f /tmp/req_restart_ip_addr_fam_bridge
printf "%s: Restarting IP address family bridge\n" "$(date '+%D %T')" >> /tmp/restart_ip_addr_fam_bridge.log
chmod 666 /tmp/restart_ip_addr_fam_bridge.log
# Avoid busy wait
sleep 5
done
exit
You can run it at startup, for example, adding this line to /etc/rc.local:
/usr/local/bin/restart_ip_addr_fam_bridge.sh &
And request it to restart your socat bridges with:
$ touch /tmp/req_restart_ip_addr_fam_bridge
See the running log with:
$ cat /tmp/restart_ip_addr_fam_bridge.log
08/20/22 15:14:43: Restarting IP address family bridge
Test your socat bridges:
$ nc -6 -l ::1 10002 | $ nc -4 127.0.0.1 10002
Typed from IPv4 TCP client | Typed from IPv4 TCP client
Be careful restart_ip_addr_fam_bridge.sh here is running as root from rc.local script.
Probably this is not very desirable/safe depending on your application.
EDIT: Added timeout for socat UDP bridge as recommended by #dest-unreach.

Related

Why is Crontab not starting my tcpdump bash script capture?

I have created a simple bash script to start capturing traffic from all interfaces I have in my Linux machine (ubuntu 22), but this script should stop capturing traffic 2 hours after the machine has reboot. Below is my bash script
#!/bin/bash
cd /home/user/
tcpdump -U -i any -s 65535 -w output.pcap &
pid=$(ps -e | pgrep tcpdump)
echo $pid
sleep 7200
kill -2 $pid
The script works fine if I run it, but I need to have it running after every reboot.
Whenever I run the script, it works without problem
user#linux:~$ sudo ./startup.sh
[sudo] password for user:
tcpdump: data link type LINUX_SLL2
tcpdump: listening on any, link-type LINUX_SLL2 (Linux cooked v2), snapshot length 65535 bytes
1202
35 packets captured
35 packets received by filter
0 packets dropped by kernel
but when I set it in the crontab as
#reboot /home/user/startup.sh
it does not start at reboot. I used ps -e | pgrep tcpdump to make sure if the script is running but there is not an output, it seems that it is not starting the script after the reboot. I don't know if I need to have root permissions for that. Also, I checked the file permission, and it has
-rwxrwxr-x 1 user user 142 Nov 4 10:11 startup.sh
Any suggestion on why it is not starting the script at the reboot?
Suggesting to update your script:
#!/bin/bash
source /home/user/.bash_profile
cd /home/user/
tcpdump -U -i any -s 65535 -w output.pcap &
pid=$(pgrep -f tcpdump)
echo $pid
sleep 7200
kill -2 $pid
Suggesting to inspect crontab execution log in /var/log/cron
The problem here was that even though the user has root permission, if an script needs to be run in crontab at #reboot, crontab needs to be modified by root. That was the only way I found to run the script. As long as I am running tcpdump, this will require root permission but crontab will not start it at the boot up if it is not modified by sudo.

Why doesn't tcpdump run in background?

I logged in a virtual machine via ssh and I tried to run a script in background, the script is shown below:
#!/bin/bash
APP_NAME=`basename $0`
CFG_FILE=$1
. $CFG_FILE #just some variables
CMD=$2
PID_FILE="$PIDS_DIR/$APP_NAME.pid"
CUR_LOG_DIR=$LOGS_RUNNING
echo $$ > $PID_FILE
#Main script code
#This script shall be called using the following syntax
# $ nohup script_name output_dir &
TIMESTAMP=`date +"%Y%m%d%H%M%S"`
CAP_INTERFACE="eth0"
/usr/sbin/tcpdump -nei $CAP_INTERFACE -s 65535 -w file_result
rm $PID_FILE
The result should be tcpdump running in background, redirecting the command result to file_result.
The script is called with:
nohup $SCRIPT_NAME $CFG_FILE start &
And It is stopped calling the STOP_SCRIPT:
##STOP_SCRIPT
PID_FILE="$PIDS_DIR/$APP_NAME.pid"
if [ -f $PID_FILE ]
then
PID=`cat $PID_FILE`
# send SIGTERM to kill all children of $PID
pkill -TERM -P $PID
fi
When I check the file_result, after running the stop script, It is empty.
What is happening? How can I solve it?
I found this link: https://it.toolbox.com/question/launching-tcpdump-processes-in-background-using-ssh-060614
The author seems to have faced a similar issue. They debate about race conditions, but I didn't understand completely.
I'm not sure what you're trying to accomplish by having the startup script itself continue to run, but here's an approach that I think accomplishes what you're trying to do, namely start tcpdump and have it continue to run immune to hangups via nohup. I've simplified things a bit for illustrative purposes - feel free to add any variables back as you see fit, such as the nohup.out output directory, TIMESTAMP, etc.
Script #1: tcpdump_start.sh
#!/bin/sh
rm -f nohup.out
nohup /usr/sbin/tcpdump -ni eth0 -s 65535 -w file_result.pcap &
# Write tcpdump's PID to a file
echo $! > /var/run/tcpdump.pid
Script #2: tcpdump_stop.sh
#!/bin/sh
if [ -f /var/run/tcpdump.pid ]
then
kill `cat /var/run/tcpdump.pid`
echo tcpdump `cat /var/run/tcpdump.pid` killed.
rm -f /var/run/tcpdump.pid
else
echo tcpdump not running.
fi
To start tcpdump, just run tcpdump_start.sh.
To stop the tcpdump instance started with tcpdump_start.sh, just run tcpdump_stop.sh.
The captured packets will be written to the file_result.pcap file, and yes, it's a pcap file, not a text file, so it helps to name it with the proper file extension. The tcpdump statistics will be written to the nohup.out file when tcpdump is terminated.
I too had faced problems when running tcpdump over an SSH session.
In my case, I was running
sudo nohup tcpdump -w {pcap_dump_file} {filter} > /dev/null 2>&1 &
Where, running this command over Paramiko SSH session as a background process was the problem.
To get around this, I used screen utility of Linux.
screen is an easy to use tool for long-running of processes as a service.
Might be an old post, but this is also relevant. I couldn;t understand why no file was being created only to realise that the file might not be created until a certain amount of data had been captured.
https://github.com/the-tcpdump-group/tcpdump/issues/485

Shutting Down Windows Network Using Bash

Here's my current code, which works but is slow
for i in {1..255..1}; do
for j in {1..255..1}; do
ip="10.8.$i.$j"
sudo net rpc shutdown -I $ip -U Username%Password -t 1 -f
echo $ip
done
done
I would like to be able to go through these IPs and attempt to shut them down. But if there is not a PC at that IP it has to wait for it to timeout before attempting the next one. So how can I find and shutdown all windows PCs on a network? (they all have the same credentials)
A trivial solution is to just run a pile of them in parallel:
for i in {1..255..1}; do
for j in {1..255..1}; do
ip="10.8.$i.$j"
sudo net rpc shutdown -I $ip -U Username%Password -t 1 -f &
echo $ip
done
wait
done
This runs 255 at a time and waits for them all to finish. Smarter and more flexible parallelization can be had through xargs, sem or parallel if Windows supports that.

autossh exit when using the -f option

When running autossh without the "-f" option, everything works fine.
Adding the "-f" option indeed sends autossh to the background, but after the ssh tunneling established correctly the autossh itself exit, leaving the ssh connection without monitor.
Here is the command I'm running: autossh -f -M 20000 -N -L 0.0.0.0:5601:10.10.0.8:5601 10.10.0.8
Anyone knows what can cause this problem? alternatively - anyone knows how can I debug autossh when using the "-f"? (is there any log file produce when using AUTOSSH_DEBUG=1)?
(I'm running on Ubuntu 14.04)
Thanks,
Shay
Seeing as no one has a better suggestion... Try running autossh under a watchdog like daemontools. With this method autossh runs as a foreground child of a supervise daemon (so, no -f switch). You can start and stop it with the svc command, and you can log all of its output with multilog.
This method has proven sufficiently reliable for me, on a fleet of production boxes.
On macOS I had a problem where autossh -M 0 -R 1234:localhost:22 worked but adding -f to make autossh run in background would log the following and autossh would die instantly:
2018/04/10 12:00:06 autossh[67839]: ssh exited with status 0; autossh exiting
Adding -N ("Do not execute a remote command.") fixed the issue:
autossh -f -M 0 -N -R 1234:localhost:22
Seeing you already had -N in the command this is probably unrelated but possibly helpful to others.

how to terminate a process which is run with sudo? Ctrl+C do it, but not kill

At my company, some commands are allowed to run with sudo, such as tcpdump. Others not.
I expect run tcpdump for a while, and then stop it.
When I run tcpdump, and I could abort that with Ctrl+C
I wrote a shell script like this -
#!/bin/sh
sudo tcpdump -ieth1 -w ~/dump.bin
sleep 5
kill -2 $!
it doesn't really work. The process of tcpdump is run as root, and current user is a normal account.
My question is: is there any way to do the equivalent of ctrl c in bash script?.
EDIT:
ps:As my company's security policy, I cannot run kill as root.
Try the -Z option to tcpdump. It instructs tcpdump to drop root privileges and run as the user specified in the argument.
sudo tcpdump -Z $USER -ieth1 -w ~/dump.bin
Now try killing that process.
Simply run kill through sudo as well:
sudo kill -2 $!
This way the kill process will have the privilege to send signals to a process that runs as root.
For programs that don't have special switches like -Z and in case you can alter sudoers file, this is a solution:
sudo myprogram &
sleep 5
sudo pkill myprogram
All I have to do is to allow to run pkill myprogram passwordless by using visudo and adding this line:
myuser ALL=(ALL) NOPASSWD:/bin/pkill myprogram
This is less dangerous that lo let sudo kill any program.
The timeout command also terminates a program after so long. sudo timeout 5 tcpdump -ieth1 -w ~/dump.bin should accomplish the same thing as the script.
sudo tcpdump -Z root -w ~/dump.bin -n -i eth0 -G 300 -W 1
G - Timeout Seconds (After timeout period the comman gets killed automatically)
Z - drop root and runs as user privilege
W - Number files to be saved (as a splitted file)
sudo tcpdump -ieth1 -w ~/dump.bin
will block your script, you need to put it into the background:
sudo tcpdump -ieth1 -w ~/dump.bin &
.
This and the answer from Blagovest should do it.

Resources