Socat, netcat, nc, tcpserver and open source "moulé sous les aisselles".

In my last post, I explored Laurent Bercot's premisce that for making a piped based server requiring a script to only know how to talk on stin/stdout tcpserver we don't need no systemd.

I experimented with tcpserver, and it worked fine.

I also « stofled » (went my way trhough stack overflow's answers) the topic and re-discovered nc, netcat, socat possible alternatives to tcpserver.

Well, as a first, all these tools are great. But, one conquered my heart : socat.

First, all honests persons should state their bias : I am a linux user since 1993 (slackware, debian) and since systemd have got some freeBSD, openBSD, and devuan. I long for systems that are idiot friendly. A special kind : the one that are not afraid to read the documentation and go on the web page of the software to get the upstrem documentation.

For famlily reasons, my main battle-station is a 12 yo core i3 with linux mint so to say debian, hence software are rarely conforming with upstream vanilla since debian political commisars have got weired ideas about how to package software.

But first, before this long digression about a certain idea of free software, let's remind the core of the problem :

Making a shell script act as a server by reading from stdin, writing to stdout and having a magical stuff transforming the shebang in a multi-connection server.

An echo server would probably look like :
while [ 1 ]; do
    read a
    echo $a
    echo $( export ) # maybe the server can see our IP address in the environment variables set ?
done
And with telnet if you connect on the port this server listen to everything you write is repeated.

Let's review the « There Is More Than One Way To Do It » (Perl's (in)famous TIMTOWTDI vs python « one best way » state of mind).
 tcpserver 127.0.0.1 1234 ./echo.sh 
https://cr.yp.to/ucspi-tcp/tcpserver.html . A tool smelling of BSD's spirit of doing one thing and only one thing well.
Netcat's way. Well. They are 3 netcats !
  • The root of all nc «hobbit» netcat, that is not available anymore ;
  • the openBSD netcat fork (also called nc) providing more protocols ;
  • the NMAP fork providing the -e option that I need (also called ncat) ;
As a result you can only do the same as tcpserver with NMAP's netcat (aka ncat) :
ncat -nlvp 1234 -e echo.sh 
Where l means listen, p port, n stand for numeric dotted quad IP address, v is verbose, e stands for execve. Trust me explainshell.com does an awesome job at explaining command line arguments in a readable way better than me.

And then, there is socat's way :
socat        TCP4-LISTEN:1234,bind=127.0.0.1,fork,reuseaddr  EXEC:"./echo.sh" 
All of these servers are accessed by doing :
  • telnet localhost 1234
  • nc localhost 1234
  • /usr/local/bin/socat READLINE TCP:localhost:123
  • and in the previous post you can also roll your own client to have history with tcpclient


So far, all these tools DO what I want, and they all transmit the IP/PORT of the client with the same convention (TOOLS)_PEERADDR, (TOOLS)_PEERPORT where tools can be SOCAT, NCAT, TCPSERVER (check yourself).

So, all these tools are equals, benchmarking over, choosing the right tool is a question of taste and religion. Over.

Or is it ? ... my religion


I may love concision, but concision sometimes does not help memory. Socat raises above all else by being user friendly but not idiot friendly.

Socat has an awesome PATTERN :
 socat [opt] SOURCE_FAMILY:args,opts DEST_FAMILY:args,opts
This make myself hate this tool for being overly verbose, but loving it for saving my precious memory muscle. For instance, READLINE is a family of source/dest that is a wrapper around stdin/stdout to provide history and line editing out of the box, which is AWESOME when you test a server repetively.

Since DEBIAN, is still so special by not providing upstream packages in their vanilla flavour, when you try READLINE source with debian based distro you will have this cryptic error :
$socat    READLINE   TCP:localhost:1234
2024/05/16 10:14:10 socat[5947] E unknown device/address "READLINE"
Requiring you to visit the upstream provider of socat and enjoy a free software « moulé sous les aisselles à l'ancienne ».

I mean, no git, no reactive website, nothing fancy, first the changelog, a tarball with checksums you can download and a man page with examples.

Ah ! It reminds me so much of my early days on linux. And a golden nugget hidden in the not that obvious link to the repos.
Curated examples commented by the author (you also have in the man page)

I think it even beats openBSD amish's style by being feature rich and consistent.

So, because I WANTED my socat with READLINE I had to compile it, and it was a delight a ./configure for portability, and even though linux may not be the primary target I had very few warnings, few of them being scary.

Oh, and there is a test suite in bash (that I red of course) and it ... was nice to check the compiled software against the expectation of the author. I have a bug in the interaction between READLINE and openSSL.

And you see also an hidden nugget of a broker + fanin/fanout network pattern example in shell that makes me question my usage of ZMQ (I basically use ZMQ only for this).

At this level, I think my will for benchmarking went out of the technical path to become much more fandom.

I mean, it even has CHROOTING out of the box, pf integration, (very) basic ingres/outgres control (CDB), SSL tunneling, cork screwing (very specific options to pass ill configured firewall with UDP), STUN like features (another way of firewall piercing) explained in a concise but funny way.

It's like christmas before christmas, with nice gift falling from the sky with mnemonics strengthening my sysadmin usage of sockets (nodelay, lingering, addresse reuse and other options that are coined as everyone everywhere else).

socat is my new favourite tool because it has a learning curve that totally worths it. It is fitting my brain topology nicely, maybe not yours.

/me <3 gerhard at dest-unreach.org

No comments: