# Fix Nginx Weak SSL Cipher Configuration Vulnerability
A security scan flags your Nginx server for using weak SSL ciphers. The report lists vulnerabilities like RC4, DES, and export-grade ciphers still being accepted. Your SSL Labs grade drops from A to C.
Identifying Weak Ciphers
Run a cipher scan against your server:
nmap --script ssl-enum-ciphers -p 443 example.comThe output shows every cipher your server accepts, graded by strength. Look for any cipher rated "weak" or "C":
| ssl-enum-ciphers:
| TLSv1.2:
| ciphers:
| TLS_RSA_WITH_RC4_128_SHA (rsa 2048) - C
| TLS_RSA_WITH_3DES_EDE_CBC_SHA (rsa 2048) - C
| TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (secp256r1) - ARemoving Weak Ciphers
Replace your ssl_ciphers directive with a strong, modern configuration:
ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305';
ssl_prefer_server_ciphers on;This configuration: - Uses only ECDHE key exchange (forward secrecy) - Uses only AES-GCM or ChaCha20-Poly1305 (authenticated encryption) - Excludes RSA key exchange (no forward secrecy) - Excludes CBC mode ciphers (vulnerable to padding oracle attacks) - Excludes RC4, DES, 3DES, and all export-grade ciphers
Disabling Legacy Protocols
Also ensure old protocols are disabled:
ssl_protocols TLSv1.2 TLSv1.3;Remove TLSv1 and TLSv1.1 entirely. TLS 1.0 and 1.1 have been deprecated by RFC 8996 and are considered insecure.
DH Parameter Strength
Generate a strong Diffie-Hellman parameter:
sudo openssl dhparam -out /etc/nginx/dhparam.pem 4096Then add to your Nginx configuration:
ssl_dhparam /etc/nginx/dhparam.pem;Without this, Nginx may use a weak 1024-bit DH parameter, which the security scanner will flag.
OCSP Stapling
Enable OCSP stapling to improve TLS handshake performance and privacy:
ssl_stapling on;
ssl_stapling_verify on;
ssl_trusted_certificate /etc/letsencrypt/live/example.com/chain.pem;
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 5s;OCSP stapling allows Nginx to provide the certificate revocation status directly during the handshake, avoiding a separate OCSP request to the CA.
Complete Production SSL Configuration
```nginx server { listen 443 ssl http2; server_name example.com;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305'; ssl_prefer_server_ciphers on; ssl_dhparam /etc/nginx/dhparam.pem;
ssl_session_cache shared:SSL:10m; ssl_session_timeout 1d; ssl_session_tickets off;
ssl_stapling on; ssl_stapling_verify on;
add_header Strict-Transport-Security "max-age=63072000" always; add_header X-Content-Type-Options nosniff always; add_header X-Frame-Options DENY always; } ```
The ssl_session_cache and ssl_session_tickets off ensure session resumption does not weaken forward secrecy. The Strict-Transport-Security header prevents protocol downgrade attacks.
Verifying the Fix
After reloading:
sudo nginx -t && sudo systemctl reload nginxTest with SSL Labs:
# Or use the command-line testssl.sh tool
./testssl.sh https://example.comYou should see an A or A+ grade, with no weak ciphers reported and TLS 1.0/1.1 rejected.