Consulting djbware Publications

sslserver - accept incoming IPv4/IPv6 TCP connections and invoke application

Purpose

sslserver allows applications to accept TCP connections in a chroot environment. Unlike inetd or xinetd it is not a `super daemon` but works for individual connections in the user space.

sslserver can listen to any IPv4/IPv6 address and any port. It also supports binding to all local IPv4 and IPv6 addresses (simultaneously).

Reversely, incoming IP/TCP connections are usually under control of tcprules allowing filtering on IP addresses and DNS informations. Remote clients thus can be qualified prior of accepting a TCP session which could be understood as user-level firewall.

Since sslserver is TLS enabled, the treatment of cryptographical materials is a bit delicate. sslserver uses a three tier approach with a double chroot environment:

  1. Invoked as server process on privileged ports sslserver starts as user root.
  2. While evaluating the required key material and X.509 certificates sslserver drops permissions and acts now in a restricted SSL environment.
  3. Upon reading the required informations into memory, sslserver is instructed to execute the application in its user space.

While the user execution is provided in the same manner as

tcpserver, the evaluation of the TLS cryptographic material requires the setting of environment variables and thus hidden from the setup of the server process.

Application support

Applications are enabled by means of sslserver to communication with the network via the standard file descriptors

  1. FD 0: Reading from the network.
  2. FD 1: Writing to the network.

Application may be supplied with any arguments on call.

While typically sslserver is invoked by root, the application is executed in a chroot enviroment with restricted permissons only. Therefore, one sets

upon calling sslserver.

sslserver spawns and instantiates a new copy of application whose concurrent number can be limited providing -c limit.

The application may be fed with several connection relevant informations pushed in its environment for further usage.

STARTTLS support for Application

sslserver is able to provide a 'delayed' TLS communication with the application which is established after the TCP handshake and using STARTTLS or STLS triggered by the application.

sslserver uses the ucspi-tls API written by Scott Gifford and Charlie Brady defining additional communication channels between sslserver and the application:

The file descriptors x and y are supplied by sslserver in the environment to be used the the application as SSLREADFD and SSLWRITEFD.

Local binding

sslserver usually uses the host's primary IP address, but can otherwise bind to any IPv4 and/or IPv6 address of the system and to any port (given the required permissions) as defined by

  • host (or the IPv4, the IPv6 address; or 0, ::, :0);
  • port (if port equals '0', a free port is chosen),
  • -I ifname

Here,

  • 0 are all available IPv4 addresses (upon invocation),
  • :: are all available IPv6 addresses (upon invocation), or
  • :0 providing IPv4/IPv6 dual-stack binding.

sslserver will allow to bind to IPv6 LLU addresses, in case additionally the interface name is provided. Beware, that LLU address are in particular subject of SLAAC changes.

Network settings and connections from the remote client

Prior to spawning the application sslserver and be advised to evaluate several IP and DNS connection conditions which are subject of the client's IP and potentially the evaluated DNS and IDENT informations:

  • -h
    Query the inverse IP-name via i6.arpa or in-addr.arpa and the authoritative Name Server followed by a query of the remotehost name via a PTR lookup (default).
  • -p
    Require that the incoming IP address matches those from the A/AAAA DNS lookup of the authoritative Name Server (paranoid) .

Now, TCP(6)REMOTEHOST is correctly populated.

DNS-lookups may be expansive and useless in case of a DoS or DDoS attack. sslserver provides now an 'early' cdb lookup accompanying the usual inquery:

  • -x cdb
    'cdb' rule lookup for IP/DNS/IDENT after DNS query.
  • -y cdb
    'cdb' rule lookup for IP addresses only before DNS query.
  • -X cdb
    Continue operation, even if no 'cdb' is found.

The 'cdb's given may be distinct or identical. Since both can be generated 'on-the-fly' by means of a fast response to DoS/DDoS attacks is possible.

Nowadays almost avoided is the lookup of the remote user via IDENT/TAP:

  • -r
    IDENT/TAP lookup applying a -t timeout (default: 26 secs).
  • -R
    IDENT/TAP lookup disabled (default).

Apart from those possibilities, some unusual settings are available:

  • -B banner
    Send 'banner' as greeting string to the remote client.
  • -b backlog
    Allow backlog simultaneous SYNs received.
  • -o
    Allow source routing of IP packets (default: no).
  • -d
    Delay sending of data for a fraction of a second (default: no).
Name resolution

sslserver reads the environment variable DNSCACHEIP which can be used to specify the recursive DNS Resolver.

If not given, sslserver uses the nameserver entries provided in /etc/resolv.conf.

Name resolution is baesd on the following flags:

  • -h (default) do a DNS PTR lookup of the received IP address.
  • -h don't do a DNS lookup.
  • -p after a PTR lookup; use this information for a regular A/AAAA lookup and provide the DNS FQDN only if both entries match (paranoid).
  • -p don't do an additional DNS A/AAAA lookup.
  • >-l localname Don't lookup the FQDN of this host in the DNS but rather use localname in the logs.

Controlling remote connection behavior via tcprules

sslserver can be advised to read one or more cdb's prior to accepting a TCP connection including additional policy informations how to handle a connection and which environment variables to be exported to the application:

  • -x tcp.cdb
    Require a file tcp.cdb, read and follow its instructions.
  • -X tcp.cdb
    Don't require a file tcp.cdb but read its content if given.
  • -y iprules.cdb>
    'cdb' rule lookup for IP addresses only before DNS query.

In order to operate successfully, sslserver supplies tcprules with the following data to be compared against a database (cdb):

  1. The IP address of the remote client (always),
  2. the hostname (given a DNS lookup),
  3. the identity of the remote caller (given a IDENT lookup).

Certain rules can be set up:

  • deny a connection,
  • allow a connection and provide additional environment variables for the application.
Maximimal Connections per IP Address

Apart from environment variables passed thru to the application, the current version of sslserver makes use of

  • MAXCONIP='n', n ≤ limit

Now, sslserver can limit the number of concurrent connections from a single source (or a network range) to 'n' instances prior to call application and thus preventing a denial of service (DoS) attack. It should be noted, that changes of enviroment variables following the settings in tcprules don't require a new start of sslserver.

DoS/DDoS Mitigation

DNS-lookups may be expansive and useless in case of a DoS or DDoS attack. While you can avoid the DNS lookup for you own host by means of providing -l localhost upon the call of sslserver, now an 'early' cdb evaluation can be performed prior of any DNS lookup. Three cases may be of interest:

  • IP only: -y iprules.cdb
    'cdb' rule lookup for IP addresses (only) before any DNS query. Here, you can put your IPs into 'iprules.cdb'. This usage is equivalent with the standard 'cdb' with no DNS lookup for sslserver.
  • IP deny: -y ipdeny.cdb
    Here you provide a particular 'cdb' just including the IP addresses (or ranges) you would like to deny access to your application without requiring additional resources.
  • IP mixed: -X -y x.cdb and -x x.cdb
    utilizing one common 'cdb' including both IP and FQDN settings. The call of -X -y x.cdb allows this 'cdb' to be none-existing. If it does, only the IP relevant content is evaluated. In case of an 'allow', the following call of -x x.cdb is omitted.

The both 'cdb's given may be distinct or identical. Since both can be generated 'on-the-fly' by means of tcprules a fast and specific response to DoS/DDoS attacks is possible flagging remote IP addresses or IP/CDIR ranges as 'deny' prior of utilizing any other resource .

Environment variables set

sslserver sets up several environment variables available for the application, as described in tcp-environ:

  • PROTO is either 'TCP' or 'TLS'.
  • The interface name for IPv6 connections: SSLINTERFACE.
  • The local information: TCPLOCALIP, SSLLOCALIP, TCPLOCALPORT, SSLLOCALPORT, TCPLOCALHOST, SSLLOCALHOST.
  • The remote IP/TCP data for the connection: TCPREMOTEIP, SSLREMOTEIP together with TCPREMOTEPORT and SSLREMOTEPORT.

DNS (TCPREMOTEHOST, SSLREMOTEHOST) and the IDENT (TCPREMOTEINFO) informations are optional and depending on the arguments supplied.

Once sslserver is supplied with the argument -e details upon the TLS connection settings are available providing both

  • the TLS state including the elected cipher settings as well as
  • specifics of the received X.509 certificate from the client (if any),
  • the own X.509 parameters.

TLS Connection Settings

Fueled by ucspissl.h, sslserver recjects SSLv2 and SSLv3 connections; but currently allows all TLS variants. SSL_CTX_set_security_level is not used.

RSA keys up to 4096 bit length are supported.

TLS Key Material

The entire TLS key material is supplied by environment variables. This allows to define specific settings per TCP connection, in case these parameters are individually given in an adjecent sslserver cdb file.

The TLS key material is read in a chroot environment demanding a partiular user taking are of it. Thus we have:

  • SSL_USER: The TLS user responsible for the key material.
  • SSL_GROUP: The adjacent TLS group.
  • SSL_UID: The UID of the SSL_USER.
  • SSL_CHROOT: The chroot directory.

In the SSL_CHROOT directory the following TLS material can be placed to be read by sslserver:

  • CERTFILE: The server's X.509 certificate.
  • KEYFILE: The corresponding key file which should never be exposed.
  • CERTCHAINFILE: The server's X.509 certificate + intermediate + root X.509 certificate (having priority over CERTFILE.

Note: The keyfile may be protected by a pasword. This is supplied via 'sslserver -3 3< $SSL_CHROOT/password'.

Apart from this key material - used to identify the server - two other TLS settings are important:

  • DHFILE: The Diffie-Hellman paramater file for discrete log key agreement (telling the large prime p and the groug g required for the calculation.
    Since most of the TLS connections now use Elliptical Curve Diffie-Hellman, this file may become obsolete but is required for backward compatibility.
  • CIPHERS The TLS connection cipher provided to OpenSSL or LibreSSL in a format given by openssl-ciphers.

Providing CIPHERS tells mainly which (available) ciphers shall be avoided for connection. the ciphers 'strength' is historically given by their numerical index, which may be questionable. Both, the server and the client negotiate the effective cipher setting for a TLS connection.

Mandatory X.509 Client Certificate Requests

sslserver may be adviced to required a X.509 client certificate. In this case, its behaviour can be tailored by the following settings:

  • sslserver -z: Instructing sslserver to requiere a client X.509 certificate and match FQDN against SAN/DN (if -h or -p is given).
  • sslserver -m: Ask for a client X.509 certificate but don't do a SAN/DN evaluation against the FQDN (typically used for personal X.509 certs.
  • CAFILE: Used to verify the client X.509 cert.
  • CADIR: The X.509 cert trust store for the client certificates.
  • CCADIR: Hint for the client, which X.509 cert should be used for mutual authentication.
  • VERIFYDEPTH: Numerical value to restrict the chainging depth of client certificates.

Logging

Invoking sslserver with the options

  • -v and optionally
  • -l localname

will provide a logging of the session on FD = 2 including (if possible) the hostname, as well as the used IP addresses and ports of the peers. A DNS lookup for the localhost can be avoided and substitued by a generic name. The displayed IP addresses are shown either as generic IPv4 or as compactified IPv6 addresses.