Socat

From Leo's Notes
Last edited on 22 September 2022, at 20:58.

socat is a utility to relay data between two data channels. Channels that socat supports includes files, pipes, devices, sockets, raw IP sockets, and more, and more. It can be regarded as a more advanced version of netcat.

Introduction

socat takes in options and two addresses. socat [options] <address> <address>

  • Both addresses are formatted as protocol:ip:port,options.
  • Protocol could be: TCP4, CREATE, EXEC, GOPEN, STDIN, STDOUT, PIPE, PTY, UDP4 and more
  • Protocol options come after the address and are separated by commas. Common ones include:
    • retry=5 - to retry
    • fork - to handle multiple connections
    • creat (open group only) - to create a file or pipe
    • trunc (open group only) - truncates a file
    • append (open group only) - appends to a file


By default, socat creates a unidirectional byte stream between the two addresses. In other words, there will be two byte streams that transfers data to/from both streams. You can make socat only transfer data in one direction with the -u option which ensures that the first address is read to the second address only.

Examples

Description Command
Connect to TCP port 80, similar to netcat 10.1.1.1 80 socat - tcp4:10.1.1.1:80
TCP port forwarder socat tcp4-listen:80 tcp4:10.1.1.1:80
TCP port forwarder to support multiple connections socat tcp4-listen:80,fork,reuseaddr tcp4:10.1.1.1:80
TCP port listener, on a specific IP socat tcp4-listen:80,fork,reuseaddr,bind=10.1.1.2 tcp4:10.1.1.1:80
SSL terminate using a SSL certificate socat openssl-listen:443,fork,reuseaddr,cert=server.pem,verify=0 tcp4:10.1.1.1:80
Expose a MySQL socket via TCP socat tcp-listen:3306,reuseaddr,fork unix-connect:/var/lib/mysql/mysql.sock
Convert a TCP socket into a local socket socat UNIX-LISTEN:/var/lib/mysql/mysql.sock,fork,reuseaddr,unlink-early,user=mysql,group=mysql,mode=777 TCP:192.168.100.5:3306
Network collector socat -u tcp4-listen:3333,reuseaddr,fork open:/tmp/test.log,creat,append
Send a broadcast to the local network from stdin. socat - UDP4-DATAGRAM:224.255.0.1:6666,bind=:6666,ip-add-membership=224.255.0.1:eth0

Tasks

Make a read-only copy of the Docker daemon socket

Possibly run socat in a separate container image that serves the socket out on a particular port? Eg: socat -u /var/lib/docker.sock tcp4:172.20.1.1:6000

Intercepting Unix Socket Data

If you want to see data sent to and from a Unix socket, one way is to proxy the socket on a TCP port, then create a new socket that forwards to this port, and then use tcpdump to capture any traffic.

For example:

## Say we want to see all traffic to /var/socket.sock
## Move the original socket elsewhere
# mv /var/socket.sock /var/socket-org.sock
## Make socat listen on 8888 for the original socket
# socat TCP-LISTEN:8888,reuseaddr,fork UNIX-CONNECT:/var/socket-org.sock &
## Create a new socket with the original name and proxy all traffic to port 8888, which then gets redirected to the original socket with the first socat
# socat UNIX-LISTEN:/var/socket.sock,fork TCP-CONNECT:127.0.0.1:8888 &
## Dump all traffic on port 8888
# tcpdump -i lo -netvvvXSs 1514 port 8888

SSL terminate using a self signed certificate

First, generate a self signed SSL certificate: For example:

$ openssl genrsa -out server.key 4096
$ openssl req -new -sha256 -key server.key   -subj "/C=CA/ST=Alberta/O=Steamr/CN=server.steamr.com" -out server.csr
$ openssl x509 -req -days 730 -signkey server.key -in server.csr -out server.crt
$ cat server.key server.crt > server.pem

Then, start socat using this certificate. Set verify=0 so that the client does not require a certificate to connect back to socat.

$ openssl-listen:443,fork,reuseaddr,cert=server.pem,verify=0 tcp4:10.1.1.1:80

See also