Decoding Nginx SSL Cipher String Syntax: A Comprehensive Guide for Secure Configuration


2 views

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';