aboutsummaryrefslogtreecommitdiffstats
smtpd-starttls-proxy: the smtpd-starttls-proxy-io program

smtpd-starttls-proxy
Software
skarnet.org

The smtpd-starttls-proxy-io program

smtpd-starttls-proxy-io is a program that runs in front of a UCSPI-compliant SMTP server (such as qmail-smtpd) and extends it with STARTTLS capability.

smtpd-starttls-proxy-io provides no TLS on its own; instead, it expects to be run under a UCSPI-TLS server, and interfaces with it.

Interface

     smtpd-starttls-proxy-io smtpd...
  • smtpd-starttls-proxy-io forks and the parent execs into smtpd.... smtpd-starttls-proxy-io sticks around as a child process.
  • smtpd-starttls-proxy-io interposes itself between the client connection (stdin/stdout) and smtpd; the latter still talks to its stdin/stdout but those are only connected to smtpd-starttls-proxy-io.
  • smtpd-starttls-proxy-io acts as an SMTP server to the client, and as an SMTP client to the server. It advertises STARTTLS capability to the client in addition to smtpd's capabilities.
  • If it receives a STARTTLS command, it triggers the UCSPI-TLS process to perform a TLS handshake, then execs into s6-ioconnect, transmitting data between the TLS layer and smtpd until the end of the connection.
  • If, instead, it receives a HELO command, which indicates lack of STARTTLS support in the client, or a MAIL command, which indicates a desire to send mail without requiring TLS, it deactivates the UCSPI-TLS process, then execs into s6-ioconnect, this time transmitting plaintext data between the network and smtpd until the end of the connection.

Environment variables

smtpd-starttls-proxy-io expects to be run under a UCSPI-TLS server such as s6-ucspitlsd or sslserver -n. As a consequence, it expects its environment to contain the following variables:

  • SSLCTLFD: the file descriptor number of the UCSPI-TLS control socket
  • SSLREADFD: the file descriptor number of the pipe used to read data from the TLS tunnel after it has been activated
  • SSLWRITEFD: the file descriptor number of the pipe used to write data to the TLS tunnel after it has been activated.

smtpd-starttls-proxy-io will refuse to run if one of these variables is nonexistent or contains invalid data.

Usage example

You can run a STARTTLS-enabled qmail-smtpd mail receiver on address hostip port port with the following steps:

  • Install s6-networking and make sure to activate TLS support. (bearssl is recommended over libtls.)
  • Define proper environment variables for your TLS connection: at least CERTFILE and KEYFILE. The environment you need is documented on the s6-tlsd-io page.
  • Refine your security with additional environment variables: TLS_UID and TLS_GID to avoid running the TLS engine as root, and UID and GID to avoid running the SMTP server (and smtpd-starttls-proxy-io!) as root.
  • If you wish, also refine the following command line with various options to every tool that appears, for fine tuning of connection parameters.
  • The following command line is only one command line, which makes heavy use of chainloading. It has been broken down into several lines for readability. (Note that you don't need the backslashes if you're writing an execline script.)
  s6-tcpserver -- hostip port \
  s6-tcpserver-access -Dl0 -t5000 -- \
  s6-ucspitlsd -K30000 -- \
  s6-applyuidgid -Uz -- \
  smtpd-starttls-proxy-io \
  qmail-smtpd 
  • s6-tcpserver will listen on socket TCP:hostip:port and spawn the rest of its command line as a child for every client connection. (Think inetd-like.)
  • s6-tcpserver-access will fine-tune some TCP parameters of the connection. It can also do ip-based access control, and that's its main use, but that's not what we're using it for here.
  • s6-ucspitlsd will create a control channel for opportunistic TLS and wait for a command.
  • s6-applyuidgid will drop root privileges.
  • smtpd-starttls-proxy-io will exchange data with the client and the server, and depending on what the client wants, tell s6-ucspitlsd either to drop it entirely or to perform a TLS handshake.
  • qmail-smtpd is the real SMTP server, does nothing else than speak SMTP to its stdin/stdout, does not support STARTTLS, and is blissfully unaware of all the plumbing and shenanigans that happen above.

Notes

  • smtpd-starttls-proxy-io is significantly less polite than qmail-smtpd when the client does not follow proper protocol.