s6-networking: an overview of the tls-related programs
Keywords: s6-networking s6-tlsc s6-tlsd tlsc tlsd tlsc-io ucspi-tls ucspi-ssl tlsd-io ssl ucspi tcp inet network tcp/ip client

s6-networking
Software
skarnet.org

# An overview of the TLS-related programs

The `s6-*tls*` programs are organized in a way that minimizes the amount of code, and in particular that keeps the crypto code as encapsulated as possible.

They are divided in two sets: client programs, which have `client` or `c` in their name, and server programs, which have `server` or `d` in their name. The sets are symmetrical: the same functionality is available whether you're interested in using a client or a server.

Of course, they do not have to be used together. You can run a TLS-enabled super-server via s6-tlsserver and it will work with any client speaking the correct TLS-enabled protocol, not only s6-tlsclient.

## The core TLS engine: s6-tlsc-io and s6-tlsd-io

- s6-tlsc-io and s6-tlsd-io are the only programs that actually perform TLS operations; the only ones that are linked against the BearSSL or LibreSSL libraries.
- They read TLS-related information (where to find my trust anchor list? where to find my server certificate and private key?) from their environment.
- They assume that their stdin/stdout is talking to the network; they also take two other fds on the command line that they assume are open and talking to the local application - one for reading, one for writing.
- They establish a TLS tunnel over the network.
- They maintain full-duplex communication: what they read from the local application is sent to stdout as ciphertext; what they read from stdin is sent to the local application as cleartext.
- They exit when they cannot transmit any more data.

Other programs in the s6-tls set perform various operations such as Unix file descriptor plumbing in order to provide a specific interface, but they always end up spawning a s6-tlsc-io or s6-tlsd-io child that will handle the actual TLS management for them.

## Regular TLSification of a service: s6-tlsc and s6-tlsd

- The s6-tlsc and s6-tlsd programs are "immediate encryption"-type programs. They assume that the rest of their command line is a UCSPI client or server application, i.e. reads from the network on fd (6 for clients, 0 for servers) and writes to the network on fd (7 for clients, 1 for servers); their goal is to provide this application with transparent encryption.
- They first spawn a s6-tlsc-io or s6-tlsd-io child to initialize the TLS connection.
- When the TLS handshake has completed, they exec into the rest of their command line, interposing the s6-tls[cd]-io program in between this application and the network.
- The application still communicates via cleartext, but the data is transparently encrypted before it goes to the network.
- The application is only started after the handshake succeeds; the TLS tunnel stays up for the whole lifetime of the application, or until the application closes the fds it uses to communicate with (what it thinks is) the network.

## Opportunistic TLS: s6-ucspitlsc and s6-ucspitlsd

- The s6-ucspitlsc and s6-ucspitlsd programs are "delayed encryption"-type programs. They assume that the rest of their command line is an application that follows the UCSPI-TLS protocol. This is a bit of a misnomer: the aim of this protocol is just to provide an application with a means to ask for TLS encryption at any time.
- They prepare the necessary communication channels, then fork. The parent execs into the rest of its command line, with the appropriate ucspi-tls environment variables set. The child stays and waits for a command.
- When the application sends a command to start TLS, the child execs into s6-tlsc-io or s6-tlsd-io, which initializes a TLS connection and performs a handshake.
- The application then communicates via the fds that have been provided to it via the ucspi-tls protocol. Those fds go through the TLS engine.

## High-level client connections and super-servers: s6-tlsclient and s6-tlsserver

- The s6-tlsclient and s6-tlsserver programs are high-level wrappers around TCP client and server functionality, followed by the establishment of a TLS tunnel, followed by the execution of an application. They're meant to provide simpler interfaces over long, complex command lines.
- s6-tlsclient rewrites itself into a command line involving s6-tcpclient and s6-tlsc.
- s6-tlsserver rewrites itself into a command line involving (depending on the given options) s6-tcpserver, s6-tcpserver-access, s6-tlsd, and s6-applyuidgid.