Unix socket reference
Unix sockets, UNIX-domain sockets, Unix domain protocol family, POSIX local inter-process communication socket, POSIX local IPC socket, AF_UNIX
, PF_UNIX
, PF_LOCAL
, AF_FILE
, PF_FILE
—
all these terms more or less refer to the same concept — a host-internal protocol and addressing
scheme that is more or less like socket communication between computers on the Internet.
Typically, but not always, Unix sockets are referenced by pathnames on the file system.
Unix sockets are available on a variety of platforms (including macOS, Windows and Linux), and they all differ a little in how they work.
Here are some references that may be useful to you.
man pages
man pages are a great reference to know more about what your particular system understands and supports.
Try the following commands on your machine:
man unix
(or:man 4 unix
,man 7 unix
)man socket
(or:man 2 socket
)man socketpair
man af_local
Make sure you follow the references to other man pages in the SEE ALSO
sections of each man page.
You can also search for references to unix
and socket
in the man pages using the apropos
command:
apropos socket
apropos unix
Here are some man pages on the web for different platforms:
- Linux: unix(7), socket(2)
- macOS: unix(4), socket(2)
- Illumos/OpenSolaris: socket(3SOCKET), socket(3HEAD).
- FreeBSD: unix(4), socket(2)
- The FreeBSD website also covers other operating systems. Just select the desired operating system from the drop-down menu (e.g., NetBSD, OpenBSD, HP-UX, 4.3BSD NET/2
- z/OS: Addressing within the AF_UNIX domain, Using z/OS UNIX sockets
- POSIX: 7P unix, 3POSIX socket, 7POSIX un.h
- Also check out the man page repository on the unix.com website, which provides entire man page sets for different operating systems.
- Windows: Since Build 17063 (Fall Creators Update?), even Microsoft Windows 10 supports AF_UNIX:
AF_UNIX comes to Windows, Windows/WSL Interop with AF_UNIX — check availability using
sc query afunix
. The driver isafunix.sys
, the headers are in<afunix.h>
. - QNX Neutrino RTOS: unix_proto, socket
Headers
You can't go wrong by looking at the system headers (maybe under /usr/include
, or elsewhere on your system).
Look for the following userspace headers:
<sys/un.h>
<sys/socket.h>
.
Here are some platform-specific references:
-
Linux:
- userspace headers are defined in glibc/dietlibc/musl, etc.
- kernel source
You may need to
#define _GNU_SOURCE
before importing these headers to unlock GNU-specific extensions. -
macOS: sys/un.h, sys/socket.h
You may need to
#define _DARWIN_C_SOURCE
before importing these headers to unlock Darwin/macOS-specific extensions. -
Open Group Base Specification: sys/un.h, sys/socket.h
-
Windows:
<afunix.h>
Port numbers
Unlike Internet socket addresses, Unix domain socket addresses do not support a numeric port component.
junixsocket provides an API that shims in support for ports, in order to support Java RMI over Unix sockets, for example.
Other references
- junixsocket's JNI code
- Wikipedia: Unix domain socket
Platform-specific limits and extensions
Length of a socket path (sun_path
)
Some operating systems, such as HP/UX, limit sun_path
to only be up to 92 bytes. macOS, QNX and 4.4 BSD limit them to 104. Linux, 4.3 BSD and z/OS have a limit of 108 bytes. A (sometimes) mandatory terminating null byte is included in this calculation.
Socket types
Usually, all platforms support SOCK_STREAM
(stream sockets), most support SOCK_DGRAM
(datagram sockets), and some also support SOCK_SEQPACKET
(sequenced packet socket with preserved message boundaries).
Abstract namespace
Some platforms, such as Linux, QNX and Windows 10, support a namespace for sockets that is not connected to the filesystem. A socket is in the abstract namespace if it starts with a null byte — the remainder of the data structure is part of the name, and null bytes may have no special meaning.
unlink
upon destruction is typically not necessary for such sockets, and chmod
/chown
has no effect.
SUN_LEN
probably shouldn't be used here to determine the length of the sockaddr_un
since it uses strlen
.
Some platforms (Linux only?) can automatically assign names in the abstract namespace by means of “autobind”, whereas the name commonly consists of the starting null byte followed by 5 bytes using hexadecimal characters (0-9, a-f).
Unnamed sockets
A pair of sockets can be created using socketpair
, which may not always be supported.
Transmit file descriptors, credentials
Ancillary messages / ancillary data allows passing special information over these sockets that is not just binary data. These messages are usually transmitted via sendmsg
/recvmsg
, and they're practically all very platform-specific.
-
SCM_RIGHTS
: Send or receive file descriptors (or more generically, “access rights”).The used data structures vary (e.g.,
struct cmsgcred
,struct cmsghdr
).Since on UNIX, practically everything can be referenced through a file descriptor, this feature can be very powerful (e.g., see Android AHardwareBuffer Shared Memory over Unix Domain Sockets).
-
SCM_CREDENTIALS
/SCM_UCRED
: Send process credentials (e.g., UID, GID, etc.), which can be used to authenticate a caller.In order to receive these credentials, the socket must have a
SO_PASSCRED
/SO_RECVUCRED
option enabled. Also see theSOL_LOCAL
-level socket options on FreeBSD and macOS, such asLOCAL_CRED
,LOCAL_PEERCRED
,LOCAL_PEERPID
,LOCAL_PEEREPID
,LOCAL_PEERUUID
,LOCAL_PEEREUUID
, etc.Note that authenticating using a particular PID may be insecure as PIDs may be reused for new processes.
The used data structures vary (e.g.,
struct xucred
,struct ucred
,ucred_t
)
Socket options
-
SOL_SOCKET
level:SO_RCVBUF
has no effect.SO_SNDBUF
imposes an upper limit for outgoing datagrams.SO_PASSCRED
/SO_RECVUCRED
enables the receipt of file descriptorsSO_NOSIGPIPE
disable raising theSIGPIPE
signal upon broken pipe.
-
SOL_LOCAL
level (FreeBSD, macOS):LOCAL_CRED
,LOCAL_PEERCRED
,LOCAL_PEERPID
,LOCAL_PEEREPID
,LOCAL_PEERUUID
,LOCAL_PEEREUUID
: Receive peer credentials
ioctls
FIONREAD
/SIOCINQ
: For stream sockets, returns the amount of unread bytes in the receive buffer. For datagram sockets, returns the size of either the next pending datagram, or all pending data. Note that the datagram size could be 0 bytes, so this is probably not a good replacement forselect
.
Command-line tools
NOTE: Not all commands and options are available on all platforms.
Enumerate available sockets
NOTE: On Linux, when showing abstract namespace paths, null bytes are converted to
@
. Older tool versions may not handle zero bytes properly.
lsof
List unix sockets:
lsof -U
Also show peer processes/endpoints (Linux-only):
lsof +E -U
Combine with other parameters (and -a
) to restrict to a particular user, process, etc., e.g., sudo lsof -a -U -u root
ss (Linux)
List unix sockets:
ss -x
Also show peer processes/endpoints (it appears that your kernel needs to have UNIX_DIAG
enabled for this.):
ss -xp
netstat
Show listening sockets:
netstat --unix -l
Show connected sockets:
netstat --unix
Filesystem
On Linux, you can get a list of all UNIX sockets:
cat /proc/net/unix
On Android, many sockets are defined in /dev/socket/
.
Communicate with Unix sockets
netcat / nc
Connect to an existing stream socket
nc -U /path/to/socket
Create a listening stream socket
nc -lU /path/to/socket
Datagrams
- Some versions of netcat support datagram sockets by adding another
-u
parameter.
socat
socat allows forwarding between two different sockets, as well as piping from and to STDIN, etc. (see man socat
).
Check out the address types UNIX-CONNECT
, UNIX-LISTEN
, UNIX-SENDTO
, UNIX-RECVFROM
, UNIX-RECV
, UNIX-CLIENT
. On Linux, replace UNIX-
by ABSTRACT-
, and you can access sockets in the abstract namespace.
Example:
socat - UNIX-CONNECT:/path/to/socket
websocat
The socat-like tool for WebSockets also has support for unix sockets.
Examples
-
Websocket to Unix socket:
websocat ws-l:127.0.0.1:8088 unix:the_socket
-
Listen socket forwarding to Websocket:
websocat --unlink unix-l:the_socket ws://127.0.0.1:8089
curl
curl can send HTTP requests over Unix sockets. This is useful for communication with Docker, for example:
curl --unix-socket /var/run/docker.sock http://localhost/images/json
Servers
Webservers
Web servers like nginx provide support to serve content over unix sockets, and curl can be used to test them.
Databases
MySQL and PostgreSQL provide access to the database via Unix Sockets. Since the communication over TCP/IP usually requires SSL, this encryption can be disabled on the Unix domain socket connection, which should improve performance.
junixsocket provides JDBC adapters for both.
Security
File permissions
As a good practice, place unix sockets in a directory with tight access controls. On systems that support file-level controls on the socket itself, use chown
/chmod
to further restrict access, but do not rely on this alone.
Independent of directory-level access controls, the names of all unix sockets may be available through /proc/net/unix
or similar APIs.
Abstract namespace
Since there are no filesystem-level permission enforced upon socket names in the abstract namespace, one should consider them less secure than those specified by file path. Checking peer credentials upon establishing a connection (in both directions!) could make up for this, but that doesn't come for free.
Android
The wild west. Applications with the INTERNET
permission to access the Internet also have access to Unix domain sockets. A lot of sockets are unsecured.
See Yuru et al., The Misuse of Android Unix Domain Sockets and Security Implications (with presentation slides) for an analysis of what can go wrong.
Also see Jiang et al., Unix Domain Sockets Applied in Android Malware Should Not Be Ignored.
Anything missing or wrong?
Feel free to reach out by email, christian@kohlschutter.com, or file an issue or pull request with junixsocket.