Troubleshooting “SSL read failed” Errors in ApacheBench (ab) HTTPS Load Testing


3 views

During HTTPS load testing with ApacheBench (ab) on macOS Lion (10.7.2), I encountered intermittent "SSL read failed - closing connection" errors while running:


ab -c 100 -n 1000 https://mywebsite.com

Interestingly, the same test worked flawlessly on a colleague's non-Lion macOS machine. The NGINX server logs showed successful requests but didn't capture the failed attempts.

This behavior typically stems from one of three scenarios:

  1. Outdated SSL/TLS implementation in older macOS versions
  2. Connection throttling at the OS level (especially on laptops)
  3. SNI (Server Name Indication) negotiation issues

First, verify your OpenSSL version:


openssl version

Then test the SSL handshake directly:


openssl s_client -connect mywebsite.com:443 -servername mywebsite.com

Option 1: Upgrade your testing tools


# For Homebrew users:
brew upgrade ab
brew install curl --with-openssl

Option 2: Use Docker for consistent testing


docker run --rm jordi/ab \
  ab -c 100 -n 1000 https://mywebsite.com

Option 3: Adjust system parameters


# Increase file descriptor limits
ulimit -n 10000

# Disable QoS on macOS
sudo sysctl -w net.inet.tcp.delayed_ack=0

When ab proves problematic, consider these alternatives:


# Using wrk
wrk -c100 -t4 -d60s https://mywebsite.com

# Using hey
hey -n 1000 -c 100 https://mywebsite.com

Add this to your NGINX configuration to debug SSL issues:


server {
    listen 443 ssl;
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers HIGH:!aNULL:!MD5;
    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 10m;
    error_log /var/log/nginx/ssl_errors.log debug;
}

When running ApacheBench (ab) tests against HTTPS endpoints, many developers encounter intermittent "SSL read failed - closing connection" errors. This manifests when executing commands like:

ab -c 100 -n 1000 https://example.com

The puzzling aspects are:

  • Errors occur inconsistently (some requests succeed)
  • Nginx/Apache logs don't show corresponding failed requests
  • Behavior varies across machines with similar configurations

After extensive testing, several potential culprits emerge:

1. OpenSSL version mismatches (particularly on macOS)
2. Incomplete TLS handshake due to timing issues
3. Server-side keepalive misconfigurations
4. Client-side TCP/IP stack quirks

First, verify your OpenSSL configuration:

openssl version
ab -V  # Check which SSL library ab is using

For deeper inspection, capture network traffic:

sudo tcpdump -i any -s 0 -w ab_ssl.pcap port 443

Solution 1: Force TLS 1.2

ab -c 100 -n 1000 -Z ECDHE-RSA-AES256-GCM-SHA384 https://example.com

Solution 2: Disable SSL compression

ab -c 100 -n 1000 -X "" https://example.com

Solution 3: Adjust concurrency settings

# Try progressive concurrency tests
for i in 1 10 20 50 100; do
    ab -c $i -n 1000 -k https://example.com
done

For macOS users experiencing this exclusively:

# Reinstall ab with homebrew using modern OpenSSL
brew uninstall httperf &>/dev/null
brew install --with-openssl httperf

Alternatively, use Docker for consistent behavior:

docker run --rm jordi/ab \
    -c 100 -n 1000 https://example.com

Ensure your web server includes these directives:

# Nginx example
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:50m;
ssl_session_tickets off;
keepalive_timeout 75s;
keepalive_requests 1000;