The cipher string in Nginx follows OpenSSL's cipher list format, which combines multiple cipher specifications with logical operators. The basic syntax consists of:
ssl_ciphers [CIPHER-SPEC]:[CIPHER-SPEC]:...;
The :
character acts as a separator between different cipher specifications, while !
serves as a negation operator:
ssl_ciphers HIGH:!aNULL:!eNULL;
In this example:
HIGH
is a cipher suite group!aNULL
excludes anonymous DH ciphers!eNULL
excludes NULL encryption ciphers
Nginx/OpenSSL supports several types of cipher specifications:
# Individual cipher names
ECDHE-RSA-AES256-GCM-SHA384
# Cipher groups
HIGH
MEDIUM
LOW
# Algorithm exclusions
!MD5
!DSS
Here's a modern, secure cipher configuration that prioritizes PFS (Perfect Forward Secrecy):
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:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384';
For compatibility with older clients while maintaining security:
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:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:!DSS';
- Hyphens (
-
) are part of cipher names, not operators - Groups like HIGH/MEDIUM/LOW are predefined OpenSSL cipher collections
- Order matters - the server attempts ciphers in left-to-right order
You can test your Nginx cipher configuration using OpenSSL:
openssl s_client -connect yourdomain.com:443 -cipher 'DEFAULT'
Or check all supported ciphers:
openssl ciphers -v 'HIGH:!aNULL:!eNULL'
The cipher string in nginx follows the OpenSSL cipher list format. Here's a breakdown of the syntax components:
ssl_ciphers HIGH:!aNULL:!eNULL:!MD5;
Colon (:) as separator: Acts as delimiter between cipher specifications. The example shows three distinct components: "HIGH", "!aNULL", and "!eNULL".
Exclamation mark (!) as negation: When prefixed to a cipher suite, it explicitly excludes that cipher. For example, "!MD5" prohibits all ciphers using MD5 hashing.
nginx/OpenSSL supports predefined cipher groups:
# Common groups
ALL # All ciphers (insecure)
DEFAULT # Default cipher list
HIGH # High strength ciphers
MEDIUM # Medium strength ciphers
LOW # Low strength ciphers
Individual cipher names follow the standard OpenSSL format:
ECDHE-RSA-AES256-GCM-SHA384
AES128-SHA
ECDHE-ECDSA-CHACHA20-POLY1305
Modern secure configuration (TLS 1.2+):
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';
Compatibility-focused configuration:
ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:
ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:
ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:
ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256';
Use OpenSSL to test your cipher suite:
openssl ciphers -v 'HIGH:!aNULL:!eNULL:!MD5'
- Always prefer ECDHE ciphers for forward secrecy
- Disable weak ciphers (!aNULL, !eNULL, !EXPORT, !DES, !RC4, !MD5, !PSK)
- Group ciphers by strength using the '+' operator when needed
- Test your configuration with SSL labs tester
Avoid these mistakes in cipher configuration:
# Too permissive (security risk)
ssl_ciphers ALL:!aNULL;
# Too restrictive (compatibility issues)
ssl_ciphers 'ECDHE-RSA-AES256-GCM-SHA384';