1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
|
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<meta http-equiv="Content-Language" content="en" />
<title>smtpd-starttls-proxy: the smtpd-starttls-proxy-io program</title>
<meta name="Description" content="smtpd-starttls-proxy: the smtpd-starttls-proxy-io program" />
<meta name="Keywords" content="smtpd-starttls-proxy io smtpd starttls ucspi-tls s6-ucspitlsd" />
<!-- <link rel="stylesheet" type="text/css" href="//skarnet.org/default.css" /> -->
</head>
<body>
<p>
<a href="index.html">smtpd-starttls-proxy</a><br />
<a href="//skarnet.org/software/">Software</a><br />
<a href="//skarnet.org/">skarnet.org</a>
</p>
<h1> The <tt>smtpd-starttls-proxy-io</tt> program </h1>
<p>
<tt>smtpd-starttls-proxy-io</tt> is a program that runs in front of a UCSPI-compliant
SMTP server (such as <tt>qmail-smtpd</tt>) and extends it with STARTTLS
capability.
</p>
<p>
<tt>smtpd-starttls-proxy-io</tt> provides no TLS on its own;
instead, it expects to be run under a
<a href="https://web.archive.org/web/20150311223933/http://www.suspectclass.com/sgifford/ucspi-tls/ucspi-tls.txt">UCSPI-TLS</a>
server, and interfaces with it.
</p>
<h2> Interface </h2>
<pre>
smtpd-starttls-proxy-io <em>smtpd...</em>
</pre>
<ul>
<li> <tt>smtpd-starttls-proxy-io</tt> forks and the parent execs into <em>smtpd...</em>.
<tt>smtpd-starttls-proxy-io</tt> sticks around as a child process. </li>
<li> <tt>smtpd-starttls-proxy-io</tt> interposes itself between the client connection
(stdin/stdout) and <em>smtpd</em>; the latter still talks to its stdin/stdout but those
are only connected to <tt>smtpd-starttls-proxy-io</tt>. </li>
<li> <tt>smtpd-starttls-proxy-io</tt> 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 <em>smtpd</em>'s capabilities. </li>
<li> If it receives a <tt>STARTTLS</tt> command, it triggers the UCSPI-TLS process to
perform a TLS handshake, then execs into
<a href="//skarnet.org/software/s6/s6-ioconnect.html">s6-ioconnect</a>, transmitting
data between the TLS layer and <em>smtpd</em> until the end of the connection. </li>
<li> If, instead, it receives a <tt>HELO</tt> command, which indicates lack of STARTTLS
support in the client, or a <tt>MAIL</tt> command, which indicates a desire to send mail
without requiring TLS, it deactivates the UCSPI-TLS process, then execs into
<a href="//skarnet.org/software/s6/s6-ioconnect.html">s6-ioconnect</a>, this time
transmitting plaintext data between the network and <em>smtpd</em> until the end of the
connection. </li>
</ul>
<h2> Environment variables </h2>
<p>
<tt>smtpd-starttls-proxy-io</tt> expects to be run under a UCSPI-TLS server such as
<a href="//skarnet.org/software/s6-networking/s6-ucspitlsd.html">s6-ucspitlsd</a> or
<a href="//www.fehcom.de/ipnet/ucspi-ssl/sslserver.html">sslserver -n</a>. As a
consequence, it expects its environment to contain the following variables:
</p>
<ul>
<li> SSLCTLFD: the file descriptor number of the UCSPI-TLS control socket </li>
<li> SSLREADFD: the file descriptor number of the pipe used to read data from the TLS tunnel after it has been activated </li>
<li> SSLWRITEFD: the file descriptor number of the pipe used to write data to the TLS tunnel after it has been activated. </li>
</ul>
<p>
<tt>smtpd-starttls-proxy-io</tt> will refuse to run if one of these variables
is nonexistent or contains invalid data.
</p>
<h2> Usage example </h2>
<p>
You can run a STARTTLS-enabled <tt>qmail-smtpd</tt> mail receiver on
address <em>hostip</em> port <em>port</em> with the following steps:
</p>
<ul>
<li> Install <a href="//skarnet.org/software/s6-networking/index.html">s6-networking</a>
and make sure to activate TLS support. (bearssl is recommended over libtls.) </li>
<li> Define proper environment variables for your TLS connection: at least
CERTFILE and KEYFILE. The environment you need is documented on the
<a href="//skarnet.org/software/s6-networking/s6-tlsd-io.html">s6-tlsd-io</a> page. </li>
<li> 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
<tt>smtpd-starttls-proxy-io</tt>!) as root. </li>
<li> If you wish, also refine the following command line with various options to every tool
that appears, for fine tuning of connection parameters. </li>
<li> The following command line is only <em>one</em> 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
<a href="//skarnet.org/software/execline/">execline</a> script.) </li>
</ul>
<pre> s6-tcpserver -- <em>hostip</em> <em>port</em> \
s6-tcpserver-access -Dl0 -t5000 -- \
s6-ucspitlsd -K30000 -- \
s6-applyuidgid -Uz -- \
smtpd-starttls-proxy-io \
qmail-smtpd </pre>
<ul>
<li> <a href="https://skarnet.org/software/s6-networking/s6-tcpserver.html">s6-tcpserver</a>
will listen on socket TCP:<em>hostip</em>:<em>port</em> and spawn the rest of its
command line as a child for every client connection. (Think <tt>inetd</tt>-like.) </li>
<li> <a href="https://skarnet.org/software/s6-networking/s6-tcpserver-access.html">s6-tcpserver-access</a>
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. </li>
<li> <a href="https://skarnet.org/software/s6-networking/s6-ucspitlsd.html">s6-ucspitlsd</a>
will create a control channel for opportunistic TLS and wait for a command. </li>
<li> <a href="https://skarnet.org/software/s6/s6-applyuidgid.html">s6-applyuidgid</a> will
drop root privileges. </li>
<li> <tt>smtpd-starttls-proxy-io</tt> will exchange data with the client and the server,
and depending on what the client wants, tell
<a href="https://skarnet.org/software/s6-networking/s6-ucspitlsd.html">s6-ucspitlsd</a>
either to drop it entirely or to perform a TLS handshake. </li>
<li> <a href="http://qmail.org/man/man8/qmail-smtpd.html">qmail-smtpd</a> 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. </li>
</ul>
<h2> Notes </h2>
<ul>
<li> <tt>smtpd-starttls-proxy-io</tt> is significantly less polite than <tt>qmail-smtpd</tt>
when the client does not follow proper protocol. </li>
</ul>
</body>
</html>
|