Troubleshooting SSLv3 Handshake Failures in Stunnel: Root Causes and Modern TLS Configuration


2 views

When implementing Stunnel as an SSL termination proxy, many administrators encounter cryptic SSLv3-related errors like:

SSL_accept: 1408F10B: error:1408F10B:SSL routines:SSL3_GET_RECORD:wrong version number
OpenSSL: error:14094410:SSL routines:SSL3_READ_BYTES:sslv3 alert handshake failure

These errors typically surface when clients attempt SSLv3 connections while the server expects more modern protocols. The inconsistency across different client systems (CentOS vs Ubuntu in your case) stems from varying default SSL/TLS configurations in different Linux distributions.

The POODLE vulnerability (CVE-2014-3566) rendered SSLv3 insecure back in 2014. Modern security best practices dictate:

  • SSLv3 should be disabled in all production environments
  • TLS 1.2 should be the minimum supported protocol
  • TLS 1.3 should be enabled where available

Your openssl s_client test reveals the core problem:

$ openssl s_client -connect example.com:443 -ssl3
CONNECTED(00000004)
3897:error:14094410:SSL routines:SSL3_READ_BYTES:sslv3 alert handshake failure:s3_pkt.c:1086:SSL alert number 40
3897:error:1409E0E5:SSL routines:SSL3_WRITE_BYTES:ssl handshake failure:s3_pkt.c:530:

The successful -tls1 test confirms the server properly supports TLS 1.0+, while rejecting the obsolete SSLv3 protocol.

Here's an improved configuration that enforces modern security standards:

pid = /etc/stunnel/stunnel.pid
debug = 3
output = /etc/stunnel/stunnel.log

socket = l:TCP_NODELAY=1
socket = r:TCP_NODELAY=1

; Security enhancements
sslVersionMin = TLSv1.2
sslVersionMax = TLSv1.3
options = NO_SSLv2
options = NO_SSLv3
options = NO_TLSv1
options = NO_TLSv1.1
options = CIPHER_SERVER_PREFERENCE
options = PREFER_SERVER_CIPHERS
options = DONT_INSERT_EMPTY_FRAGMENTS

[https]
accept = 12.34.56.78:443
connect = 127.0.0.1:80
TIMEOUTclose = 0
xforwardedfor = yes
CAfile = /path/to/ssl/example.com.cabundle
cert = /path/to/ssl/example.com.crt
key = /path/to/ssl/example.com.key

; Modern cipher suite
ciphers = ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305

For legacy clients that must connect, consider these approaches:

# Force TLS 1.2 with wget
wget --secure-protocol=TLSv1_2 https://example.com

# With curl
curl --tlsv1.2 https://example.com

# For OpenSSL clients
openssl s_client -connect example.com:443 -tls1_2

After reconfiguration, verify your setup with:

stunnel -version  # Check compiled OpenSSL version
openssl ciphers -v | grep TLSv1.2  # Verify supported ciphers
nmap --script ssl-enum-ciphers -p 443 example.com  # Remote verification

The solution ensures robust security while maintaining compatibility with modern clients. Any remaining SSLv3 connection attempts should be treated as configuration errors requiring client updates rather than server-side accommodations.


When working with Stunnel as an SSL proxy, you might encounter these specific OpenSSL errors:

SSL_accept: 1408F10B: error:1408F10B:SSL routines:SSL3_GET_RECORD:wrong version number
OpenSSL: error:14094410:SSL routines:SSL3_READ_BYTES:sslv3 alert handshake failure

These errors typically occur when there's a protocol version mismatch between the client and server during SSL/TLS negotiation.

The fundamental issue stems from attempting to use the obsolete SSLv3 protocol with modern security requirements. Your OpenSSL version (0.9.8e-fips-rhel5) and Stunnel version (4.32) combination reveals several important points:

  • SSLv3 is vulnerable to POODLE attacks and should be disabled
  • Modern clients increasingly reject SSLv3 connections
  • The protocol negotiation fails when clients expect newer TLS versions

Your current Stunnel configuration lacks specific protocol restrictions:

[https]
accept=12.34.56.78:443
connect=127.0.0.1:80
TIMEOUTclose=0
xforwardedfor=yes
CAfile = /path/to/ssl/example.com.cabundle
cert=/path/to/ssl/example.com.crt
key=/path/to/ssl/example.com.key

This allows clients to negotiate any SSL/TLS version, leading to potential incompatibilities.

Here's the improved configuration that enforces modern security standards:

pid = /etc/stunnel/stunnel.pid
debug = 3
output = /etc/stunnel/stunnel.log
socket=l:TCP_NODELAY=1
socket=r:TCP_NODELAY=1
verify=3
fips=no

[https]
accept=12.34.56.78:443
connect=127.0.0.1:80
TIMEOUTclose=0
xforwardedfor=yes
CAfile = /path/to/ssl/example.com.cabundle
cert=/path/to/ssl/example.com.crt
key=/path/to/ssl/example.com.key

; Enforce modern TLS protocols only
sslVersion = TLSv1.2
options = NO_SSLv3
options = NO_TLSv1
options = NO_TLSv1.1
ciphers = HIGH:!aNULL:!MD5

After making changes, verify the configuration with these commands:

# Test SSLv3 (should fail)
openssl s_client -connect example.com:443 -ssl3

# Test TLS 1.2 (should succeed)
openssl s_client -connect example.com:443 -tls1_2

For comprehensive testing, consider using testssl.sh or online SSL checkers to validate your server's protocol support.

If you must support older clients:

  • Create separate service entries in stunnel.conf for different protocol requirements
  • Consider upgrading OpenSSL to a newer version for better protocol support
  • Monitor your logs for connection attempts that fail due to protocol restrictions