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:
- Outdated SSL/TLS implementation in older macOS versions
- Connection throttling at the OS level (especially on laptops)
- 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;