Send text file, line by line, with netcat - shell

I'm trying to send a file, line by line, with the following commands:
nc host port < textfile
cat textfile | nc host port
I've tried with tail and head, but with the same result: the entire file is sent as a unique line.
The server is listening with a specific daemon to receive data log information.
I'd like to send and receive the lines one by one, not the whole file in a single shot.
How can I do that?

Do you HAVE TO use netcat?
cat textfile > /dev/tcp/HOST/PORT
can also serve your purpose, at least with bash.
I'de like to send, and receive, one by one the lines, not all the file in a single shot.
Try
while read x; do echo "$x" | nc host port; done < textfile

OP was unclear on whether they needed a new connection for each line. But based on the OP's comment here, I think their need is different than mine. However, Google sends people with my need here so here is where I will place this alternative.
I have a need to send a file line by line over a single connection. Basically, it's a "slow" cat. (This will be a common need for many "conversational" protocols.)
If I try to cat an email message to nc I get an error because the server can't have a "conversation" with me.
$ cat email_msg.txt | nc localhost 25
554 SMTP synchronization error
Now if I insert a slowcat into the pipe, I get the email.
$ function slowcat(){ while read; do sleep .05; echo "$REPLY"; done; }
$ cat email_msg.txt | slowcat | nc localhost 25
220 et3 ESMTP Exim 4.89 Fri, 27 Oct 2017 06:18:14 +0000
250 et3 Hello localhost [::1]
250 OK
250 Accepted
354 Enter message, ending with "." on a line by itself
250 OK id=1e7xyA-0000m6-VR
221 et3 closing connection
The email_msg.txt looks like this:
$ cat email_msg.txt
HELO localhost
MAIL FROM:<system#example.com>
RCPT TO:<bbronosky#example.com>
DATA
From: [IES] <system#example.com>
To: <bbronosky#example.com>
Date: Fri, 27 Oct 2017 06:14:11 +0000
Subject: Test Message
Hi there! This is supposed to be a real email...
Have a good day!
-- System
.
QUIT

Use stdbuf -oL to adjust standard output stream buffering. If MODE is 'L' the corresponding stream will be line buffered:
stdbuf -oL cat textfile | nc host port

Just guessing here, but you probably CR-NL end of lines:
sed $'s/$/\r/' textfile | nc host port

Related

How to send named-pipe to all connected clients (Bash)

I have a named pipe, to which I output log informations from several scripts. I need to make a TCP server, which sends these informations to connected clients. For one client solution, this worked fine:
tail -f name_of_pipe | nc -lk $tcp_port
Is there some effective way, how to send the content to multiple clients? I think netcat does not support multiple clients. I have found that there is utility named tcpserver from ucspi-tcp, which executes new process for each client, but this won't do what I want - Each line will be read out from named pipe and delivered just to one random client.
In fact, I don't need named pipe acting like FIFO, I can throw away everything before client has connected and send just real-time data.
Something like this?
$ echo "Bye bye" | tee >( cat ) | tee >( cat ) | cat
Bye bye
Bye bye
Bye bye
Bye bye

How to extract IP address from log file and append it to an URL?

Log file contains this line.
Nov 28 21:39:25 soft-server sshd[11946]: Accepted password for myusername from 10.0.2.2 port 13494 ssh2
I want to run the curl command only if the log file contains the string "Accepted password for" and append the IP address to URL.
Something like this:
if [ grep -q "Accepted password for" var/log/auth.log]
then
curl 'www.examplestextmessage.com/send-a-message/text=$IP_address'
fi
Additionally, how to rewrite the above script which can check multiple logins and to run separate curl commands for each results?
for eg:
Nov 28 21:35:25 localhost sshd[565]: Server listening on 0.0.0.0 port 22
Nov 28 21:39:25 soft-server sshd[11946]: Accepted password for myusername
from 10.0.2.2 port 13494 ssh2
Nov 28 21:40:25 localhost sshd[565]: Server listening on 0.0.0.0 port 22
Nov 28 21:41:25 localhost sshd[565]: Server listening on 0.0.0.0 port 22
Nov 28 21:42:25 localhost sshd[565]: Server listening on 0.0.0.0 port 22
Nov 28 21:43:25 soft-server sshd[11946]: Accepted password for myusername from 10.0.1.1 port 13494 ssh2
grep -oP 'Accepted password for \w+ from\s\K[^ ]+' log.file|while read line;
do
curl "www.examplestextmessage.com/send-a-message/text=$line"
done
Explanation:
First grep will list the IP addresses from the line containing the words "Accepted password for". Then the stream of grep result is feeded into while loop to append ip addresses to curl and execute curl.
1 line script with xargs:
grep -oP 'Accepted password for \w+ from\s\K[^ ]+' "/var/log/auth.log" | xargs -I{} -r curl -v -L "www.examplestextmessage.com/send-a-message/text={}"
xarg -r If the standard input is completely empty, do not run the command. By default, the command is run once even if there is no input.
xarg -I{} option changes the way the new command lines are built. Instead of adding as many arguments as possible at a time, xargs will take one name at a time from its input, look for the given token ({} here) and replace that with the name.
Explanation :
grep the content "Accepted password for"
From result set find ip address using awk/cut
use IP address list as input for loop
below is code example
for IP_address in `cat auth.log | grep 'Accepted password for' | awk '{print $11}'`
do
curl "www.examplestextmessage.com/send-a-message/text=$IP_address"
done
Another option for completeness is sed using -E to cater for regular expressions:
sed -En 's/(^.*Accepted password for )(.*)( from )(.*)( port.*$)/\4/p'
This will split the text into five separate sections signified by extracts in between brackets. We then focus on the 4th extract to get the ip address

How to add something after a line grep found?

I would like to see whenever the ping to a specific server goes down.
So at the moment I have something like this: ping 8.8.8.8 | grep time=11 && date
This pings google and prints every line that has a ping of 11.x that is just for testing so that I have some output that is not there all the time but often enough that I can test this. And then I have && date that I thought would print the date when grep finds the string.. But it does not. So my question now Is how can I get it so that in every line that grep spits out I can append the current timestamp. Or what would be even better is to have it as a prefix in front of every line that grep spits out. Is this possible with one command? Or do I need a simple shell script?
Thanks in advance. I hope I get an answer soon. :)
Also merry x-mas to everyone!
See if it works for you:
ping 8.8.8.8 | while read line; do echo "$(date): $line"; done | grep time=13
You can also turn the setup around to check when a remote host becomes available by using while ! ping ... Example, in case your path to 8.8.8.8 goes down:
declare -i cnt=0; while ! ping -c 1 8.8.8.8; do ((cnt++)); echo "test '$cnt' - network down on $(date)"; sleep 60; done
Which will check once per-minute if the host 8.8.8.8 is available and report, for example:
test '10' - network down on Sat Dec 26 16:38:48 CST 2015
The script will terminate on its own once the network path is established.

Bad nmap grepable output

if i scan which nmap one target and i use output grepable option (-oG) if have this output
nmap -sS -oG - 192.168.1.1
Status: Up
Host: 192.168.1.1 () Ports: 20/closed/tcp//ftp-data///, 21/open/tcp//ftp///, 22/closed/tcp//ssh///, 43/closed/tcp//whois///, 80/open/tcp//http///
# Nmap done at Thu Dec 12 11:32:36 2
As you can see the line who indicate the ports number have no newline. For use grep it's no easy... :)
I'am on debian wheezy, i use bash, how can i correct this?
Thanks
Well, although they call it "grepable" output, it's more meant to be parsed by tools such as awk, sed or Perl.
Alot of useful information is on NMAP website.
The fields are also separated by tab characters, so i'd start with eg. cut -f5 file to get the fields you want and then you can do fine parsing with say awk -F/ '{print $2}'. I'm not sure what part of the output is of interest.
Perl would also work to parse the output as described on their webpage, but that's probably not needed.
There is nothing wrong with that output. Grepable format is designed to have one line per host, so that you can grep for all hosts with a particular port open.
If what you want is a list of only those ports that are open, you can tell Nmap to only print those with the --open option:
sh$ nmap -p 80,22 localhost -oG - -n -Pn --open
# Nmap 6.41SVN scan initiated Thu Dec 12 08:40:03 2013 as: nmap -p 80,22 -oG - -n -Pn --open localhost
Host: 127.0.0.1 () Status: Up
Host: 127.0.0.1 () Ports: 22/open/tcp//ssh/// Ignored State: closed (1)
# Nmap done at Thu Dec 12 08:40:03 2013 -- 1 IP address (1 host up) scanned in 0.08 seconds

Scripting an HTTP header request with netcat

I'm trying to play around with netcat to learn more about how HTTP works. I'd like to script some of it in bash or Perl, but I've hit upon a stumbling block early on in my testing.
If I run netcat straight from the prompt and type in a HEAD request, it works and I receive the headers for the web server I'm probing.
This works:
[romandas#localhost ~]$ nc 10.1.1.2 80
HEAD / HTTP/1.0
HTTP/1.1 200 OK
MIME-Version: 1.0
Server: Edited out
Content-length: 0
Cache-Control: public
Expires: Sat, 01 Jan 2050 18:00:00 GMT
[romandas#localhost ~]$
But when I put the same information into a text file and feed it to netcat through a pipe or via redirection, in preparation for scripting, it doesn't return the headers.
The text file consists of the HEAD request and two newlines:
HEAD / HTTP/1.0
Sending the same information via echo or printf doesn't work either.
$ printf "HEAD / HTTP/1.0\r\n"; |nc -n 10.1.1.2 80
$ /bin/echo -ne 'HEAD / HTTP/1.0\n\n' |nc 10.1.1.2 80
Any ideas what I'm doing wrong? Not sure if it's a bash problem, an echo problem, or a netcat problem.
I checked the traffic via Wireshark, and the successful request (manually typed) sends the trailing newline in a second packet, whereas the echo, printf, and text file methods keep the newline in the same packet, but I'm not sure what causes this behavior.
You need two lots of "\r\n", and also to tell netcat to wait for a response. printf "HEAD / HTTP/1.0\r\n\r\n" |nc -n -i 1 10.1.1.2 80 or similar should work.
Another way is to use what is called the 'heredoc' convention.
$ nc -n -i 1 10.1.1.2 80 <<EOF
> HEAD / HTTP/1.0
>
> EOF
Another way to get nc to wait for the response is to add a sleep to the input. e.g.
(printf 'GET / HTTP/1.0\r\n\r\n'; sleep 1) | nc HOST 80
You can use below netcat command to make your instance webserver:
MYIP=$(ifconfig eth0|grep 'inet addr'|awk -F: '{print $2}'| awk '{print $1}')
while true; do echo -e "HTTP/1.0 200 OK\r\n\r\nWelcome to $MYIP" | sudo nc -l -p 80 ; done&
This line will also work as equivalent:
echo -e "HEAD / HTTP/1.1\nHost: 10.1.1.2\nConnection: close\n\n\n\n" | netcat 10.1.1.2 80

Resources