Last Updated: September 23, 2016
·
18.88K
· maxcnunes

Forwarding TCP-traffic to a UNIX socket

Nowadays I’m working a lot with Docker containers and sometimes I was asked to allow someone access the database in production. But how to do it easy and fast?

Due security reasons the database in production has bind only for localhost so it is not possible to connect directly from my machine.

Objective

  • allow remote connection
  • only specific IPs could have access to it
  • easy to enable or disable it

And I achieved it using socat \o/

What is socat?

Socat allow establish two bidirectional byte streams and transfers data between them. It has support for many channels type (e.g. file, serial line, socket Unix, TCP) and can be used, e.g., as TCP port forwarder or for redirecting TCP oriented programs to a serial line.

Base Command

Forwarding port 15432 to socket /srv/mongodb-27017.sock:

socat -d -d TCP4-LISTEN:15432,fork UNIX-CONNECT:/srv/mongodb-27017.sock

Explaining

  • -d -d: prints fatal, error, warning, and notice messages
  • TCP4-LISTEN: Listens on <port>, accepts a TCP/IP connection and only supports IPv4 protocol
  • fork: forks a new child process for each connection
  • UNIX_CONNECT: connects to filename assuming it is a UNIX domain socket

With that command running in the server then you can connect there from your local machine.

Final Script

Was missing only allow specific IPs use this proxy. Also the main ideas was to be easy enable the proxy. Therefore I created this script below:

forward-port-to-socket.sh

#!/bin/sh -e

if [ $# != 2 ]; then
    echo "usage: $0 <public-port> <path-private-socket>"
    echo "example: $0 15432 /srv/my-service.sock"
    exit 0
fi

PUBLIC_PORT=$1
PRIVATE_SOCKET=$2
SOCAT_LOG=/tmp/socat-$PUBLIC_PORT.log

echo "--> socat forwarding:\n\t- from port: $PUBLIC_PORT\n\t- to socket: $PRIVATE_SOCKET"
echo "--> allowed ips:\n\t$(cat socat-allow)"
echo "--> logs: $SOCAT_LOG"

socat -d -d -lf $SOCAT_LOG \
        TCP4-LISTEN:$PUBLIC_PORT,reuseaddr,fork,tcpwrap=socat,allow-table=socat-allow,deny-table=socat-deny \
        UNIX-CONNECT:$PRIVATE_SOCKET

socat-allow

socat:<allowed-ip-here>

socat-deny

socat:all

Executing

./forward-port-to-socket.sh 15432 /srv/mongodb-27017.sock

Explaining

  • lf: writes messages to logfile
  • reuseaddr: allows immediate restart of the server process
  • tcpwrap: uses Wietse Venema's libwrap (tcpd) library to determine if the client is allowed to connect
  • allow-table: takes the specified file instead of /etc/hosts.allow
  • deny-table: takes the specified file instead of /etc/hosts.deny

Gist