summaryrefslogtreecommitdiff
path: root/doc/s6-tlsd.html
blob: 76dc1864f963537bc6b8b9f569d3b646b0836d2e (plain)
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
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
<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>s6-networking: the s6-tlsd program</title>
    <meta name="Description" content="s6-networking: the s6-tlsd program" />
    <meta name="Keywords" content="s6-networking s6-tlsd tlsd tls ssl ucspi tcp inet network tcp/ip server" />
    <!-- <link rel="stylesheet" type="text/css" href="http://skarnet.org/default.css" /> -->
  </head>
<body>

<p>
<a href="index.html">s6-networking</a><br />
<a href="http://skarnet.org/software/">Software</a><br />
<a href="http://skarnet.org/">skarnet.org</a>
</p>

<h1> The <tt>s6-tlsd</tt> program </h1>

<p>
<tt>s6-tlsd</tt> is a program that performs the server side of
a TLS or SSL connection over an existing TCP connection, then spawns
an application. It is meant to make network communications
secure even for applications that do not natively support
TLS/SSL.
</p>

<p>
 <a href="index.html">s6-networking</a> does not include
cryptographic software. All the crypto used in <tt>s6-tlsd</tt>
is provided by the chosen SSL backend:
<a href="https://bearssl.org/">BearSSL</a> or
<a href="https://www.libressl.org/">LibreSSL</a>, depending on
the options given when configuring <tt>s6-networking</tt>.
</p>

<h2> Interface </h2>

<pre>
     s6-tlsd [ -S | -s ] [ -Y | -y ] [ -Z | -z ] [ -v <em>verbosity</em> ] [ -K kimeout ] [ -- ] <em>prog...</em>
</pre>

<ul>
 <li> s6-tlsd expects to have an open TCP connection it
can talk to on its stdin (for reading) and stdout
(for writing). </li>
 <li> It spawns <em>prog...</em> as a child process,
interposing itself between it and the network.
In other words: <em>prog</em> still reads cleartext
on its stdin and writes cleartext on its stdout, but
those will actually be pipes to <tt>s6-tlsd</tt>, which
will read ciphertext from its own stdin (the network)
and write ciphertext to its own stdout (the network). </li>
 <li> It initiates the server side of a TLS/SSL handshake
over the network connection, expecting a TLS/SSL client on
the other side. </li>
 <li> It manages the encryption/decryption of all the
messages between <em>prog</em> and the client.
<em>prog</em> speaks plaintext, but only ciphertext is sent
on the network. </li>
 <li> When <em>prog</em> exits, <tt>s6-tlsd</tt> exits.
</ul>

<h2> Exit codes </h2>

<ul>
 <li> 96: error while configuring the TLS/SSL context - for instance, invalid
private key or server certificate files. </li>
 <li> 97: error while setting up the TLS/SSL client engine. </li>
 <li> 98: TLS/SSL error while running the engine. </li>
 <li> 100: wrong usage. </li>
 <li> 111: system call failed. </li>
</ul>

<p>
 If the TLS/SSL connection closes cleanly, <tt>s6-tlsd</tt>
waits for <em>prog</em> to exit, then exits with an
<a href="http://skarnet.org/software/execline/exitcodes.html">approximation</a>
of <em>prog</em>'s exit code.
</p>

<h2> Protocol version and parameters </h2>

<p>
 During the TLS/SSL handshake, <tt>s6-tlsd</tt> tries the
versions of the protocol that is supported by default by the
backend, with the default algorithms and cipher suites;
the backend normally ensures that the most secure combination
is tried first, with slow degradation until the client and
the server agree.
</p>

<ul>
 <li> For BearSSL, this means use of the
<a href="https://bearssl.org/apidoc/bearssl__ssl_8h.html#a76293c81c4624c58254a62be7b2d5e79">br_ssl_server_init_full_rsa()</a> or
<a href="https://bearssl.org/apidoc/bearssl__ssl_8h.html#a592b2af27b2f6b9389aac854fb0b783a">br_ssl_server_init_full_ec()</a>
function. The supported protocol versions are described
<a href="https://bearssl.org/support.html#supported-versions">here</a>. </li>
 <li> For LibreSSL, this means use of the
<a href="http://man.openbsd.org/OpenBSD-current/man3/tls_config_set_protocols.3">tls_config_set_protocols(TLS_PROTOCOLS_DEFAULT)</a>
call. </li>
</ul>

<p>
 As a server, <tt>s6-tlsd</tt> can be conservative in its
choice of protocols. It is currently not very conservative
when using the BearSSL backend; it could become more so in
the future, by defining a custom server profile that supports
only TLS-1.2 but with several algorithms and cipher suites.
</p>

<h2> Environment variables </h2>

<h3> Read </h3>

<p>
 <tt>s6-tlsd</tt> expects to have the following
environment variables set:
</p>

<ul>
 <li> <tt>KEYFILE</tt>: a path to the file
containing the server's private key, DER- or PEM-encoded. </li>
 <li> <tt>CERTFILE</tt>: a path to the file
containing the server's certificate, DER- or PEM-encoded.
If PEM-encoded, the file can actually contain a chain
of certificates. </li>
</ul>

<p>
 If one of those variables is unset, <tt>s6-tlsd</tt>
will refuse to run.
</p>

<p>
 If you are using client certificats, <tt>s6-tlsd</tt>
also requires either one of the following variables to be set:
</p>

<ul>
 <li> <tt>CADIR</tt>: a directory where trust anchors
(i.e. root or intermediate CA certificates) can be found,
one per file, DER- or PEM-encoded. </li>
 <li> <tt>CAFILE</tt>: a file containing the whole set
of trust anchors, PEM-encoded. </li>
</ul>

<p>
 If <tt>s6-tlsd</tt> is run as root, it can also read two
more environment variables, <tt>TLS_UID</tt> and <tt>TLS_GID</tt>,
which contain a numeric uid and a numeric gid; <tt>s6-tlsd</tt>
then drops its root privileges to this uid/gid after spawning
<em>prog...</em>. This ensures that the TLS/engine and the
application run with different privileges.
</p>

<p>
 Note that <em>prog...</em>
should drop its own root privileges by its own means: the
<a href="http://skarnet.org/software/s6/s6-applyuidgid.html">s6-applyuidgid</a>
program is a way of doing it. If the <tt>s6-tlsd</tt>
invocation actually comes from a
<a href="s6-tlsserver.html">s6-tlsserver</a> command line,
and privilege-dropping options (<tt>-G</tt>, <tt>-g</tt>,
<tt>-u</tt> or <tt>-U</tt>) have been given to
<a href="s6-tlsserver.html">s6-tlsserver</a>, then
<a href="http://skarnet.org/software/s6/s6-applyuidgid.html">s6-applyuidgid</a>
directly follows <tt>s6-tlsd</tt> on the command line, in order
to also drop the child's privileges before executing the application.
The point of that setup is:
</p>

<ul>
 <li> To read the private key file as root </li>
 <li> To run the application as a non-root user </li>
 <li> To run <tt>s6-tlsd</tt> as a <em>different</em> non-root user </li>
 <li> That way, even if <tt>s6-tlsd</tt>, the application, or both,
get compromised, the private key is still secure. </li>
</ul>

<h3> Written </h3>

<p>
 Unless the <tt>-Z</tt> option has been given to
<tt>s6-tlsd</tt>, <em>prog...</em> is run with all the
TLS/SSL variables <em>unset</em>: CADIR, CAFILE,
KEYFILE, CERTFILE, TLS_UID and TLS_GID. The goal is
for <tt>s6-tlsd</tt> to be, by default, as invisible
as possible.
</p>

<h2> SSL close handling </h2>

<p>
 If <em>prog</em> initiates the end of the session by sending
EOF, there are two ways for the TLS/SSL layer to handle it.
</p>

<ul>
 <li> It can send a <tt>close_notify</tt> alert, and wait for
an acknowledgement from the peer, at which point the connection
is closed. The advantage of this setup is that it is secure
even when the application protocol is not auto-terminated, i.e.
when it does not know when its data stops. Old protocols such
as HTTP-0.9 are in this case. The drawback of this setup is
that it breaks full-duplex: once a peer has sent the
<tt>close_notify</tt>, it must discard all the incoming
records that are not a <tt>close_notify</tt> from the
other peer. So if a client sends EOF while it is still
receiving data from the server, the connection closes
immediately and the data can be truncated. </li>
 <li> It can simply transmit the EOF, shutting down
half the TCP connection, and wait for the EOF back.
The advantage of this setup is that it maintains
full-duplex: a client can send EOF after its initial
request, and still receive a complete answer from the
server. The drawback is that it is insecure when the application
protocol is not auto-terminated. </li>
</ul>

<p>
 Nowadays (2017), most protocols are auto-terminated, so
it is not dangerous anymore to use EOF tranmission, and that
is the default for <tt>s6-tlsd</tt>. Nevertheless, by
using the <tt>-S</tt> option, you can
force it to use the <tt>close_notify</tt> method if your
application requires it to be secure.
</p>

<h2> <tt>s6-tlsd</tt> options </h2>

<ul>
 <li> <tt>-v&nbsp;<em>verbosity</em></tt>&nbsp: Be more or less
verbose. Default for <em>verbosity</em> is 1. 0 is quiet, 2 is
verbose, more than 2 is debug output. This option currently has
no effect. </li>
 <li> <tt>-Z</tt>&nbsp;: do not clean the environment of
<tt>s6-tlsd</tt>-related variables before spawning <em>prog...</em>. </li>
 <li> <tt>-z</tt>&nbsp;: clean the environment of
<tt>s6-tlsd</tt>-related variables before spawning <em>prog...</em>.
This is the default. </li>
 <li> <tt>-S</tt>&nbsp;: send a <tt>close_notify</tt> alert
and break the connection when <em>prog</em> sends EOF. </li>
 <li> <tt>-s</tt>&nbsp;: transmit EOF by half-closing the TCP
connection without using <tt>close_notify</tt>. This is the default. </li>
 <li> <tt>-Y</tt>&nbsp;: Require an optional client certificate. </li>
 <li> <tt>-y</tt>&nbsp;: Require a mandatory client certificate.
The default, with neither the <tt>-Y</tt> nor the <tt>-y</tt> option,
is not to require a client certificate at all. </li>
 <li> <tt>-K&nbsp;<em>kimeout</em></tt>&nbsp;: close the connection
if <em>kimeout</em> milliseconds elapse without any data being
received from either side. The default is 0, which means
infinite timeout (never kill the connection). </li>
</ul>

<h2> Notes </h2>

<ul>
 <li> The goal of the <tt>s6-tlsd</tt> interface (and its
client-side companion <a href="s6-tlsc.html">s6-tlsc</a>) is to
make it so that if you have a client, run by the command line
<tt>client...</tt> that speaks a cleartext protocol to a server
run by the command line <tt>server...</tt>, then if the server
has the proper private key and certificate, and the client has
the proper list of trust anchors, you can just change the
client command line to <tt>s6-tlsc client...</tt> and the
server command line to <tt>s6-tlsd server...</tt>
without changing the client or the server themselves, and the
communication between them will be secure. </li>
</ul>

</body>
</html>