Stunnel FAQ
- Configuration
- Authentication and certificates
- Troubleshooting
- Applications and protocols
- Operations and performance
Configuration
What is the difference between server mode and client mode?
Server mode is the default. Stunnel accepts TLS connections and forwards the decrypted traffic to the service selected by connect, exec, or a supported protocol handler.
Client mode is enabled with client = yes. Stunnel accepts plaintext traffic, normally on a loopback address, and establishes TLS to the target named by connect.
[local-client]
client = yes
accept = 127.0.0.1:8080
connect = server.example.com:443
verifyChain = yes
CAfile = /etc/ssl/certs/ca-certificates.crt
checkHost = server.example.com
sni = server.example.com
The CA bundle path varies by operating system.
Why does stunnel start but not listen on a port?
A standalone service needs a named section and an accept option:
[service]
accept = 0.0.0.0:8443
connect = 127.0.0.1:8080
A configuration without a service section is interpreted as an inetd-style configuration, in which another process supplies an already accepted socket. Inetd mode is primarily for legacy integrations.
Also check that:
- The service section was not accidentally placed in a file that is not included.
- Another process is not already using the port.
- The configured address exists on the host.
- The process has permission to bind the port.
- An operating-system firewall permits the connection.
Use accept = :::8443 to listen on all IPv6 addresses. IPv4 behavior for an IPv6 listening socket is operating-system-dependent.
How do I check a configuration?
The current command-line interface has no separate check-only option. Run stunnel in the foreground during initial testing:
foreground = yes
debug = info
Then start it with the explicit configuration path:
stunnel /etc/stunnel/stunnel.conf
Stunnel reports syntax errors and failures while loading certificates, keys, cryptographic settings, or listening sockets. If initialization succeeds, it continues running; stop it with Ctrl+C.
Where is the configuration file?
The default is selected at build time and is shown by stunnel -version. Common locations are /etc/stunnel/stunnel.conf and /usr/local/etc/stunnel/stunnel.conf. An explicit path avoids ambiguity:
stunnel /path/to/stunnel.conf
On Windows, use the installer-selected configuration directory or pass the intended configuration file explicitly.
Can one stunnel process run several services?
Yes. Add one named section for each service. Service-level options remain in effect until the next section. Put global options before the first section.
The include = DIRECTORY option loads configuration fragments in ascending filename order. Names such as 00-global.conf, 01-imap.conf, and 02-smtp.conf make the order clear.
Which TLS versions and ciphers should I configure?
The defaults provided by current stunnel and OpenSSL releases are preferable for most deployments. For a new service, set only the required minimum TLS version:
sslVersionMin = TLSv1.2
Use TLSv1.3 when all peers support it. Use sslVersionMin and sslVersionMax rather than disabling individual versions with options.
The ciphers option controls TLS 1.2 and earlier. The ciphersuites option separately controls TLS 1.3. Changing either can reduce security or interoperability, so keep the defaults unless a documented policy requires otherwise. Run stunnel -version to see the defaults of the installed build and stunnel -options to list supported TLS options.
How do I use SNI?
In client mode, set sni to the remote DNS name when the server hosts multiple TLS services:
sni = server.example.com
SNI selects the virtual server; it does not verify its identity. Use verifyChain = yes and checkHost = server.example.com as well.
In server mode, stunnel can route TLS connections to secondary service sections according to the client's SNI name. See the sni option in man stunnel for the primary and secondary service syntax.
Authentication and certificates
Does every stunnel service need a certificate?
No.
- A TLS server normally needs
certandkeyso that it can authenticate itself. - A TLS client does not need its own certificate unless the server requires mutual TLS.
- A PSK service uses
PSKsecretsinstead of certificate authentication.
The key option defaults to the value of cert, so it may be omitted when the certificate chain and private key are stored in the same file.
How should a client verify a server certificate?
Certificate-chain validation and server-identity validation are separate checks. Configure both:
verifyChain = yes
CAfile = /path/to/trusted-ca-bundle.pem
checkHost = server.example.com
sni = server.example.com
Use checkIP instead of checkHost when connecting by an IP address represented in the certificate. Do not rely on SNI alone: it sends a name but does not authenticate it.
CAfile, CApath, and, with OpenSSL 3.0 or later, CAstore provide trust anchors. The syntax and availability of CAstore URIs depend on the linked OpenSSL providers.
What is the difference between verifyChain and verifyPeer?
verifyChain = yesvalidates the peer certificate through a trusted CA. In client mode, combine it withcheckHostorcheckIP.verifyPeer = yesrequires the exact leaf certificate to be installed locally inCAfileorCApath. This is certificate pinning.
The numeric verify option is obsolete and should not be used in new configurations.
Why does certificate verification fail with "unable to get local issuer certificate"?
Usually either the peer did not send the required intermediate certificate or the local trust store does not contain the issuing CA.
For a server, configure cert with the leaf certificate followed by the required intermediate certificates. For a client, point CAfile, CApath, or CAstore at the intended trust anchors. Do not solve this error by disabling verification.
Useful OpenSSL diagnostics include:
openssl s_client -connect server.example.com:443 \
-servername server.example.com \
-verify_hostname server.example.com \
-CAfile trusted-ca-bundle.pem
openssl verify -CAfile trusted-ca-bundle.pem \
-untrusted intermediate-chain.pem server.crt
Why does checkHost or checkIP fail?
The expected identity must appear in the leaf certificate's Subject Alternative Name extension. DNS names belong in checkHost; IP addresses belong in checkIP. Wildcard certificates match only according to the OpenSSL hostname-verification rules.
Make sure the value describes the final TLS server, not a local stunnel listener, load balancer address, or HTTP proxy.
How can I tell whether a certificate matches its private key?
Compare hashes of their public keys:
openssl x509 -in server.crt -pubkey -noout | openssl sha256
openssl pkey -in server.key -pubout | openssl sha256
The hashes must match.
Why does stunnel reject the private-key file permissions?
A private key allows an attacker to impersonate the service. On Unix, restrict it to the account that loads it:
chmod 600 /etc/stunnel/private/server.key
Set the owner to match the startup model. Root ownership is appropriate when stunnel starts as root and drops privileges; a service that starts unprivileged needs ownership or group permissions for its service account. The process must be able to read the key before applying setuid or setgid. PSK files must likewise be neither world-readable nor world-writable.
Can stunnel use PKCS#12 files, hardware tokens, or system stores?
The cert option accepts PEM or P12 certificate files. Current builds can also use certificate and key URIs supplied by OpenSSL engines or providers. OpenSSL 3 provider support includes the provider and providerParameter global options; availability depends on how stunnel and OpenSSL were built.
Use stunnel -version to inspect the linked OpenSSL version and the engine, FIPS, and other compile-time capabilities reported by the build. Consult man stunnel and the provider documentation before deploying a hardware-backed key.
How do I reload a renewed certificate?
After replacing the certificate and key atomically, reload the configuration:
- Unix: send
SIGHUPor use the package's service-manager reload command. - Windows service: run
stunnel -reload.
Review the log to confirm that the new certificate and key loaded successfully. Test renewal and reload procedures before the certificate expires.
Should I use a self-signed certificate?
Self-signed certificates are suitable for controlled testing and can be used for pinning. Every client must explicitly trust the certificate, and the certificate still needs correct Subject Alternative Name entries.
For public or broadly distributed services, use a certificate from an appropriate CA. Never disable certificate verification merely to make a self-signed certificate work.
Troubleshooting
What information should I collect before reporting a problem?
Include:
- The output of
stunnel -version. - The operating system and installation source.
- The relevant configuration with passwords, PSKs, and private data removed.
- The exact error and the surrounding log messages.
- Whether the failure occurs at startup, TCP/UDP connection, TLS handshake, or application-data transfer.
- Whether a direct connection to the backend succeeds.
Start with debug = info. Use debug = debug (equivalent to debug = 7) only when requested by a stunnel developer or technical support; it is intentionally very verbose.
What does "wrong version number" or "unknown protocol" mean?
This usually means that one side expected TLS while the other sent plaintext. Check:
- Whether
client = yesis set on the side initiating TLS. - Whether
acceptandconnectpoint to the intended plaintext and TLS ports. - Whether the application expects implicit TLS on a dedicated port or negotiates TLS with STARTTLS.
- Whether an HTTP proxy requires
protocol = connect.
For STARTTLS-style services, use the appropriate protocol handler rather than connecting TLS directly to the plaintext protocol port.
Why does the TLS handshake fail after I changed the cipher configuration?
TLS 1.3 and earlier versions use separate settings:
ciphersuitescontrols TLS 1.3.cipherscontrols TLS 1.2 and earlier.
The selected certificate type, TLS version limits, OpenSSL security level, and peer policy must also be compatible. Restore the defaults first, then make one policy change at a time. stunnel -version prints the active defaults.
Why can stunnel connect to the TLS peer but not pass application data?
TLS only protects the bytes; it does not make incompatible application protocols compatible. Verify that:
- The backend is reachable directly from the stunnel host.
- The client and backend speak the same application protocol.
protocolis configured only when negotiation such as STARTTLS, HTTP CONNECT, SOCKS, or the PROXY protocol is required.- The application is not expecting another TLS layer.
TIMEOUTconnect,TIMEOUTbusy, andTIMEOUTidleare appropriate.
Capture traffic on the plaintext side only in a controlled environment because it may contain credentials or other sensitive data.
Why is a connection slow to start?
Common causes include DNS timeouts, an unreachable first connect target, OCSP delays, overloaded backends, and network packet loss.
Stunnel automatically uses delayed resolution when a target cannot be resolved at startup. Set delay = yes when DNS must always be deferred, such as with dynamic DNS. Note that delayed resolution uses priority failover.
Avoid changing socket options such as TCP_NODELAY until measurements identify a TCP buffering problem.
What does "too many open files" mean?
The process reached an operating-system resource limit. Each proxied connection consumes multiple file descriptors. Increase the service's file-descriptor limit and verify process, memory, and service-manager limits. On systemd, the relevant unit setting is commonly LimitNOFILE.
Do not set an unlimited TLS session cache merely to work around capacity issues; sessionCacheSize = 0 can permit a memory-exhaustion denial of service.
Why does stunnel fail after chroot or dropping privileges?
Paths and permissions change when chroot, setuid, or setgid is used. The jail may need copies of:
- The configuration and included fragments.
- Certificates, keys, CA files, CRLs, logs, and the PID file.
- Resolver configuration such as
/etc/nsswitch.confand/etc/resolv.conf. - Timezone files and required devices.
Paths documented as relative to the chroot must be written accordingly. Also remember that a process which has dropped privileges may be unable to rebind privileged ports during a reload.
Stunnel reports a random-number-generator error. What should I do?
Current OpenSSL releases normally obtain entropy from the operating system. Treat a failure as an operating-system, container, or OpenSSL initialization problem; do not seed the generator with arbitrary files or copied kernel data.
RNDfile and EGD remain available for unusual or legacy platforms. Use them only with a well-designed entropy source and follow the OpenSSL guidance for that platform.
Do TCP Wrappers still control access?
Not by default. libwrap defaults to no and is available only in builds compiled with that support. If a legacy deployment requires /etc/hosts.allow and /etc/hosts.deny, set libwrap = yes and confirm Auth:LIBWRAP appears in stunnel -version.
For new deployments, use the operating-system firewall, service-manager controls, network policy, and TLS client authentication.
Applications and protocols
Can stunnel protect any TCP service?
Usually, if the application uses one TCP connection and either:
- TLS starts immediately on a dedicated port; or
- stunnel supports the application's TLS negotiation through
protocol.
Current protocol handlers include IMAP, LDAP, NNTP, PostgreSQL, POP3, SMTP, HTTP CONNECT, SOCKS, and HAProxy PROXY protocol, among others. Run man stunnel for the exact list in the installed version.
Protocols that open additional dynamic connections, depend on unusual out-of-band behavior, or embed network addresses may need application-aware gateways.
Can stunnel forward UDP?
Yes. Current stunnel versions support DTLS over UDP:
[dtls-service]
transport = udp
accept = 0.0.0.0:9443
connect = 127.0.0.1:9000
cert = /etc/stunnel/server-fullchain.pem
key = /etc/stunnel/private/server.key
Each datagram opens a logical connection within the service, so confirm that this behavior fits the application. Both endpoints must use compatible DTLS configurations; setting transport = udp does not convert an arbitrary TCP protocol into UDP or vice versa.
Can stunnel wrap FTP?
Not as a generic single tunnel. FTP opens separate, dynamically negotiated data connections. Use an FTP implementation with native TLS support or a protocol-aware gateway.
How do I use a STARTTLS-style protocol?
Set protocol to the application protocol so stunnel performs the plaintext negotiation before enabling TLS. For example, a client-side SMTP tunnel may use:
[smtp-submission]
client = yes
accept = 127.0.0.1:1025
connect = mail.example.com:587
protocol = smtp
protocolHost = client.example.com
verifyChain = yes
CAfile = /etc/ssl/certs/ca-certificates.crt
checkHost = mail.example.com
sni = mail.example.com
Do not set protocol when connecting to a port that expects TLS immediately, such as the usual implicit-TLS ports.
How do I connect through an HTTP proxy?
Use the client-side HTTP CONNECT handler. connect names the proxy, while protocolHost names the final TLS server:
[through-proxy]
client = yes
accept = 127.0.0.1:8443
connect = proxy.example.net:3128
protocol = connect
protocolHost = server.example.com:443
verifyChain = yes
CAfile = /etc/ssl/certs/ca-certificates.crt
checkHost = server.example.com
sni = server.example.com
If required, configure protocolUsername, protocolPassword, and protocolAuthentication. Protect configuration files containing credentials.
Can stunnel load-balance or fail over between backends?
Yes. Specify connect more than once:
[service]
accept = 0.0.0.0:8443
connect = backend1.example.com:8080
connect = backend2.example.com:8080
failover = rr
cert = /etc/stunnel/server-fullchain.pem
key = /etc/stunnel/private/server.key
Use failover = rr for round-robin distribution or failover = prio to prefer targets in configuration order.
How can the backend learn the original client address?
If the backend understands HAProxy PROXY protocol version 1, use protocol = proxy. Otherwise, selected Unix platforms support transparent = source, which requires elevated privileges and operating-system routing or firewall configuration.
Do not enable either mode unless the backend and network are configured to trust it. In particular, a backend must not accept forged PROXY headers from untrusted sources.
Can stunnel connect to a Unix-domain socket?
Yes, on Unix. An address parameter may be a TCP port, a host-and-port pair, or a Unix socket path. The stunnel account needs the appropriate filesystem permissions. Service-level setuid and setgid can set the owner and group of a Unix socket created by accept.
Operations and performance
How do I reload stunnel or rotate its log?
On Unix:
SIGHUPreloads the configuration.SIGUSR1closes and reopens the log file.SIGUSR2logs the active connections.SIGTERM,SIGQUIT, andSIGINTstop stunnel.
The chroot, foreground, pid, setgid, and setuid global options are not changed by a reload. Prefer the package's service-manager commands when available.
On Windows services, use stunnel -reload, stunnel -reopen, and stunnel -stop.
How does TLS session resumption work?
Session resumption avoids a full handshake on repeat connections. Current deployments normally use TLS session tickets, especially with TLS 1.3. Stunnel also has an internal session cache for session-ID-based resumption and can use sessiond for legacy clustered deployments.
Relevant options include sessionResume, sessionCacheSize, and sessionCacheTimeout. Keep the defaults unless measurements or cluster design justify a change. See sessiond before deploying the external cache.
How do I list available ciphers and curves?
The effective choices depend on both stunnel and the linked OpenSSL library:
stunnel -version
openssl ciphers -v
openssl ecparam -list_curves
TLS 1.3 ciphersuites may need a separate OpenSSL query depending on the OpenSSL release. The defaults printed by stunnel -version are the most useful starting point.
How can I delay DNS lookups until connection time?
Use:
delay = yes
This is useful for dynamic DNS or systems where DNS is unavailable during startup. Stunnel also engages delayed resolution automatically when a connect target cannot be resolved at startup. Delayed resolution implies priority failover.
Which ports should I use?
Use the port assigned to the application protocol when one exists, or a locally approved unassigned port for private deployments. Consult the current IANA Service Name and Transport Protocol Port Number Registry.
A registered port does not guarantee that a particular application uses implicit TLS, STARTTLS, TCP, or UDP. Confirm the protocol expected by both peers.
Where can I find the authoritative option syntax?
Use the documentation installed with the same build:
man stunnel
stunnel -help
stunnel -version
stunnel -options
stunnel -sockets
The manual reflects build-dependent features and should take precedence over examples written for older stunnel or OpenSSL releases.


