summaryrefslogtreecommitdiff
path: root/docs/configuration/service/stunnel.md
blob: b66e7518786fff51efd351868b962ecca6f2c15c (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
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
(stunnel)=
# Stunnel

**stunnel** wraps TCP connections in {abbr}`TLS (Transport Layer Security)`
and authenticates peers using X.509 certificates, a pre-shared key, or
both. It is commonly used to secure protocols that lack native TLS
support, such as plain IMAP, POP3, or SMTP. You can also use it to build
TLS-encrypted tunnels for other services, such as a SOCKS proxy.

Each named service (`service stunnel client|server <name>`) operates in
one of the following modes:

- **Client:** Accepts plaintext connections locally and forwards them,
  encrypted, to a remote TLS endpoint.
- **Server:** Accepts TLS connections and forwards them, decrypted, to a
  local plaintext service.

The following sections describe how to configure a service in each mode.

## Configuration

### Connection endpoints

The following commands define where a service accepts connections and
where it forwards them. They are the same for client and server modes.

```{cfgcmd} set service stunnel \<client | server\> \<name\> listen address \<address\>

**Configure the local address on which the specified service accepts
incoming connections.**

The value can be an IPv4 address, an IPv6 address, or an
{abbr}`FQDN (Fully Qualified Domain Name)`.

When unset, the service accepts connections on all local IPv4 addresses,
and the listen port must then be free on every local IPv4 address.
```

Example:

```none
set service stunnel server app1 listen address 192.0.2.1
```

```{cfgcmd} set service stunnel \<client | server\> \<name\> listen port \<1-65535\>

**Configure the TCP port on which the specified service accepts incoming
connections.**

A listen port is mandatory for every named service.

The listen address and port together must not already be in use on the
router, either by another stunnel service or by any other local process.
Otherwise, the commit fails.
```

Example:

```none
set service stunnel server app1 listen port 443
```

```{cfgcmd} set service stunnel \<client | server\> \<name\> connect address \<address\>

**Configure the destination address to which the specified service
forwards accepted connections.**

The value can be an IPv4 address, an IPv6 address, or an FQDN.

In client mode, the destination is typically a remote TLS server, and in
server mode, it is typically a plaintext service.

When unset, the service uses the local host as the destination.
```

Example:

```none
set service stunnel client app1 connect address 203.0.113.10
```

```{cfgcmd} set service stunnel \<client | server\> \<name\> connect port \<1-65535\>

**Configure the destination TCP port to which the specified service
forwards accepted connections.**

A connect port is mandatory for every named service, except a
server-mode service using the `socks` protocol, where `connect` must not
be configured at all. Otherwise, the commit fails.
```

Example:

```none
set service stunnel client app1 connect port 443
```

### TLS certificates

The following commands configure certificate-based authentication for a
service.

```{cfgcmd} set service stunnel \<client | server\> \<name\> ssl certificate \<name\>

**Reference a TLS certificate and its private key from the 
{doc}`PKI subsystem </configuration/pki/index>`
to the specified service.**

The pair must already be defined under `set pki certificate <cert-name>`.

The service presents this certificate to authenticate itself to the
remote peer during the TLS handshake.

A server-mode service requires either a TLS certificate from the PKI
subsystem or at least one pre-shared key. Otherwise, the commit fails.

A TLS certificate is optional for a client-mode service.
```

Example:

```none
set service stunnel server app1 ssl certificate srv-cert
```

```{cfgcmd} set service stunnel \<client | server\> \<name\> ssl ca-certificate \<name\>

**Add a CA certificate from the PKI subsystem to the trusted CA store of
the specified service.**

The CA certificate must already be defined under `set pki ca <ca-name>`.

Repeat the command to add multiple CA certificates.
```

```{note}
Configuring a CA certificate loads it into the service's trusted CA
store, but it does not make the service validate the certificate that the
peer presents. Peer-certificate validation cannot currently be enabled
from the CLI, so the handshake completes even when the peer certificate
is not signed by a CA in the store.
```

Example:

```none
set service stunnel client app1 ssl ca-certificate my-ca
```

### Pre-shared keys

As an alternative or in addition to TLS certificates, a service can
authenticate its peers with TLS pre-shared keys. Each PSK entry pairs an
identity with a secret key, and the client and server must be configured
with a matching identity and secret.

During the TLS handshake, a server-mode service accepts any peer whose
identity matches one of its configured PSK pairs. A client-mode service
presents only a single identity. If several PSK entries are defined on a
client, only one is used, so configure exactly one.

```{cfgcmd} set service stunnel \<client | server\> \<name\> psk \<name\> id \<id\>

**Configure the identity for the specified PSK entry.**

The PSK entry name is only a local configuration label. The `id` value is
the identity exchanged with the peer.

Both an identity and a secret must be configured for every PSK entry.

To configure additional identities, define separate PSK entries
(`psk <name>`), each with its own `id`.
```

Example:

```none
set service stunnel server app1 psk key1 id client1
```

```{cfgcmd} set service stunnel \<client | server\> \<name\> psk \<name\> secret \<secret\>

**Configure the pre-shared secret key, as a hexadecimal string, for the
specified PSK entry.**

The key must be at least 16 bytes long, which implies at least 32
hexadecimal characters. Otherwise, the commit fails.
```

```{note}
Use the `generate psk random size <32-512>` operational command to
generate a valid random secret. The `<32-512>` size is specified in
bytes.
```

Example:

```none
set service stunnel server app1 psk key1 secret 1234567890abcdef1234567890abcdef
```

### Protocol negotiation

By default, a service encrypts or decrypts the whole TCP connection. For
applications that upgrade a plaintext connection to TLS (STARTTLS-style),
and for other protocol-specific exchanges such as SOCKS or proxy
handshakes, the application protocol must be declared so that stunnel
performs this negotiation before starting TLS.

```{cfgcmd} set service stunnel \<client | server\> \<name\> protocol \<cifs | connect | imap | nntp | pgsql | pop3 | proxy | smtp | socks\>

**Configure the application protocol used for the initial,
protocol-specific negotiation that precedes TLS encryption.**

This option should not be used when TLS runs on its own dedicated port.

The `connect` and `nntp` protocols are available only in client mode.
```

Example:

```none
set service stunnel client app1 protocol connect
```

### Protocol options

The following commands tune the protocol negotiation of a client-mode
service. They are committable only when the service's protocol is
`connect` or `smtp`. With the `smtp` protocol, the `domain` and `host`
options are not available.

```{cfgcmd} set service stunnel client \<name\> options authentication \<basic | ntlm | plain | login\>

**Configure the authentication type for the protocol negotiation.**

The `connect` protocol supports `basic` or `ntlm` authentication;
`basic` is the default. The `smtp` protocol supports `plain` or `login`
authentication; `plain` is the default.
```

Example:

```none
set service stunnel client app1 options authentication ntlm
```

```{cfgcmd} set service stunnel client \<name\> options domain \<domain\>

**Configure the domain used for the connect protocol negotiation.**

The value must be a FQDN.
```

Example:

```none
set service stunnel client app1 options domain example.com
```

```{cfgcmd} set service stunnel client \<name\> options host address \<address\>

**Configure the final destination address the intermediate proxy
connects to during the connect protocol negotiation.**

The intermediate proxy itself is the service's `connect` destination.

Both a `host address` and a `host port` are required.
```

Example:

```none
set service stunnel client app1 options host address 198.51.100.10
```

```{cfgcmd} set service stunnel client \<name\> options host port \<1-65535\>

**Configure the TCP port of the final destination the intermediate proxy
connects to during the connect protocol negotiation.**
```

Example:

```none
set service stunnel client app1 options host port 443
```

```{cfgcmd} set service stunnel client \<name\> options username \<username\>

**Configure the username used for the protocol negotiation.**
```

Example:

```none
set service stunnel client app1 options username stunnel-user
```

```{cfgcmd} set service stunnel client \<name\> options password \<password\>

**Configure the password used for the protocol negotiation.**
```

Example:

```none
set service stunnel client app1 options password mysecretpassword
```

### Logging

```{cfgcmd} set service stunnel log level \<emerg | alert | crit | err | warning | notice | info | debug\>

**Configure the severity threshold for stunnel logging.**

The levels correspond to syslog severity levels. Messages at the
configured level and all more severe levels are logged.

The default is `notice`.
```

Example:

```none
set service stunnel log level info
```

## Examples

### TLS wrapper for a plaintext service

The following example demonstrates how two VyOS routers secure a legacy
plaintext application over an untrusted network by protecting its
traffic with TLS, without modifying the application.

On the router at `192.0.2.1`, stunnel runs in server mode: it terminates
TLS and forwards the connection to a local application on port 8080. On
the router at `192.0.2.2`, stunnel runs in client mode: it wraps the
application's connection in TLS and forwards it to the server.

On `192.0.2.1` (server mode):

```none
set service stunnel server app1 listen address 192.0.2.1
set service stunnel server app1 listen port 443
set service stunnel server app1 connect address 127.0.0.1
set service stunnel server app1 connect port 8080
set service stunnel server app1 ssl certificate srv-cert
```

On `192.0.2.2` (client mode):

```none
set service stunnel client app1 listen address 127.0.0.1
set service stunnel client app1 listen port 8080
set service stunnel client app1 connect address 192.0.2.1
set service stunnel client app1 connect port 443
```

### TLS-secured SOCKS proxy

To build a TLS-secured SOCKS proxy, configure a **server** service with
`protocol socks` - note that no `connect` target is set on the server side
since SOCKS negotiates its own destination - and a matching **client**
service that exposes a local SOCKS listener:

```none
set service stunnel server srv-one listen port 9001
set service stunnel server srv-one protocol 'socks'
set service stunnel server srv-one psk sock_proxy id 'cli-one'
set service stunnel server srv-one psk sock_proxy secret '1234567890ABCDEF1234567890ABCDEF'

set service stunnel client cli-one listen port 9000
set service stunnel client cli-one connect port 9001
set service stunnel client cli-one psk sock_proxy id 'cli-one'
set service stunnel client cli-one psk sock_proxy secret '1234567890ABCDEF1234567890ABCDEF'
```

### TLS via an HTTP CONNECT proxy

To tunnel an authenticated HTTP CONNECT proxy session:

```none
set service stunnel client app2 listen address '127.0.0.1'
set service stunnel client app2 listen port 83
set service stunnel client app2 connect address '192.168.0.10'
set service stunnel client app2 connect port 84

set service stunnel client app2 protocol 'connect'
set service stunnel client app2 options authentication 'basic'
set service stunnel client app2 options domain 'example.com'
set service stunnel client app2 options host address '127.0.0.1'
set service stunnel client app2 options host port 5000
set service stunnel client app2 options username 'user'
set service stunnel client app2 options password 'password'
```