Underrated Socat

3 minute read

Socat

Socat is one of the most underrated software in Linux. It is a tool to help in debugging and applying network interops in ways the original author of a software probably had not anticipated. The author of socat describes it as multipurpose relay software (socket cat). People lovingly synonymize it as like cat but for sockets. I first came across socat when I was working as a pentester back in the day (I have worn many hats in the past) whilst trying to work my way through protocol debugging.

TL;DR? Refer to the commands instead.

The socat story

So, why would you need socat? Follow through on the fictionalised story below 1.

Let’s pretend that we want to have a TCP client sitting locally to be able to connect to a TCP server sitting elsewhere on port 3450; i.e., a TCP network clients connect to a TCP socket on the server at port 3450. This is the trivial part and software libraries have evolved to abstract almost 99% of this game so engineers can have a good sleep.

Now, here’s the catch - say that Bob the sysadmin appeared on the deck of this ship and said that clients can only connect to TCP sockets on the server on port 80 and 443 2

You can use many tools in Linux and *BSDs (and that’s the beauty of it - each to their own) to achieve the precise outcome (HAProxy, Nginx, iptables DNATs, SSH port forwards, IPsec tunnels, sshuttle, Wireguard etc..) but in this instance I would like to focus only on socat.

So, how could socat be of help here for a quick win? The TCP client will now connect to the server on port 80. That is, the TCP endpoint to the client will look like server.ip.address:80.

On the server, Bob, the sysadmin will spin up socat and run a TCP relay from the listening TCP port 80 to the local loopback address’ TCP port 3450. Thus, Bob, the sysadmin will run this on the server:

$ socat -v tcp-listen:80,reuseaddr,fork tcp-connect:127.0.0.1:3450

This will relay all TCP packets that connect to the server on port 80 to be sent to 127.0.0.1 on port 3450. As socat accepts a TCP client connection on port 80, it will fork a new child process, set up a bi-directional socket pairs on the child process and forward all incoming and outgoing TCP packets via these descriptors. The parent process will continue to service new TCP connections.

Until a permanent solution is in place2, Bob can now proceed to block non-standard TCP port to ingress the server.

socat the swiss-army knife

An exhaustive list of socat capabilities is documented in the manual page for socat(1) and it is still the authoritative source. Below are some common ones one might need.

Relay TCP to TCP

$ socat -v tcp-listen:80,reuseaddr,fork tcp-connect:172.16.2.10:8080

Relay TCP to UDP

$ socat -v tcp-listen:80,reuseaddr,fork udp-connect:172.16.2.10:8080

Relay UDP to UDP

$ socat -v udp-listen:80,reuseaddr,fork udp-connect:172.16.2.10:8080

Relay UDP to TCP

$ socat -v udp-listen:80,reuseaddr,fork tcp-connect:172.16.2.10:8080

Relay TCP to Unix Domain Sockets

$ socat -v tcp-listen:80,reuseaddr,fork unix-client:/var/run/uds.sock

Relay Unix Domain Sockets to TCP

$ socat -v -v unix-listen:/var/run/uds.sock,reuseaddr,fork tcp-connect:172.16.2.10:80

Relay UDP to Unix Domain Sockets

$ socat -v udp-listen:80,reuseaddr,fork unix-client:/var/run/uds.sock

Relay Unix Domain Sockets to UDP

$ socat -v -v unix-listen:/var/run/uds.sock,reuseaddr,fork udp-connect:172.16.2.10:80

Relay SCTP to Unix Domain Sockets

$ socat -v sctp-listen:80,reuseaddr,fork unix-client:/var/run/uds.sock

Relay Unix Domain Sockets to SCTP

$ socat -v -v unix-listen:/var/run/uds.sock,reuseaddr,fork sctp-connect:172.16.2.10:80

Tunnel Unix Domain Socket packets inside TLS relay

Please avoid setting verify=0 on production if you can.

$ socat -v                                          \
    unix-listen:/var/run/uds.sock,reuseaddr,fork    \
    openssl:server.domain.name:443,certificate=cert.pem,cafile=cert.pem,verify=1,key=key.pem,commonname=server.domain.name

Relay TLS packets to Unix Domain Socket (aka virtual patching)

$ socat -v                                                                                             \
    openssl-listen:443,reuseaddr,pf=ip4,fork,key=key.pem,cafile=cert.pem,cert=cert.pem,method=TLS1.2   \
    unix-client:/var/run/uds.sock

Capture TLS packets to /dev/stdout for quick debugging

Please avoid setting verify=0 on production if you can.

$ socat -v                                                                                       				\
    openssl-listen:443,reuseaddr,pf=ip4,fork,key=key.pem,cafile=cert.pem,cert=cert.pem,verify=0,commonname=server.domain.name	\
    file:/dev/stdout

Feel free to drop me a comment if anything. Until next time adios!


1 Everything in this story is fictional and has been trivialised for the purpose of simplicity. I am a big fan of KISS philosophy although I haven’t had the time to listen to the band KISS at all :smile:.

2 Let’s pretend that there is a forcing function here.

Updated:


If you like the post, feel free to support me via BuyMeACoffee or Patreon.

Buy Me A Coffee

Patreon

Thank you.

Leave a Comment