Dienstag, 2. August 2022

Linux named pipes - a nice discovery in the hand of netcat

 Most of the software developer have implemented an application with an REST interface. The nice thing working with REST is, that for testing or whatever purpose, an curl request can be made. But what if the application speaks with a protocol which contains binary data or a binary header. What makes it worse is, if the protocol has its own hand shake and therefor it is needed to send different network frames  depending on requests or responses of the communication partner. It would be nice if that could be all done with a tool like netcat (nc). It is possible using netcat reading from a fifo or named pipe.    

Creating a named pipe is easy:

:~$ mktemp -d
/tmp/tmp.6FxU69SgTJ

:~$ mkfifo /tmp/tmp.6FxU69SgTJ/fifo

:~$ ls -l /tmp/tmp.6FxU69SgTJ
prw-r--r-- 1 user group 0 Aug  2 12:14 fifo

Now there is a fifo under a temporary directory and the first steps are done with cat. cat is used with the input from the fifo.
:~$ cat < /tmp/tmp.6FxU69SgTJ/fifo
cat is now waiting on input from the fifo. Currently it is blocked on the fifo because the reader on a fifo is blocked for a writer. If something is written o a different shell with the help of echo, it can be seen that the cat command print the result but also finished, which is not the expecting result.
:~$ echo something > /tmp/tmp.6FxU69SgTJ/fifo/
:~$ cat < /tmp/tmp.6FxU69SgTJ/fifo/
something
:~$

After looking a little bit around in the internet and especially on stackoverflow, the shell builtin command exec comes into the game. It is possible to open a new stream and redirect all to the fifo. First start the cat command again:
:~$ cat < /tmp/tmp.6FxU69SgTJ/fifo/
Redirect all output via filedescriptor 3 to the fifo.
:~$ exec 3> /tmp/tmp.6FxU69SgTJ/fifo/
Now it is possible to write some words with echo and the cat command is showing them all without to stop.
:~$ echo some > /tmp/tmp.6FxU69SgTJ/fifo/
:~$ echo command > /tmp/tmp.6FxU69SgTJ/fifo/

# The cat command in the other shell
:~$ cat < /tmp/tmp.6FxU69SgTJ/fifo/
some
command

As the output from 3 redirected to the fifo it is a bit more easier to redirect stdout to 3 and not to the fifo directly because 3 is always directed to the fifo.
:~$ echo some >&3 
:~$ echo command >&3

# The cat command in the other shell
:~$ cat < /tmp/tmp.6FxU69SgTJ/fifo/
some
command

Now it is time to try the whole thing with netcat:
# start a new shell with a netcat listener which gets the commands from echo
:~$ netcat -l -p 2628 < /tmp/tmp.6FxU69SgTJ/fifo/

# start a new shell with a netcat client
:~$ netcat localhost 2628

# now we get the netcat listener to do what we say (here with some binary data which does not make sense here but in different cases)
echo -n -e '\x02\x00\x00\x09\x03Some' >&3
echo -n -e '\x02\x00\x00\x0C\x03Command' >&3 

# the netcat client received all the frames we send via echo to the fifo. 
# We can't really display the binary data here.

Do not forget the close the filedescriptor after usage, otherwise it stays open and can't be used in other cases.
:~$ exec 3>&-

Without the internet especially stackoverflow, I would never get to that solution. With the help of this functionality it is much more easier to play with some network protocols. Thanks to all the people who share their knowledge.