How to Disable TLS 1.0 in NGINX for PCI DSS Compliance: A Step-by-Step Guide


2 views

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:

  1. Test with OpenSSL:
    openssl s_client -connect example.com:443 -tls1
    

    Should return an error

  2. Check with nmap:
    nmap --script ssl-enum-ciphers -p 443 example.com
    
  3. 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