Many administrators face this frustrating scenario: you've explicitly configured NGINX to disable TLS 1.0 in both your global nginx.conf
and server blocks, yet scans still show it as enabled. Here's what your configuration might look like:
# In nginx.conf (http context)
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
# In your server block
ssl_protocols TLSv1.1 TLSv1.2;
Yet when testing with OpenSSL:
openssl s_client -connect www.example.com:443 -tls1
The connection still succeeds, potentially failing PCI DSS compliance scans.
Several factors could be at play:
- Configuration inheritance: NGINX merges configurations in complex ways
- OpenSSL version limitations: Older versions may behave differently
- Multiple server blocks: Another server block might be handling the request
Here's the definitive approach to ensure TLS 1.0 is disabled:
# In nginx.conf (http context)
ssl_protocols TLSv1.1 TLSv1.2;
# In EVERY server block that handles SSL
server {
listen 443 ssl;
server_name example.com;
# Explicitly disable TLS 1.0
ssl_protocols TLSv1.1 TLSv1.2;
# Recommended modern ciphers
ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256';
# Other security settings
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
ssl_session_tickets off;
}
After making changes:
- Test with OpenSSL:
openssl s_client -connect example.com:443 -tls1
Should return an error
- Check with nmap:
nmap --script ssl-enum-ciphers -p 443 example.com
- Verify with SSL Labs test
For maximum security:
- Upgrade to OpenSSL 1.1.1+ if possible
- Consider disabling TLS 1.1 as well
- Implement HSTS headers
- Rotate SSL certificates regularly
Remember to test thoroughly in staging before applying to production, as some legacy clients might still rely on older protocols.
server {
listen 443 ssl;
server_name example.com;
# SSL configurations
ssl_certificate /etc/nginx/ssl/example.com.crt;
ssl_certificate_key /etc/nginx/ssl/example.com.key;
# Disable TLS 1.0
ssl_protocols TLSv1.1 TLSv1.2;
# Recommended cipher suites
ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256';
ssl_prefer_server_ciphers on;
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:50m;
}
After implementing these changes, verify TLS 1.0 is disabled using OpenSSL:
openssl s_client -connect example.com:443 -tls1
You should receive an error like:
140735848642464:error:1409442E:SSL routines:ssl3_read_bytes:tlsv1 alert protocol version:s3_pkt.c:1493:SSL alert number 70
1. Multiple SSL configurations: Ensure you don't have conflicting ssl_protocols
directives in included files.
2. Old OpenSSL versions: Upgrade if using OpenSSL older than 1.0.1 (your 1.0.1f should work)
3. Configuration inheritance: Check for protocol settings in http {} block that might override server settings
For maximum security, consider:
ssl_protocols TLSv1.2;
ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384';
ssl_ecdh_curve secp384r1;
ssl_dhparam /etc/nginx/dhparam.pem;
Beyond OpenSSL, use these tools to verify:
- Qualys SSL Labs test
- testssl.sh
- PCI DSS ASV scans