The main purpose of socketbox-preload is to allow the Socketbox system to be used with existing server daemons, ideally without having to make any changes in code to the server daemon itself. It is implemented as an LD_PRELOAD library. Socketbox-preload is designed such that daemons can seamlessly listen on both Socketbox listeners and traditional TCP listeners at the same time, provided that the server daemon already supports listening on multiple addresses/ports at the same time without Socketbox.
Socketbox-preload relies on the server daemon to support binding to a particular IP address for the socket. This address may also be known as the "bind address", "host address", "listen address", or "interface address", and is usually specified as an IP address on the local system; in many cases, the port number may also be a part of it, but for the purposes of Socketbox, only the IP address part is significant. (We don't want to affect any other socket listeners for compatibility reasons, so intercepting binds to the wildcard address (0.0.0.0 or ::) is not appropriate.)
Instruct your server daemon, with the LD_PRELOAD library injected, to bind to the following IPv6 address:
- X = 0, open
$SKBOX_DIRECTORY_ROOT/skbox_dir_Yd000as a regular file where Yd000 is the decimal representation of YYYY zero-left-padded to five digits. Use the first 108 (or UNIX_PATH_MAX) bytes starting from byte offset
128 * Zdof that file as the Unix domain socket address (i.e. the bytes in that range are copied into struct sockaddr_un->sun_path), where Zd is the numeric value of ZZZZ in decimal (if past the end of the file, bind() returns -1 and sets errno to
ERANGE). If that address contains the string
_@SB_, then it is replaced with the original requested port number of the bind() call zero-left-padded to five digits. The socket will be created as an instance of a Socketbox "A" protocol listener. If $SKBOX_DIRECTORY_ROOT is unset, this will result in an error.
- X = 1, same as X = 0, but create a traditional stream socket instead.
- X = 2, open
$SKBOX_DIRECTORY_ROOT2/Yd000/Zd000_Pd000as the socket address, using the Socketbox "A" protocol, where Yd000 is the decimal value of YYYY zero-left-padded to five digits, Zd000 is the decimal value of ZZZZ zero-left-padded to five digits, and Pd000 is the decimal value of the original port number zero-left-padded to five digits. If $SKBOX_DIRECTORY_ROOT2 is unset, this will result in an error.
- X = 3, same as X = 2, but create a traditional stream socket instead.
- All other values for X are reserved and will result in an error.
The following additional restrictions apply:
- The length of the socket address passed to bind() must be equal to
sizeof(struct sockaddr_in6)and the value of sa_family is set to AF_INET6.
- Original socket must be detected as domain AF_INET or AF_INET6 and type SOCK_STREAM.
- Requested port number to bind() must be greater than zero and less than 1024. (Because we don't actually bind the socket to that port in terms of the TCP socket layer, the CAP_NET_BIND_SERVICE restriction does not apply; instead, it's the filesystem permissions on
$SKBOX_DIRECTORY_ROOT2which are significant.)
- sin6_scope_id must be set to 0.
- IPv6 must not be disabled on the machine using
/etc/sysctl.confinstead, though I would question why you would want to run socketbox in such an environment.)
- The "B" protocol is not supported.
Note these additional points:
- The socket is chmod'd to 0660. This means that if the directory in which the socket is created has the set-group-ID bit set, then the group permission of the socket is set to that of the directory, and that group can in turn access the socket. (This means that it is possible to create a set-group-ID directory whose group is
socketboxand allow unprivileged processes to create sockets there without root access, provided that the Socketbox server is running as group
socketbox(or has it as a supplementary group ID), and the permissions on the directory are set appropriately, preferably with POSIX acl's, such that the program placing the socket there has write and search access to that directory, and the socketbox daemon has search permission on that directory.)
Snippet from Apache httpd web server configuration file (The
Listen directive is described in https://httpd.apache.org/docs/2.4/bind.html):
If the socketbox-preload library is injected into the httpd process and
$SKBOX_DIRECTORY_ROOT2 is set, then this will result in the httpd process listening on
$SKBOX_DIRECTORY_ROOT2/00395/00016_00080 as a Socketbox "A" protocol receiver. (18b hex = 395 decimal, 10 hex = 16 decimal)
Example command to start httpd (can be placed in shell script or systemd
LD_PRELOAD=/path/to/libsocketbox-preload.so SKBOX_DIRECTORY_ROOT2=/run/socketbox_dir httpd [...]
In this example, with the same listening IP address set as above in the configuration file, the path to the Socketbox receiver would be
/run/socketbox_dir/00395/00016_00080, and this would be the path used in
jump-unix in the Socketbox server's configuration file (assuming non-chroot operation), if you want to select this instance of the Apache web server for a given IP address and port number.
Note that the preload library does not create any parent directories if they do not exist. So you would need to create the
/run/socketbox_dir/00395 directory and adjust permissions on that directory as appropriate if it did not previously exist.
It is possible to also enable the ability to connect to fe8f:: addresses using SKBOX_ENABLE_CONNECT (it is disabled by default), but depending on the credentials of the web (or other) server, enabling it may also result in the ability to create server-side request forgery attacks. Use with caution!
- This end-user documentation is part of socketbox. Reproduction and use of this material for any purpose is permitted, provided that a link to this page is provided as attribution.