The ssl_ciphers HIGH:!aNULL:!MD5; directive in Nginx controls which cryptographic algorithms are permitted for TLS/SSL connections. Let's examine each component:
# Basic structure
ssl_ciphers [cipher_suite_specification];
The HIGH keyword represents a predefined group of ciphers considered secure by current standards. This includes:
- AES256-SHA256
- AES128-SHA256
- ECDHE-RSA-AES256-GCM-SHA384
- ECDHE-ECDSA-AES256-GCM-SHA384
The exclamation mark (!) indicates exclusion:
!aNULL - Disables anonymous Diffie-Hellman ciphers (security risk)
!MD5 - Bans ciphers using MD5 hashing (considered cryptographically weak)
While HIGH:!aNULL:!MD5 works, here's a more contemporary approach:
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';
Use OpenSSL to test your cipher suite:
openssl s_client -connect yourdomain.com:443 -cipher 'HIGH:!aNULL:!MD5'
Complete secure configuration example:
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
ssl_session_timeout 1d;
ssl_session_cache shared:MozSSL:10m;
ssl_session_tickets off;
ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384';
The ssl_ciphers directive in Nginx configuration is crucial for specifying the encryption algorithms used in TLS/SSL communication. It determines which cryptographic protocols are available for securing connections between clients and your server.
The configuration line:
ssl_ciphers HIGH:!aNULL:!MD5;
consists of several important components:
The HIGH profile includes ciphers that are considered strong and secure by current standards, typically those with key lengths of 128 bits or more. This includes:
- AES (128/256-bit) with SHA hash functions
- Camellia (128/256-bit)
- 3DES (though less recommended today)
The !aNULL and !MD5 components are exclusion modifiers:
!aNULLexplicitly disables cipher suites that provide no authentication!MD5removes cipher suites that use the MD5 hash algorithm, which is considered cryptographically broken
For better security in current environments, consider using:
ssl_ciphers 'TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256: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:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384';
To test your SSL configuration, you can use OpenSSL:
openssl ciphers -v 'HIGH:!aNULL:!MD5'
This will output the list of enabled ciphers according to your specification.
When selecting ciphers, consider:
- Modern CPUs handle AES-GCM efficiently
- ChaCha20-Poly1305 performs well on mobile devices
- ECDHE provides forward secrecy
Always:
- Disable SSLv2 and SSLv3 (
ssl_protocols TLSv1.2 TLSv1.3;) - Prioritize AEAD cipher suites
- Enable OCSP Stapling
- Use strong DH parameters
# Example complete SSL configuration
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_ecdh_curve secp384r1;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
ssl_session_tickets off;