SkillAgentSearch skills...

Unsock

shim library to automatically change AF_INET sockets to AF_UNIX, etc.

Install / Use

/learn @kohlschutter/Unsock
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

unsock: shim to automatically change AF_INET sockets to AF_UNIX, etc.

Makefile CI

unsock

Unix domain sockets (AF_UNIX) are Berkeley (BSD-style) sockets that are accessible as paths in the file system. Unlike AF_INET sockets, they may be given user and group ownership and access rights, which makes them an excellent choice to connect services that run on the same host.

Unfortunately, not all programs support Unix domain sockets out of the box. This is where unsock comes in:

unsock is a shim library that intercepts Berkeley socket calls that use AF_INET sockets and automatically rewrites them such that they use AF_UNIX sockets instead, without having to modify the target program's source code.

Moreover, with the help of a custom control file in place of a real AF_UNIX domain socket, unsock allows communicating over all sorts of sockets, such as AF_VSOCK and AF_TIPC.

Using unsock not only makes systems more secure (by not having to expose internal communication as AF_INET sockets), it also helps improve performance by removing inter-protocol proxies from the equation — programs can now talk directly to each other.

unsock specifically also simplifies communication between a virtual machine and its host, by allowing communication to go through AF_VSOCK sockets even if the programs were designed for IPv4-communication only. As a bonus feature, unsock simplifies communication with Firecracker-style multiplexing sockets.

Mode of operation

Being a shared library that is inserted into a process using LD_PRELOAD, unsock intercepts standard C library calls like connect(2), bind(2), accept(2), etc. The calls are analyzed and, if necessary, modified transparently such that the calling process does not notice (or at least only minimally) that an exchange took place.

Since socket file descriptors are first created on a per-protocol bassis using socket(2), should an address family need to be changed, that socket file descriptor is replaced transparently using a correct one. dup3(2) is used to re-assign the file descriptor number on the fly, so no additional housekeeping is necessary.

AF_INET socket addresses are converted to a configurable path on the file system, under which either AF_UNIX sockets reside, or special control files with instructions how to reach the desired socket destination (for details see below).

unsock's behavior can be modified using several environment parameters, which are outlined below.

The shared library binary doubles as a simple configuration tool to create the special control files (for details see below).

Building and running

In order to build, you need a working C compiler (available under cc), Linux headers, and for tests an nc command that supports UNIX sockets. If you're on Alpine Linux, just run

./init

To create the shared library libunsock.so, on a Linux machine just run

make

To run some tests on the created library use

make test

To install the library on the system (by default to /usr/local/lib/) use

sudo make install

To launch a target process with unsock, add libunsock.so to the environment variable LD_PRELOAD, and set the environment variable UNSOCK_DIR to the absolute path of the directory where unsock's AF_UNIX sockets are stored, for example as follows:

UNSOCK_DIR=/tmp/unsockets/ LD_PRELOAD=/usr/local/lib/libunsock.so *some-process* *(some-args ...)*

This will ensure that all connections to 127.175.0.0 are intercepted and routed to unix domain sockets in /tmp/unsockets. The socket files are named (port).socket, e.g., 1234.socket for port 1234.

Use UNSOCK_ADDR to configure which IP addresses are redirected. You can either specify a single IP-address (e.g., 1.2.3.4), or an IP-range identified by a bitmask (e.g., 1.2.3.4/24). Specifying a bitmask of 32 is identical to omitting the bitmask. Specifying a bitmask of 0 means "all" IPv4 addresses, whereas the IP address itself is used to flag incoming connections from other protocols:

UNSOCK_ADDR=127.0.0.1/8 UNSOCK_DIR=/tmp/unsockets/ LD_PRELOAD=/usr/local/lib/libunsock.so some-process some-args ...

If UNSOCK_ADDR is omitted, only connections/binds to 127.175.0.0/32 are intercepted and converted.

Security and permissions

Choosing a directory for UNSOCK_DIR

In the examples, for simplicity, we use /tmp/unsockets for UNSOCK_DIR.

Note that you should use a different directory in production, preferably one that has read/write permissions restricted to the user/group that uses the socket.

You also don't necessarily need one directory; you can have separate directories for different processes.

Socket file permissions

By default, unsock does not modify permissions for created socket files. However, you may specify an octal value for UNSOCK_MODE to run chmod whenver an unsock socket file is created, e.g.:

# Make available to all
UNSOCK_MODE=777 (...)

# Make available only to user
UNSOCK_MODE=700 (...)

Since you may not be able to change group ownership from any process, you can strategically move UNSOCK_DIR to a directory that has a certain group ownership and still get some security even with UNSOCK_MODE=777.

Disabling AF_INET6

Some processes may try binding/connnecting via IPv6. unsock will not prevent that, unless you specify the following environment variable setting, which will block any attempts to create AF_INET6 sockets:

UNSOCK_BLOCK_INET6=1 (...)

Disabling unintercepted AF_INET

You can also prevent unintercepted AF_INET connections (those that are not translated via unsock), by specifying the following environment variable:

UNSOCK_BLOCK_INET=1 (...)

Usage Examples

nc

Make nc listen on Unix domain socket /tmp/unsockets/7000.sock instead of using TCP port 7000:

UNSOCK_DIR=/tmp/unsockets/ LD_PRELOAD=/usr/local/lib/libunsock.so nc -l 127.175.0.0 7000

Listen on all IPv4 addresses; connections are coming from 127.175.0.3:

UNSOCK_ADDR=127.175.0.3/0 UNSOCK_DIR=/tmp/unsockets/ LD_PRELOAD=/usr/local/lib/libunsock.so nc 127.0.0.1 7000

Listen on all IP addresses between 127.1.0.0 and 127.1.0.255; connection to 127.0.0.1 is via TCP:

UNSOCK_ADDR=127.1.0.3/24 UNSOCK_DIR=/tmp/unsockets/ LD_PRELOAD=/usr/local/lib/libunsock.so nc 127.0.0.1 7000

NOTE: busybox nc is a bit picky when accepting connections. You may need to specify

UNSOCK_BLOCK_INET6=1 UNSOCK_PORT=7000 UNSOCK_ADDR=127.0.0.1/0 UNSOCK_DIR=/tmp/unsockets/ \
    LD_PRELOAD=/usr/local/lib/libunsock.so nc -l -p 7000

to fix the bound + incoming addresses and ports.

java

Make Java connect to UNIX sockets even without special support. Obviously, this is no replacement for proper libraries like junixsocket, but may be useful sometimes.

UNSOCK_ADDR=127.0.0.1/0 UNSOCK_DIR=/tmp/unsockets/ LD_PRELOAD=/usr/local/lib/libunsock.so java -jar ...

noVNC

unsock + noVNC can be used to expose a VNC server to the Web via nginx, using Unix domain sockets for all internal ports.

see doc/novnc.md for details.

iperf

unsock allows to run iperf over arbitrary sockets (e.g., AF_UNIX, AF_VSOCK and AF_TIPC), not just IP.

see doc/iperf.md for details.

Python HTTP server

unsock allows to run the HTTP server over arbitrary sockets (e.g., AF_UNIX, AF_VSOCK and AF_TIPC), not just IP.

see doc/python-http.md for details.

Control files, other socket domains like AF_VSOCK and AF_TIPC.

unsock can also connect to other types of sockets. If the *.sock file in UNSOCK_DIR is not a unix domain socket but a regular file with a magic header, the contents of the file control the actual target of the connection. See struct unsock_socket_info in unsock.h for details of the file format.

Some control file configurations can be created by calling libunsock.so as an executable, along with some environment variables being set, including UNSOCK_FILE pointing to the control file:

Create a control file to bind on an AF_VSOCK address.

Create a control file under /tmp/unsockets/1234.sock that points to AF_VSOCK port 5678 with CID "any" (-1).

UNSOCK_FILE=/tmp/unsockets/1234.sock UNSOCK_VSOCK_PORT=5678 /usr/local/lib/libunsock.so  

The command will fail if the file already exists.

Create a control file to connect to a VSOCK socket via a Firecracker-style Unix domain socket

The Firecracker hypervisor exposes a multiplexed Unix domain socket, over which one can connect to VSOCK ports in the guest system. When using libunsock.so with such a control file, the connection is transparent, so no manual CONNECT port/OK logic is necesssary.

Create a control file under /tmp/unsockets/1024.sock that points to the AF_UNIX socket at /path/to/firecracker/vsock which is a Firecracker multiplexing server. Connecting to /tmp/unsockets/1024.sock will actually try to connect to the guest's VSOCK port 5678.

  UNSOCK_FILE=/tmp/unsockets/1024.sock UNSOCK_FC_SOCK=/path/to/firecracker/vsock \
      UNSOCK_VSOCK_PORT=5678 /usr/local/lib/libunsock.so  

The command will fail if the file already exists. You should specify an absolute path for UNSOCK_FC_SOCK. If it's a relative path, it must actually exist since it is resolved to an absolute path for the control file.

Create a control file to connect TIPC sockets

TIPC knows several addressing types, but it comes down to specifying five values, address type and scope, and then three integer values depending on address type.

unsock does not discern these values, so the naming may be a littl

View on GitHub
GitHub Stars46
CategoryDevelopment
Updated4mo ago
Forks1

Languages

C

Security Score

92/100

Audited on Nov 25, 2025

No findings