Why is Crontab not starting my tcpdump bash script capture? - linux

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.

Related

Killing Socat and restarting it via a bash script

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.

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

Process continues to hold file after file deletion

I created a log file by running the iostat command to a text file, and ran the command in the background using nohup.
#nohup iostat -xm 5 > /z/logfile.txt &
Later on, I created a cronjob that runs every ten minutes doing the same as above, after I realized my process was being killed by a reboot.
I've also setup log-rotation as below:
/z/logfile.txt {
size 20M
rotate 0
create 0644 root root
missingok
notifempty
}
Now I have realized that the logfile.txt gets deleted but the iostat command keeps pointing at deleted files as shown by the lsof -n | grep deleted command. There the disk space is not freed.
How can I make sure the files are rotated and thereafter iostat points to the newly created file, freeing up disk space?
Any ideas how to set it up correctly?
One solution would be to write a program that will read from iostat, write to the output file, and accept a signal to reopen the file. For example, if you did: iostat -xm 5 | log-daemon /z/logfile.txt where log-daemon is a simple script like:
#!/bin/bash
echo $$ > /var/run/log-daemon
exec > $1
trap 'exec > $1' SIGHUP
read line
while test $? -le 0; do
echo $line
read line
done
Then add a postrotate clause in the logrotate config to send a HUP to the log-daemon:
postrotate
/usr/bin/kill -HUP $(cat /var/run/log-daemon)
Would pointing your cronjob iostat command at a softlink not work?
ln -s /z/logfile.txt iostat_link.txt
nohup iostat -xm 5 > /z/iostat_link.txt &
I haven't used logrotate before, but I tested this by manually changing the file in the background while I had this running:
#Make the files
touch afile1.txt
ln -s afile1.txt file.txt
#Kick off loop
for i in {1..1000};do echo "running still $i" >> file.txt;sleep 3;done &
[localhost (2017-05-15 20:30:55) IP: 26.176 ~]# cat afile1.txt
running still 7
running still 8
running still 9
#Change the file out from under the loop
mv afile1.txt afile1.txt.backup;touch afile1.txt
[localhost (2017-05-15 20:31:21) IP: 26.176 ~]# cat afile1.txt
running still 15
running still 16
running still 17
Check if file system where log is recording is full. If you have such a case find and kill process or reboot server in worst case.

How to run tshark commands from root mode in linux using TCL script ?

I am using linux pc and installed tshark . And have to capture packets in eth1 interface using TCL script. But tshark is running in root mode. Capturing and script running pc's are same. How to login as root and how to run tshark commands using TCL ? Please provide me a solution for this.
#!/usr/bin/tclsh
set out [exec tshark -V -i eth1 arp -c 1 ]
puts $out
Output
test#test:~$ tclsh pcap.tcl
Capturing on eth1
tshark: The capture session could not be initiated (eth1: You don't have permission to capture on that device (socket: Operation not permitted)).
Please check to make sure you have sufficient permissions, and that you have the proper interface or pipe specified.
0 packets captured
while executing
"exec tshark -V -i eth1 arp -c 1 "
invoked from within
"set out [exec tshark -V -i eth1 arp -c 1 ]"
(file "pcap.tcl" line 5)
test#test:~$
please try below steps and also refer this link http://packetlife.net/blog/2010/mar/19/sniffing-wireshark-non-root-user/
root#test:/usr/bin# setcap cap_net_raw,cap_net_admin=eip /usr/bin/dumpcap
root#test:/usr/bin# getcap /usr/bin/dumpcap
/usr/bin/dumpcap = cap_net_admin,cap_net_raw+eip
root#test:/usr/bin# exit
exit
test#test:/usr/bin$ tshark -V -i eth1
Capturing on eth1
Frame 1 (60 bytes on wire, 60 bytes captured)
Arrival Time: Aug 8, 2013 13:54:27.481528000
[Time delta from previous captured frame: 0.000000000 seconds]
[Time delta from previous displayed frame: 0.000000000 seconds]
You have to either elevate the privileges of your tshark process via sudo (or any other available means) or run your whole script with elevated privileges.
One way to do that which might be simpler than sudo as it would require zero customizations is to write a super-simple C program which would just run /usr/bin/tshark with the necessary arguments and then make that program setuid root and distribute along with your Tcl program. That is only needed if you need portability. Otherwise sudo is much simpler.

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