bash receive udp packets tcpdump - bash

On one server, I am receiving udp packets on 192.168.0.51 from an application running on 192.168.0.21, and have to reply with a specific acknowledgement packet.
The solution I wrote works as following:
#!/bin/bash
send_ack() {
<calculate $ack - code removed>
echo -n "$ack" | nc -u -w1 192.168.0.21 8076
}
while [ 1 ]
do
for string in $(/usr/sbin/tcpdump -Avnni eth0 -c 1 dst 192.168.0.51 and udp port 8076)
do
send_ack &
done
done
The issue is that I seem to have some running condition when packets arrive too quickly, I guess they arrive before tcpdump restarts.
I tried -l for single line buffer instead of -c 1 to no success.
Would anyone have any ideas of how to solve this issue?
Thanks, looking forward :)

The problem in your program is that packets will slip by in between tcpdump invocations, since you're just running it to capture a single packet using -c 1 and then exiting again each time.
The solution would be to run tcpdump continuously in line buffered mode (-l) with its output piped to a process reading that.
#!/bin/bash
# tcpdump line buffered and piped to infinite loop
/usr/sbin/tcpdump -Avnni eth0 -l dst 192.168.0.51 and udp port 8076 | \
while true; do
# read output line by line
read result
# only act on non-blank output
if [ "$result" != "" ]; then
echo "Read a packet: $result"
# perform whatever action
send_ack &
fi
done
In addition to this you may also want to experiment with the -B option to tcpdump which lets you set the buffer size, and with different options for read.

Related

How to close netcat connection after receive a server response?

I need to sendo a lot of messages via netcat or something similar. The problem is that when I run echo "something" | netcat ip port the connection continues opened after I received the response. Actually the connection continues opened waiting for a new input. However, what I need is that the connection closed after I receive the response. Look, my script is basically this:
#!/bin/bash
i=1
while [ $i -ne 10000 ];do
sed -n $[i]p wordlist | netcat localhost 30002 >> result
i=$[$i+1]
done
If I can close the connection after print the response in result, everything will work fine. I know that there is an option -w "x" that closes the connection after "x" seconds, but the minimum value for "x" is 1 and 1 is bigger than I can wait, I need close the connection as soon as possible.
Unfortunately, the -q flag didn't work for me.
I'm using "OpenBSD netcat (Debian patchlevel 1.187-1ubuntu0.1)" and, even though the -q flag shows up in the manual, it didn't work as mentioned in cnicutar's answer.
Therefore, my workaround was:
#!/bin/sh
# POSIX COMPLIANT
HOST="localhost"
PORT=30002
scan () {
# Ensuring there is no file named msg
rm msg
# While msg file doesn't exist or is empty, do
while [ ! -s msg ]; do
# Remove instruction from within the loop
rm msg
# Append the received messages to msg file, and put the process in the background
echo "$HOST $PORT" | xargs nc >> msg &
# If the file exists and is not empty, return, we received the message
[ -s msg ] && return;
# A small timeout.. doing some tests I noticed that a timeout of zero sometimes didn't work to catch the message
# Maybe nc needs a small time to receive everything. You might want to test and increase or decrease this timeout if needed.
sleep 0.1
# This script will be spawning a lot of nc process, to kill it before the loop runs again
pkill -x nc
done
} 2> /dev/null
scan
# The function returned, so cat the file
cat msg
# make sure nc is killed
pkill -x nc > /dev/null 2>&1
rm msg
What you're looking for is the -q switch. If you specify:
netcat -q 0 localhost 30002
netcat will exit immediately.

Read and write to the same netcat tcp connection

Say I write to a netcat connection:
tail -f ${file} | nc localhost 7050 | do_whatever | nc localhost 7050
what happens here is that we have two socket connections, to do some request/response. But that's not ideal for a few reasons.
What I am looking to do is reuse the same connection, to read from and write to.
Does anyone know how I can reuse just one netcat connection?
The correct way to do this in UNIX is to make use of a back pipe. You can do so as follows:
First, create a pipe: mknod bkpipe p
This creates a file named bkpipe of type pipe.
Next, figure out what you need to do. Here are two useful scenarios. In these, replace the hosts/addresses and port numbers with the appropriate ports for your relay.
To forward data sent to a local port to a remote port on another machine:
nc -l -p 9999 0<bkpipe | nc remotehost 7000 | tee bkpipe
To connect to another machine and then relay data in that connection to another:
nc leftHost 6000 0<bkpipe | nc rightHost 6000 | tee bkpipe
If you simply need to handle basic IPC within a single host, however, you can do away with netcat completely and just use the FIFO pipe that mknod creates. If you stuff things into the FIFO with one process, they will hang out there until something else reads them out.
Yeah, I think the simplest thing to do is use this method:
tail -f ${file} | nc localhost 7050 | do_whatever > ${file}
just write back into the same file (it's a 'named pipe').
As long as your messages are less than about 500 bytes, they won't interleave.
Using ncat is much easier and understandable for beginners as a one-liner ;)
prompt$> ncat -lk 5087 -c ' while true; do read i && echo [You entered:] $i; done'
Connect with telnet (or nc) to localhost port 5087, and everything you type echoes back to you ;)
Use -lk option for listening and keeping/maintaining (multiple) connections.
You can make one bash script out of it like this, using back slashes but it invokes multiple bash, not cheap on resource usage:
#!/bin/bash
# title : ncat-listener-bidirectional.sh
# description : This script will listen for text entered by a client
# like for instance telnet
# and echo back the key strokes
#
ncat -lk 5087 -c ' \
#!/bin/bash \
while true; do \
read i && echo [You entered:] $i; \
done'

Test if netcat listener got a connection and run a command locally

I need a way to fire a netcat listener from a shell script and if a connection received I need to run a command on the same local listener machine and without interrupting the netcat process / connection
it's like the -e option but I need to run a command locally while keeping the netcat connection running
I don't really know if it can be done I mean after the shell process forked the netcat child can it interact with nc's output for example and run other command before netcat exit?
Edit: I figured it's even easier to do it on the client C code side by checking the return value of an initial send() message to determine if the client connected successfully if we got the sent message length
sret = send(sock, message, strlen(message), 0);
if (sret == strlen(message)) // We're Connected
do something
Thanks
This will check if the initial nc process has started listening, and it will echo every line of input it receives and will then send back a Received response:
rm -f input.txt
touch input.txt
tail -f input.txt | nc -l 5555 > output.txt &
if ! ps -p $! >/dev/null; then
echo "Netcat didn't start. Exiting..."
exit 1
fi
tail -f output.txt | while read -r LINE; do
echo "Received input: $LINE"
echo "Received" >> input.txt
done
See if you can adapt this to meet your needs.

How can I terminate netcat so my script can loop again?

I'm running a bash script that goes through the list of my remote server IPs, connects via netcat (telnet) for each line, and runs a few commands.
The problem is I can't seem to figure out how to terminate netcat so the script can loop to the next IP in the list.
Here's the relevant bit:
#!/bin/bash
while ISF= read -r line;do
(
sleep 3
printf 'command1'
sleep 3
printf 'command2'
sleep 3
) | nc $line
done < ~/servers.txt
The remote servers don't send an EOF, so is there something I can echo or printf at netcat to terminate netcat so the script can loop through again? I would really rather not do a -w flag for a timeout, because I have quite a few servers I need to do this on, and a timeout would make it take much longer.
Specify a timeout after which nc will exit if it receives no further input, either from the remote end or via standard input.
... | nc "$line" -w 10 # Choose a value for -w as appropriate
Depends on your version of netcat, but -c should do what your looking for. From the usage statement of gnu netcat (which is likely what you're running on Ubuntu):
-c, --close close connection on EOF from stdin

Bash: monitoring TCP socket activity

I use mpg123 to read an mp3 webradio stream (port 8000).
Sometimes, the webradio server stops but mpg123 doesn't quit. Also, if the network on my machine fails, mpg123 won't quit either.
I would like to monitor mpg123 activity using a bash script launched by cron.
Something like this:
tcpdump -i eth0 port 8000 2>/dev/null | head | wc -l &
sleep 5
killall tcpdump
If no stream is played by mpg123, the result will be 1. Otherwise, it will be > 1.
How can I get this result into a variable?
Then I could relaunch mpg123 if the streaming has failed.
Note that I can't use the timeout command and I can't write anything on my system.
possibly
isitthere=$(tcpdump -i eth0 port 8000 2>/dev/null | head | wc -l & sleep 5; killall tcpdump)
if [[ $isitthere -eq 1 ]]
then
SET FIRE TO EVERYTHING
fi
not sure if it'd handle the sleep 5. But can't you use a -ll switch on tcp dump so..
worth a shot.

Resources