HOWTO: Crafting arbitrary network packets with socat




socat is a powerful UNIX command-line tool for crafting, sending and receiving network packets. Once understood it can be used to prototype client-server designs, probing and fuzzing remote machines, data-transfer and even proxy traffic from one host to another.

NOTE: the below examples use socat to move data around networks in the open, with no encryption in place. With this in mind you should only use socat to move data of a volatile nature over a trusted VPN or using socat’s SSL options. To move data around securely on networks you don’t control you are better to use ssh and scp (section coming soon).

Installing socat

Installing socat on Linux systems

Most Linux distributions provide socat in their repositories.

To install it on a Debian-based Linux system (most distributions, including Ubuntu, CrunchBang and Debian itself) do the following:

sudo apt-get install socat

To install socat on a RedHat system, do as follows:

sudo yum -y install socat

Installing socat on OS X

Mac OS X users should download the latest version of socat from and compile it as follows (here we use socat- as an example).

Unpack the archive:

 tar xvzf socat-

Change to the newly created directory and configure the source for compilation:

 cd socat-

Compile the source:


Install it:

sudo make install


Send a UDP packet to a remote host

Here we send a UDP packet with a string in its payload to port 2001 on remote host

We can pass socat our string with echo over a UNIX pipe:


Send data to a remote host, logging to a file

In this example we start socat on the remote host, telling it to listen for connections on port 3333. Each time it receives a connection it will execute cat, redirecting and appending (’>>’) received input as output into the file /tmp/log.txt:


socat tcp-l:3333,reuseaddr,fork system:'cat >> /tmp/log.txt',nofork

Now on our client machine we echo a string over a UNIX pipe to socat, which then sends it within a TCP packet to the remote host on port 3333:


Send a UDP packet to a remote host, hitting every port (packet protest)

Here we use a range in bash, the most popular UNIX shell, to send to ports incrementing from 1001 to 65535 on the remote domain, sleeping for 1/10th of a second in between. Please note this is very network-noisy.

for PORT in {1001..65535}; do echo "READ YOUR CONSTITUTION, NOT OUR EMAIL." | socat -$PORT; sleep .1; done

Execute commands on a remote host, viewing command output locally

socat can be used to trigger system calls and shell scripts on the remote host. Used this way socat effectively replaces netcat and remote command execution with ssh (albeit without encryption) and affords the user great flexibility.

In the following example we execute the command ls -lt on the remote host, outputting standard output to our shell on the local machine. This can be very useful if you want to monitor the contents of a directory on a server or other remote machine. Importantly, the commands executed will not appear in the remote user’s shell history.

First we start socat on the remote server ( on an arbitrary port (3333), executing the specified command each time a packet is received:


socat tcp-l:3333,reuseaddr,fork system:'ls -lt',nofork

Note that the reuseaddr option keeps socat in a listening state rather than exiting after each call, while fork will spawn a new child-process each time it’s called.


Now on the client we send our packet to

socat -

Output from the remotely executed ls -lt command will appear in the local shell.

Naturally the output from the remote command can be logged to a local file, like so:

socat - >> log.txt

Monitoring the display of a remote computer

In this example we’ll use socat and command line tools to take a screen-grab on a remote machine that has a graphical display, retrieving the file to a local directory. This can be a useful way of monitoring remote machines with desktop environments.


Linux and OS X have different command line tools for screencapture. If the remote machine runs Linux we’d use scrot. If OS X, screencapture. For this example we’ll use Linux as it’s the OS most used on embedded computers (like the BeagleBone Black and Raspberry Pi) and servers.

CAP=scrot # Linux
# CAP=screencapture # OS X

On the remote machine (on a LAN or Internet), we start our capture command.

socat tcp-l:3333,reuseaddr,fork system:'s=cap.png; $CAP $s; cat $s'

The above command can be left running, a server that will take a screen-grab whenever we ask for it.


Now on our local monitoring machine we’ll create a folder for our screen grabs:

mkdir Screengrabs

Now we tell socat to send a TCP packet to trigger and retrieve the capture on our local monitoring machine.

socat - > Screengrabs/$(date +%Y-%m-%d_%H-%M-%S).png

This will produce a PNG file whose file name inherits a date/time form (eg.2014-05-08_21-49-51.png) in the Screengrabs directory.


The capture trigger and retrieval command can be easily automated to ask for a screen-grab every few seconds:


# - Remote screengrab trigger and retrieval script. 
# Use with *socat* command on a Linux or OS X remote host with graphical display:
# CAP=scrot # For Linux
# CAP=screencapture # For OS X
# PORT=3333
# socat tcp-l:$PORT,reuseaddr,fork system:'s=cap.png; $CAP $s; cat $s'

# Vars
REMOTE='' # A variable for the remote host we're monitoring
PORT=3333 # Define a port (be sure it matches that of the server)
DIR=~/Screengrabs # A variable for a directory that will hold our screen-grabs
POLL=10 # A variable for our poll interval, in seconds

# Check the directory for our screen-grabs exists. If not, create it.
if [ ! -d $DIR ]
mkdir $DIR

# Simple loop
while true
                 # A variable for our file name that calls *date*
                 FN=$(date +%Y-%m-%d_%H-%M-%S).png
                 # Send a TCP packet on port 3333 to trigger capture and retrieval
                 socat - TCP4:$REMOTE:$PORT > $DIR/$FN
                 echo "Retrieved $FN and wrote it to $DIR"
                 # Get some rest
                 sleep $POLL

Copy out the file to and set it to executable:

chmod +x

Run it like so: