Linux: socat used as secure HTTPS web server

If you need to quickly standup a secure HTTPS server on a machine, perhaps to validate that a client is sending the proper method or parameters, the socat utility can assist.

In this article we will use “socat.local” as the FQDN of our certificate and host.

Maybe you already have a pem key+certificate for this host, but if not then you can quickly create a self-signed certificate.

FQDN="mysocat.local"
PORT=9443

# create private key for TLS
openssl genrsa -out $FQDN.key 2048

# create public certificate for TLS
openssl req -new -key $FQDN.key -x509 -days 3653 -out $FQDN.crt -subj "/C=US/ST=CA/L=SFO/O=myorg/CN=$FQDN"

# create pem format key+cert
cat $FQDN.key $FQDN.crt >$FQDN.pem

# limit permissions
chmod 600 $FQDN.key $FQDN.pem
chmod 644 $FQDN.crt

# if running OS level firewall, make sure port is open
sudo ufw status
sudo -E ufw allow $PORT/tcp

Start secure socat web server

Then start socat listening on the port using the pem certificate for secure TLS.

# ensure socat is installed
sudo apt install socat curl -y

# incoming communication will be output to console
socat -v -ls OPENSSL-LISTEN:${PORT},reuseaddr,cert=${FQDN}.pem,verify=0,crlf,fork SYSTEM:"echo HTTP/1.0 200; echo Content-Type\: text/plain; echo; echo \"hello from $(hostname) at \$(date)\""

The “-v” flag on socat will take care of outputting the incoming data coming from client calls.

Test client access with curl

We are going to test using curl on the same host, but a different terminal session.

FQDN="mysocat.local"
PORT=9443
cacert="${FQDN}.crt"

# tells curl that mysocat.local resolves to localhost
resolvestr="${FQDN}:${PORT}:127.0.0.1"

# basic curl
curl --cacert $cacert --resolve $resolvestr https://${FQDN}:${PORT}/

# curl with urlencoded params
curl --cacert $cacert --resolve $resolvestr -X POST -d 'foo=bar&email=me@mydomain.com' https://${FQDN}:${PORT}/test

# curl with uploaded file
echo "this is going up">toupload.txt
curl --cacert $cacert --resolve $resolvestr -X POST -F 'image=@toupload.txt' https://${FQDN}:${PORT}/test

Github code

You can find the commands above wrapped up as scripts on my github.

 

REFERENCES

man socat

github epitron, socat examples

dest-unreach.org, socat for SSL tunnel, mutual TLS

NOTES

If instead of secure HTTPS, you just wanted plain HTTP

PORT=8080
socat -v -ls TCP-LISTEN:${PORT},reuseaddr,crlf,fork SYSTEM:"echo HTTP/1.0 200; echo Content-Type\: text/plain; echo; echo \"hello from $(hostname) at \$(date)\""