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
|
<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-tlsc-io program</title>
<meta name="Description" content="s6-networking: the s6-tlsc-io program" />
<meta name="Keywords" content="s6-networking s6-tlsc-io tlsc tls ssl ucspi tcp inet network tcp/ip client" />
<!-- <link rel="stylesheet" type="text/css" href="//skarnet.org/default.css" /> -->
</head>
<body>
<p>
<a href="index.html">s6-networking</a><br />
<a href="//skarnet.org/software/">Software</a><br />
<a href="//skarnet.org/">skarnet.org</a>
</p>
<h1> The <tt>s6-tlsd-io</tt> program </h1>
<p>
<tt>s6-tlsd-io</tt> is a program that establishes a TLS or SSL
server connection over an existing TCP connection, then
communicates with an existing local program over already
established pipes. It is the only server-side program in
s6-networking that performs cryptography.
</p>
<p>
<a href="index.html">s6-networking</a> does not include
cryptographic software. All the crypto used in <tt>s6-tlsd-io</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 s6-networking.
</p>
<h2> Interface </h2>
<pre>
s6-tlsd-io [ -S | -s ] [ -Y | -y ] [ -v <em>verbosity</em> ] [ -K <em>kimeout</em> ] [ -k <em>snilevel</em> ] [ -d <em>notif</em> ] [ -- ] <em>fdr</em> <em>fdw</em>
</pre>
<ul>
<li> s6-tlsd-io expects to have an open connection it
can talk to on its standard input and output. It also expects to read
cleartext data from file descriptor <em>fdr</em> and write cleartext
data to file descriptor <em>fdw</em>. </li>
<li> It expects a TLS client on the other side of the network connection
to initiate a TLS handshake, and it answers it. </li>
<li> Then it acts as a full duplex tunnel, decrypting and transmitting
data from stdin to <em>fdw</em>, and encrypting and transmitting data
from <em>fdr</em> to stdout. </li>
<li> When it cannot transmit any more data from/to the local application
because connections have closed, <tt>s6-tlsd-io</tt> exits. </li>
</ul>
<h2> Exit codes </h2>
<ul>
<li> 0: the connection terminated normally.
<li> 96: error while configuring the TLS context - for instance, invalid private key or server certificate files. </li>
<li> 97: error while setting up the TLS server engine. </li>
<li> 98: TLS error while running the engine. </li>
<li> 100: wrong usage. </li>
<li> 111: system call failed. </li>
</ul>
<h2> Protocol version and parameters </h2>
<p>
During the TLS/SSL handshake, <tt>s6-tlsd-io</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="https://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-io</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>
<p>
<tt>s6-tlsd-io</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 chain, 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-io</tt>
will refuse to run.
</p>
<p>
Alternatively, if <em>snilevel</em> is nonzero, the private
key for the server named <em>x</em> should be held in a file
whose name is contained in the <tt>KEYFILE:<em>x</em></tt>
environment variable, and the corresponding certificate chain
file should be named in the <tt>CERTFILE:<em>x</em></tt>
environment variable. If <em>snilevel</em> is 2 or more, the
<tt>KEYFILE</tt> and <tt>CERTFILE</tt> variables will be
entirely ignored.
</p>
<p>
You can wildcard the first level of a SNI domain: you can point
to a valid certificate for <tt><em>foo</em>.example.com</tt> for all
values of <em>foo</em> via a variable called <tt>CERTFILE:*.example.com</tt>
(and have the corresponding <tt>KEYFILE:*.example.com</tt>). Only the
first level can be wildcarded, and this does not work for top-level
domains (you cannot hold a certificate for <tt>*.com</tt>). Note: if you are
using a shell to handle your environment variables, be careful to
properly quote them so that it does not attempt to expand the asterisks.
</p>
<p>
If you are using client certificates, <tt>s6-tlsd-io</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-io</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-io</tt>
then drops its root privileges to this uid/gid after reading its
private key file. This ensures that the engine, including the
handshake, is run with as little privilege as possible.
</p>
<h2> SSL close handling </h2>
<p>
If the local application initiates the end of the session by sending
EOF to <em>fdr</em>, there are two ways for the TLS 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 (2020), most protocols are auto-terminated, so
it is not dangerous anymore to use EOF tranmission, and that
is the default for <tt>s6-tlsd-io</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-io</tt> options </h2>
<ul>
<li> <tt>-v <em>verbosity</em></tt> : 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>-S</tt> : send a <tt>close_notify</tt> alert
and break the connection when receiving a local EOF. </li>
<li> <tt>-s</tt> : transmit EOF by half-closing the TCP
connection without using <tt>close_notify</tt>. This is the default. </li>
<li> <tt>-Y</tt> : Request an client certificate.
The certificate is optional: if the client gives none, the connection
proceeds. </li>
<li> <tt>-y</tt> : Request a client certificate.
The certificate is mandatory: if the client gives none, the handshake
fails.
The default, with neither the <tt>-Y</tt> nor the <tt>-y</tt> option,
is not to request a client certificate at all. </li>
<li> <tt>-K <em>kimeout</em></tt> : if the peer fails
to send data for <em>kimeout</em> milliseconds during the handshake,
close the connection. The default is 0, which means infinite timeout
(never kill the connection). </li>
<li> <tt>-k <em>snilevel</em></tt> : support alternative
certificate chains for SNI. If <em>snilevel</em> is nonzero, private
key file names are read from every environment variable of the form
<tt>KEYFILE:<em>x</em></tt>, where <em>x</em> is a server name that
the client may require, and a corresponding certificate chain for the name
<em>x</em> should exist in the file named after the contents of the
<tt>CERTFILE:<em>x</em></tt> environment variable. If <em>snilevel</em>
is 2 or more, <em>only</em> those files are read, and the generic
<tt>KEYFILE</tt> and <tt>CERTFILE</tt> variables are ignored.
If <em>snilevel</em> is 0, or if the option is not given, which is the
default, <tt>KEYFILE</tt> and <tt>CERTFILE</tt> are the only private
key / certificate chain pair that are loaded, no other environment
variable is read for keypairs. </li>
<li> <tt>-d <em>notif</em></tt> : handshake notification.
<em>notif</em> must be a file descriptor open for writing. When the
TLS handshake has completed, some data (terminated by two null
characters) will be sent to file descriptor <em>notif</em>. The
data contains information about the TLS parameters of the connection;
its exact contents are left unspecified, but there's at least
an <tt>SSL_PROTOCOL=<em>protocol</em></tt> string and
an <tt>SSL_CIPHER=<em>cipher</em></tt> string, both
null-terminated.
Sending this data serves a dual purpose: telling the <em>notif</em>
reader that the handshake has completed, and providing it with some
basic information about the connection. If this option is not given,
no such notification is performed. </li>
</ul>
</body>
</html>
|