Socat
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
- https://gist.github.com/mario21ic/c09f0a648130ad6a91abdde41cb011c8
- https://copyconstruct.medium.com/socat-29453e9fc8a6
- http://www.dest-unreach.org/socat/doc/socat.html#ADDRESS_TCP_LISTEN
- https://stuff.mit.edu/afs/sipb/machine/penguin-lust/src/socat-1.7.1.2/EXAMPLES - Examples!