s6-networking: the s6-tlsserver program
Keywords: s6-networking s6-tlsclient tlsserver tls ssl ucspi tcp inet network tcp/ip server superserver

s6-networking
Software
skarnet.org

# The `s6-tlsserver` program

`s6-tlsserver` is an UCSPI server tool for TLS/SSL connections over INET domain sockets. It acts as a TCP super-server that listens to connections, accepts them, and for each connection, establishes a TLS transport over it, then executes into a program.

## Interface

         s6-tlsserver [ options ] [ -- ] ip port prog...

- s6-tlsserver rewrites itself into a command line involving:
  - s6-tcpserver, which listens to TCP connections on IP address ip port port and forks a command line for every connection. Note that s6-tcpserver also rewrites itself into a more complex command line (the final long-lived process being s6-tcpserverd), so your end command line may look a lot longer in `ps` than what you originally wrote. This is normal and healthy.
  - (if applicable) s6-tcpserver-access, which performs TCP access control and various operations on the TCP connection.
  - s6-tlsd, which establishes a TLS transport (server-side) over a connection, via an s6-tlsd-io child process.
  - (if applicable) s6-applyuidgid, which drops root privileges.
  - prog..., your client program, which is run with the same pid as s6-tlsd.
- It runs until it is killed by a signal.

prog is expected to read from its peer on its standard input and write to its peer on its standard output. Since there will be an s6-tlsd-io program between prog and the network to perform the SSL encryption/decryption, those descriptors will not be a network socket - they will be pipes.

## Signals

`s6-tlsserver` reacts to the same signals as s6-tcpserverd, which is the long-lived process hanging around.

## Environment variables

### Read

The following variables should be set before invoking `s6-tlsserver`, because they will be used by every s6-tlsd invocation:

- KEYFILE
- CERTFILE
- TLS_UID and TLS_GID (if you run `s6-tlsserver` as root)
- CADIR (if you want client certificates)
- CAFILE (if you want client certificates, alternative to CADIR)

Setting both KEYFILE and CERTFILE is mandatory.

### Written

prog... is run with the following variables added to, or removed from, its environment by s6-tcpserverd and possibly by s6-tcpserver-access:

- PROTO
- TCPREMOTEIP
- TCPREMOTEPORT
- TCPCONNNUM
- TCPLOCALIP
- TCPLOCALPORT
- TCPREMOTEHOST
- TCPLOCALHOST
- TCPREMOTEINFO

Depending on TCP access rules (if the `-i` or `-x` option has been given), it is possible that prog's environment undergoes more modifications. Also, since s6-tlsd is always run after s6-tcpserver-access, it is possible to set different TLS/SSL parameters (typically a different KEYFILE and CERTFILE) depending on the client connection, by writing the correct set of TCP access rules.

Unless the `-Z` option is given to `s6-tlsserver`, the CADIR, CAFILE, KEYFILE, CERTFILE, TLS_UID and TLS_GID variables will not appear in prog's environment.

## Options

`s6-tlsserver` accepts a myriad of options, all of which are passed as is to the correct executable. Not giving any options will generally work, but unless you're running a very public server (such as a Web server) or base your access control on client certificates, you probably still want TCP access rules.

### Options passed as is to s6-tcpserver

- `-q`, `-Q`, `-v`
- `-1`
- `-c maxconn`
- `-C localmaxconn`
- `-b backlog`

### Options passed as is to s6-tcpserver-access

- The verbosity level, if not default, as `-v0` or `-v2`
- `-w`, `-W` : be strict or tolerant with DNS or IDENT resolution errors
- `-d`, `-D` : enable or disable Nagle's algorithm
- `-r`, `-R` : enable or disable IDENT lookups
- `-p`, `-P` : enable or disable paranoid DNS cross-checking
- `-H` : disable DNS lookups
- `-h` : consult `/etc/hosts` before DNS
- `-l localname` : get the local name from the command line, don't look it up
- `-B banner` : initial server-side banner
- `-t timeout` : set a timeout for all the lookups
- `-i rulesdir`, `-x rulesfile` : TCP access control

### Options passed as is to s6-tlsd

- `-Z`, `-z` : keep or remove the s6-tlsd-io-specific variables from the application's environment
- `-S`, `-s` : use close_notify or EOF to signal the end of a TLS connection
- `-J`, `-j` : exit nonzero with an error message when the peer fails to close_notify, or ignore it
- `-Y`, `-y` : request an optional or a mandatory client certificate
- `-K kimeout` : set a timeout for the TLS handshake
- `-k snilevel` : support SNI-based certificate chains

### Options passed to s6-applyuidgid

- `-u uid`, `-g gid`, `-G gidlist` : set uid, gid, or supplementary group list
- `-U` (passed as `-Uz`) : get the uid, gid and supplementary group list from the UID, GID and GIDLIST variables, and remove these variables from the application's environment

## Example

As root:

    env KEYFILE=/etc/ssl/private/mykey.der CERTFILE=/etc/ssl/public/mycert.pem \
    TLS_UID=65534 TLS_GID=65534 \
    s6-envuidgid www \
    s6-tlsserver -U -- 1.2.3.4 443 httpd

This will start a server listening to 1.2.3.4 on TCP port 443, and for every connection, spawn the `httpd` program reading queries on stdin and replying on stdout, as user `www`, with a TLS layer protecting the connection, the TLS engine running as user `nobody` (`65534:65534`). The server is authenticated by the certificate in `/etc/ssl/public/mycert.pem` that it sends to the client, and the private key in `/etc/ssl/private/mykey.der` that it keeps to itself.