I was usually copy ssl_ciphers
values from somewhere on Internet and paste it on my Nginx config when deploying SSL certificate.
After some experiment with those ssl_ciphers
, now I note it based on certificate type, TLS version,
and make sure every cipher is explicitly defined (handpicked, not just blindly using group and not knowing what’s inside).
RSA Certificate
Most common certificate type, all CA provide RSA certificate, with recommended size 2048-bit to 4096-bit.
TLSv1.2 ONLY
### /etc/nginx/snippets/tls12-rsa.conf
ssl on;
ssl_protocols TLSv1.2;
ssl_ciphers ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256;
ssl_ecdh_curve prime256v1;
ssl_prefer_server_ciphers on;
ssl_buffer_size 4k;
ssl_session_timeout 1h;
ssl_session_cache shared:SSL:64m;
ssl_session_tickets off;
Nginx >=1.13 build with OpenSSL 1.1.0:
ssl_ciphers ECDHE-RSA-CHACHA20-POLY1305:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256;
ssl_ecdh_curve X25519:prime256v1;
AES128 ciphers only:
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-SHA256;
TLSv1.2, TLSv1.1, TLSv1.0
### /etc/nginx/snippets/tlsall-rsa.conf
ssl on;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA;
ssl_dhparam /etc/ssl/dhparam.pem; # openssl dhparam -dsaparam -out /etc/ssl/dhparam.pem 4096
ssl_ecdh_curve prime256v1;
ssl_prefer_server_ciphers on;
ssl_buffer_size 4k;
ssl_session_timeout 1h;
ssl_session_cache shared:SSL:64m;
ssl_session_tickets off;
Nginx >=1.13 build with OpenSSL 1.1.0:
ssl_ciphers ECDHE-RSA-CHACHA20-POLY1305:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA;
ssl_ecdh_curve X25519:prime256v1;
AES128 ciphers only:
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:DHE-RSA-AES128-SHA;
ECC Certificate
Newer certificate type, not all CA provide ECC certificate, and only have compatilibity with modern client. ECC key have same strength with larger RSA key. For example, 256-bit ECC key equivalent to 3072-bit RSA key, and 384-bit ECC key equivalent to 7680-bit RSA key.
TLSv1.2 ONLY
### /etc/nginx/snippets/tls12-ecc.conf
ssl on;
ssl_protocols TLSv1.2;
ssl_ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256;
ssl_ecdh_curve prime256v1;
ssl_prefer_server_ciphers on;
ssl_buffer_size 4k;
ssl_session_timeout 1h;
ssl_session_cache shared:SSL:64m;
ssl_session_tickets off;
Nginx >=1.13 build with OpenSSL 1.1.0:
ssl_ciphers ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256;
ssl_ecdh_curve X25519:prime256v1;
AES128 ciphers only:
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-SHA256;
TLSv1.2, TLSv1.1, TLSv1.0
### /etc/nginx/snippets/tlsall-ecc.conf
ssl on;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-ECDSA-AES256-SHA:ECDHE-ECDSA-AES128-SHA:DHE-ECDSA-AES256-SHA:DHE-ECDSA-AES128-SHA;
ssl_dhparam /etc/ssl/dhparam.pem; # openssl dhparam -dsaparam -out /etc/ssl/dhparam.pem 4096
ssl_ecdh_curve prime256v1;
ssl_prefer_server_ciphers on;
ssl_buffer_size 4k;
ssl_session_timeout 1h;
ssl_session_cache shared:SSL:64m;
ssl_session_tickets off;
Nginx >=1.13 build with OpenSSL 1.1.0:
ssl_ciphers ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-ECDSA-AES256-SHA:ECDHE-ECDSA-AES128-SHA:DHE-ECDSA-AES256-SHA:DHE-ECDSA-AES128-SHA;
ssl_ecdh_curve X25519:prime256v1;
AES128 ciphers only:
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:DHE-ECDSA-AES128-SHA;
Dual Certificate
If you have ECC and RSA certificate, on Nginx >= 1.13 you can use dual setup for ssl, for example:
### /etc/nginx/snippets/tlsall-dual.conf
ssl on;
ssl_protocols TLSv1.2;
ssl_ciphers ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256;
For certificate path, use it as following:
### /etc/nginx/snippets/yourdomain.com.cert.conf
# ECDSA
ssl_certificate /etc/ssl/acme/yourdomain.com.ec256.full.pem;
ssl_certificate_key /etc/ssl/acme/yourdomain.com.ec256.key.pem;
# RSA
ssl_certificate /etc/ssl/acme/yourdomain.com.rsa2048.full.pem;
ssl_certificate_key /etc/ssl/acme/yourdomain.com.rsa2048.key.pem;
# TRUSTED CA FOR OCSP
ssl_trusted_certificate /etc/ssl/acme/yourdomain.com.trusted_ca.pem;
# OCSP
ssl_stapling on;
ssl_stapling_verify on;
resolver 1.1.1.1 1.0.0.1 valid=300s;
resolver_timeout 5s;
Testing
When we are done with SSL/TLS setup, we can test using following service/tools:
- SSL Server Test (web) (if you get A and want to get A+, set HSTS header to 1 year)
- testssl.sh (CLI)
- sslscan (CLI)
To get info about cipher we use, we can use openssl ciphers -V [CIPHER]
, for example:
# by group
$ openssl ciphers -V CHACHA20
0xCC,0xA9 - ECDHE-ECDSA-CHACHA20-POLY1305 TLSv1.2 Kx=ECDH Au=ECDSA Enc=CHACHA20/POLY1305(256) Mac=AEAD
0xCC,0xA8 - ECDHE-RSA-CHACHA20-POLY1305 TLSv1.2 Kx=ECDH Au=RSA Enc=CHACHA20/POLY1305(256) Mac=AEAD
0xCC,0xAA - DHE-RSA-CHACHA20-POLY1305 TLSv1.2 Kx=DH Au=RSA Enc=CHACHA20/POLY1305(256) Mac=AEAD
0xCC,0xAE - RSA-PSK-CHACHA20-POLY1305 TLSv1.2 Kx=RSAPSK Au=RSA Enc=CHACHA20/POLY1305(256) Mac=AEAD
0xCC,0xAD - DHE-PSK-CHACHA20-POLY1305 TLSv1.2 Kx=DHEPSK Au=PSK Enc=CHACHA20/POLY1305(256) Mac=AEAD
0xCC,0xAC - ECDHE-PSK-CHACHA20-POLY1305 TLSv1.2 Kx=ECDHEPSK Au=PSK Enc=CHACHA20/POLY1305(256) Mac=AEAD
0xCC,0xAB - PSK-CHACHA20-POLY1305 TLSv1.2 Kx=PSK Au=PSK Enc=CHACHA20/POLY1305(256) Mac=AEAD
# by name/namelist
$ openssl ciphers -V ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-SHA256
0xC0,0x2B - ECDHE-ECDSA-AES128-GCM-SHA256 TLSv1.2 Kx=ECDH Au=ECDSA Enc=AESGCM(128) Mac=AEAD
0xC0,0x23 - ECDHE-ECDSA-AES128-SHA256 TLSv1.2 Kx=ECDH Au=ECDSA Enc=AES(128) Mac=SHA256
Conclusion
Choosing what SSL ciphers we want to use, here is some of consideration:
-
Security
Encryption using AES256(/GCM) or AES128(/GCM) is sufficient, or maybe CHACHA20/POLY1305. Cipher ordering is important.
-
Compatibility
TLSv1.2 for modern client only, or need to support all TLS version and wider compatibility including old android, Java and IE.
For infrastructure perspective, TLS for data transit is only one of many aspect for our application security. We may need Web Application Firewall if we require more strict security. It’s all depends on what is your requirements.