Stunnel HOWTO
Getting started
Stunnel adds TLS to an existing TCP or UDP service. It usually runs in one of two modes:
- Server mode accepts TLS connections and forwards decrypted traffic to a local or remote application. This is the default.
- Client mode accepts plaintext connections from a local application, establishes TLS to a remote server, and verifies that server.
A standalone configuration contains global options followed by one or more named service sections. Put global options before the first service section.
Check the installed version, linked OpenSSL version, compile-time defaults, and available features with:
stunnel -version
stunnel -options
stunnel -sockets
Package locations vary. Common configuration paths include /etc/stunnel/stunnel.conf and /usr/local/etc/stunnel/stunnel.conf. Pass an explicit path when in doubt:
stunnel /etc/stunnel/stunnel.conf
Server mode: add TLS to a plaintext service
Suppose an HTTP application listens on 127.0.0.1:8080, and stunnel should expose it over TLS on port 8443:
foreground = yes
debug = info
[web]
accept = 0.0.0.0:8443
connect = 127.0.0.1:8080
cert = /etc/stunnel/fullchain.pem
key = /etc/stunnel/private/server.key
sslVersionMin = TLSv1.2
Use accept = :::8443 to listen on all IPv6 addresses. Whether that socket also accepts IPv4 connections depends on the operating system.
Server mode requires a certificate chain and its private key. The key option may be omitted when the private key is stored in the file named by cert, but separate files are usually easier to manage securely.
Remove foreground = yes when a service manager is responsible for starting stunnel in the background.
Client mode: protect a local plaintext client
Suppose a legacy application can connect only without TLS. Configure it to use 127.0.0.1:8080, then have stunnel connect securely to server.example.com:8443:
foreground = yes
debug = info
[remote-web]
client = yes
accept = 127.0.0.1:8080
connect = server.example.com:8443
verifyChain = yes
CAfile = /etc/ssl/certs/ca-certificates.crt
checkHost = server.example.com
sni = server.example.com
sslVersionMin = TLSv1.2
The CA bundle path is distribution-specific. Other common paths are /etc/ssl/cert.pem and /etc/pki/tls/certs/ca-bundle.crt.
A secure TLS client configuration normally needs all of the following:
verifyChain = yesto validate the certificate chain.CAfile,CApath, orCAstoreto define trusted certificate authorities.checkHostorcheckIPto verify the identity of the server.sniwhen the server uses name-based virtual hosting.
Do not expose a client-mode accept port to untrusted networks unless remote plaintext access is intentional.
Multiple services and configuration fragments
One stunnel process can serve multiple independent tunnels:
[imap]
client = yes
accept = 127.0.0.1:1143
connect = mail.example.com:993
verifyChain = yes
CAfile = /etc/ssl/certs/ca-certificates.crt
checkHost = mail.example.com
sni = mail.example.com
[smtp]
client = yes
accept = 127.0.0.1:1025
connect = mail.example.com:465
verifyChain = yes
CAfile = /etc/ssl/certs/ca-certificates.crt
checkHost = mail.example.com
sni = mail.example.com
The include = DIRECTORY option can load configuration fragments in alphabetical order. A useful naming scheme is 00-global.conf, 01-imap.conf, and 02-smtp.conf.
TLS authentication
Certificates in server mode
For a public service, obtain a certificate from a trusted certificate authority, usually through an ACME client. Configure cert with the leaf certificate followed by the required intermediate certificates, and configure key with the corresponding private key.
Protect private keys on Unix:
chmod 600 /etc/stunnel/private/server.key
Set the file owner to the account that loads the key. If stunnel starts as root and then drops privileges, root ownership is appropriate; a service that starts unprivileged needs ownership or group permissions that allow its service account to read the key.
For short-lived development or testing, a self-signed certificate with a Subject Alternative Name can be generated with a recent OpenSSL release:
openssl req -x509 -newkey rsa:3072 -sha256 -nodes \
-keyout server.key -out server.crt -days 30 \
-subj "/CN=server.example.com" \
-addext "subjectAltName=DNS:server.example.com"
chmod 600 server.key
A client will trust this certificate only when server.crt is explicitly installed as a trusted certificate. Do not disable verification merely to suppress self-signed-certificate errors.
Certificate verification in client mode
Use chain verification and identity verification together:
verifyChain = yes
CAfile = /path/to/trusted-ca-bundle.pem
checkHost = server.example.com
sni = server.example.com
Use checkIP instead of checkHost when the certificate identifies the service by IP address. Modern certificates should carry identities in the Subject Alternative Name extension; the Common Name alone is not a replacement for correct SAN entries.
The numeric verify option is obsolete. Use:
verifyChain = yesfor public-key infrastructure (PKI) validation from a trusted root.verifyPeer = yesto trust only a locally installed leaf certificate (certificate pinning).
A pinning configuration looks like this:
verifyPeer = yes
CAfile = /etc/stunnel/pinned-server.pem
Pinned certificates must be updated before they expire or are replaced.
Mutual TLS
To require client certificates, configure the server with the CA that issues them:
[mutual-tls-server]
accept = 0.0.0.0:8443
connect = 127.0.0.1:8080
cert = /etc/stunnel/server-fullchain.pem
key = /etc/stunnel/private/server.key
verifyChain = yes
CAfile = /etc/stunnel/client-ca.pem
verifyChain = yes implies requireCert = yes. The client presents its own certificate and key while still verifying the server:
[mutual-tls-client]
client = yes
accept = 127.0.0.1:8080
connect = server.example.com:8443
cert = /etc/stunnel/client-fullchain.pem
key = /etc/stunnel/private/client.key
verifyChain = yes
CAfile = /etc/stunnel/server-ca.pem
checkHost = server.example.com
sni = server.example.com
Pre-shared keys
TLS-PSK can be simpler than maintaining a certificate authority for a closed group of stunnel clients and servers. Store one identity and secret per line in the file used by PSKsecrets:
client1:0123456789abcdef0123456789abcdef
The key must contain at least 16 bytes; hexadecimal keys therefore need at least 32 hexadecimal characters. The file must not be world-readable or world-writable. Give each client a unique secret. See the authentication tutorial for complete PSK examples.
Running stunnel
Foreground testing and logs
During initial setup, run in the foreground and use informational logging:
foreground = yes
debug = info
Startup validates the configuration and initializes certificates, keys, listening sockets, and cryptographic settings. A valid standalone configuration continues running; use Ctrl+C to stop it.
The default log level is notice. The debug = debug (or debug = 7) level is intended for developers and for logs requested by technical support. It is usually too verbose for routine troubleshooting.
Use output = FILE to write a log file and log = append or log = overwrite to control how it is opened. On Unix, syslog = yes is enabled by default.
Unix signals
SIGHUPreloads the configuration. Thechroot,foreground,pid,setgid, andsetuidglobal options are not reloaded.SIGUSR1reopens the log file after rotation.SIGUSR2logs the active connections.SIGTERM,SIGQUIT, andSIGINTshut down stunnel.
For example:
kill -HUP "$(cat /run/stunnel.pid)"
A package-provided systemd or other service-manager unit may offer its own reload command. Prefer that interface when available.
Windows service
From an elevated command prompt, install a service with an explicit configuration file, then control it with the service commands:
stunnel -install stunnel.conf
stunnel -start
stunnel -reload
stunnel -reopen
stunnel -stop
stunnel -uninstall
Use stunnel -help to confirm the command syntax of the installed build.
Privilege separation
On Unix, bind listening sockets before dropping privileges:
setuid = stunnel
setgid = stunnel
A chroot can provide additional isolation, but every required file must be available at the correct path inside the jail. This may include the configuration, certificates, CA files, resolver files, timezone data, logs, PID file, and devices. Containers or service-manager sandboxing are often easier to maintain.
Inetd mode, TCP Wrappers, and direct exec services remain available for compatibility, but named standalone service sections and operating-system access controls are preferable for new deployments. See man stunnel if a legacy integration requires one of these modes.
Security recommendations
- Keep stunnel and OpenSSL updated.
- Prefer the default cipher and curve configuration unless interoperability requirements justify an override.
- Use
sslVersionMin = TLSv1.2for broadly compatible new deployments, or TLS 1.3 when every peer supports it. - Use
sslVersionMinandsslVersionMaxinstead of disabling protocol versions withoptions. - Verify both the certificate chain and the expected host or IP address in client mode.
- Restrict private keys and PSK files with operating-system permissions.
- Bind plaintext client-mode listeners to loopback or another trusted interface.
- Do not enable TLS compression; it can expose secrets when attacker-controlled and confidential data are compressed together.
- Test certificate renewal and configuration reload procedures before certificates expire.
- Treat
securityLevel, cipher, curve, and FIPS changes as cryptographic policy decisions, not generic troubleshooting steps.
The complete and authoritative option reference for the installed build is available in man stunnel and through stunnel -help, stunnel -version, stunnel -options, and stunnel -sockets.


