What it is
socat is a command-line utility that establishes bidirectional data streams between two endpoints. It’s like a universal socket redirector, useful for connecting diverse network protocols, files, pipes, and devices.
Installation
Linux
sudo apt update && sudo apt install socat
# or
sudo yum install socat
# or
sudo dnf install socat
macOS
brew install socat
Windows
socat is not directly available as a native Windows executable. The common approach is to use it within the Windows Subsystem for Linux (WSL).
- Install WSL: Follow Microsoft’s official guide to install WSL.
- Install socat within WSL: Once WSL is set up, open your Linux distribution (e.g., Ubuntu) and run:
sudo apt update && sudo apt install socat
Core Concepts
socat operates by connecting two addresses. An address defines an endpoint for data transfer. socat then relays data bidirectionally between these two connected addresses.
Common address types include:
- TCP:
tcp-listen:<port>,tcp:<host>:<port> - UDP:
udp-listen:<port>,udp:<host>:<port> - File:
file:<path> - STDIO:
stdios - Pipes:
pipe:<path> - PTY (Pseudo-terminal):
pty - EXEC (Execute a program):
exec:<command>
Commands / Usage
socat’s primary syntax is socat [options] <address1> <address2>.
Listening for Connections
TCP Server
socat TCP-LISTEN:12345,reuseaddr,fork EXEC:'/bin/bash -i'
Listens on TCP port 12345, accepts multiple connections (due to fork), and spawns an interactive bash shell for each connection. reuseaddr allows immediate reuse of the port.
socat TCP-LISTEN:54321 STDOUT
Listens on TCP port 54321 and prints any incoming data to standard output.
UDP Server
socat UDP-LISTEN:9999,fork STDOUT
Listens on UDP port 9999, accepts multiple datagrams (due to fork), and prints incoming data to standard output.
Unix Domain Socket Server
socat UNIX-LISTEN:/tmp/mysocket,fork EXEC:'/usr/bin/cat -'
Listens for connections on the Unix domain socket /tmp/mysocket. For each connection, it executes cat - which reads from its standard input (the connection) and writes to its standard output (the connection).
Making Connections
TCP Client
socat TCP:example.com:80 STDIN
Connects to example.com on port 80 and reads data from standard input to send.
socat TCP:192.168.1.100:8080 EXEC:'/bin/bash -i'
Connects to a remote host on port 8080 and spawns an interactive bash shell, relaying data between the shell and the remote connection.
UDP Client
socat UDP:192.168.1.200:53 STDIN
Sends data from standard input as UDP datagrams to 192.168.1.200 on port 53.
Unix Domain Socket Client
socat UNIX:/var/run/docker.sock STDOUT
Connects to the Docker daemon’s Unix domain socket and prints any data received to standard output.
File and Pipe Operations
Reading from a File
socat FILE:logfile.txt STDOUT
Reads the content of logfile.txt and prints it to standard output.
Writing to a File
socat STDIN FILE:output.txt
Reads data from standard input and writes it to output.txt.
Appending to a File
socat STDIN FILE:output.txt,append
Reads data from standard input and appends it to output.txt.
Reading from a Named Pipe
socat PIPE:/tmp/mypipe STDOUT
Reads data from the named pipe /tmp/mypipe and prints it to standard output.
Writing to a Named Pipe
socat STDIN PIPE:/tmp/mypipe
Reads data from standard input and writes it to the named pipe /tmp/mypipe.
Pseudo-terminals (PTY)
Creating a PTY Pair
socat PTY,link=/tmp/pty_master,raw,echo=0 EXEC:'/bin/bash -i'
Creates a pseudo-terminal pair. The master side is accessible via /tmp/pty_master. The slave side is attached to an interactive bash shell. raw disables terminal processing, and echo=0 prevents echoing input.
Executing Commands
Running a Command and Piping its Output
socat EXEC:'ls -l' STDOUT
Executes ls -l and sends its standard output to socat’s standard output.
Piping Input to a Command
SOCAT_CMD="echo hello world"
socat STDIN EXEC:"$SOCAT_CMD"
Reads from standard input and pipes it as standard input to the command specified by $SOCAT_CMD.
Connecting a Command’s Stdin/Stdout to a Socket
socat TCP:localhost:9000 EXEC:'/usr/bin/curl -X POST -d @-' localhost:8000
Connects to localhost:9000. Any data received on this TCP connection is sent as standard input to the curl command. The curl command then sends this data via HTTP POST to localhost:8000.
Combining Addresses and Options
Port Forwarding (TCP)
socat TCP-LISTEN:8080,fork TCP:localhost:3000
Listens on port 8080, and for each connection, forwards the traffic to localhost:3000.
TCP to UDP Relay
socat TCP-LISTEN:12345 UDP:localhost:54321
Listens for TCP connections on port 12345 and forwards received data to UDP port 54321 on localhost.
File to Network
socat FILE:data.txt TCP:remotehost:9999
Sends the content of data.txt over TCP to remotehost:9999.
Network to File
socat TCP:localhost:8888 FILE:received_data.bin
Listens for TCP connections on localhost:8888 and writes all received data to received_data.bin.
Common Options
-d,-dd,-ddd: Increase verbosity level for debugging (shows packets, connection attempts, etc.).-s: Print statistics about data transfer.fork: For listening sockets, creates a new process for each incoming connection, allowing multiple simultaneous clients.reuseaddr: Allows the socket to be bound to an address that is already in use (useful for rapid restarts).raw: Disables canonical mode and all special line processing on the pseudo-terminal.echo=0: Disables echo on the pseudo-terminal.bind=<ip>: Bind the listening socket to a specific IP address.sourceport=<port>: Force the source port for outgoing connections.wait-conn: Waits until the second address is actually connected before relaying data.
Common Patterns
Simple Shell Access over Network
# On the server:
socat TCP-LISTEN:4444,reuseaddr,fork EXEC:'/bin/bash -i'
# On the client:
socat TCP:server_ip:4444 STDIN
Provides a remote shell. Be cautious with this, as it’s insecure without encryption.
Port Forwarding with socat (a more robust alternative to ssh -L)
# Forward local port 8080 to remote port 3000 on a server that socat is running on
# On your local machine:
socat TCP-LISTEN:8080 TCP:your_server_ip:9000
# On your_server_ip:
socat TCP-LISTEN:9000 TCP:localhost:3000
This setup forwards local port 8080 to your_server_ip:9000, which then forwards to localhost:3000 on your_server_ip.
Secure Shell Access (using socat with OpenSSL)
# Server-side setup (generate certs first if you don't have them)
socat OPENSSL-LISTEN:8443,cert=server.pem,key=server.key,reuseaddr,fork EXEC:'/bin/bash -i'
# Client-side setup
socat OPENSSL:server_ip:8443,verify=0 STDIN
This provides an encrypted shell. verify=0 disables certificate verification for simplicity in this example; in production, you’d want proper verification.
Debugging Network Services
# Connect to a running service and see raw traffic
socat TCP:target_host:port STDOUT
# Send commands to a service and see responses
socat STDIN TCP:target_host:port
Creating a Network-based Pipe
# In one terminal:
socat TCP-LISTEN:12345 STDOUT
# In another terminal:
socat STDIN TCP:localhost:12345
Anything typed in the second terminal appears in the first, and vice-versa (if the first terminal is also set up to send back).
Interacting with Serial Ports
# Connect a serial port to a TCP port
socat PTY,link=/tmp/vserial0,raw,echo=0,waitslave FILE:/dev/ttyUSB0,raw,echo=0
# Then, connect to the PTY's master side
socat TCP-LISTEN:5000 PTY:/tmp/vserial0,raw,echo=0
This allows remote access to a serial device over TCP.
Gotchas
forkvs.wait-conn:forkis crucial for handling multiple clients on listening sockets.wait-connis useful when you need to ensure the second address is connected before any data is relayed. Withoutwait-conn, data might be sent to an address that isn’t yet ready.- Buffering: Terminal applications often buffer output.
socatitself can also buffer. Use therawoption on PTYs and file descriptors to disable terminal processing and buffering where appropriate for raw data streams. - Security:
socatitself does not provide encryption. For secure communication, usesocatwithOPENSSLaddresses or tunnelsocattraffic throughsshorstunnel. Be extremely cautious when exposing shell access (EXEC:'/bin/bash -i') over unencrypted networks. - Error Handling:
socatcan be verbose with-d. Understanding the output is key to debugging connection issues. Look for messages about "connection refused," "timeout," or "address already in use." - File Permissions: When using
UNIX-LISTEN, ensure the directory for the socket file has appropriate permissions. - Resource Limits: Be mindful of system limits on open file descriptors, especially when using
forkextensively.