My blog (and pretty much every other site I host) is using Let’s Encrypt certificates in order to be served over https. Using any certificate at all is generally an upgrade when it comes to security, but your webserver’s configuration needs to be up to standard as well. Unlike the Let’s Encrypt certificates, keeping the configs up to date requires manual intervention, and is therefore something I don’t do often.
This week I decided I should check up on the state of my SSL configuration in nginx. I usually check this through SSL Lab’s SSL Server Test. This is basically testssl.sh in a shiny web frontend, and assigns you a score. I aim to always have A or higher, but it seemed my old settings were capped at a B. This was due to the cipher list allowing ciphers which are nowadays considered insecure.
While I could’ve just updated the cipher list, I decided to check up on all the other settings as well. There’s a GitHub gist which shows you what settings to use with nginx to make it secure by modern standards, which I’ve used to check if I should update some of my own settings.
My old settings looked as follows. Please don’t be too scared of the giant list
# DHparams ssl_dhparam /etc/nginx/dhparam.pem; # SSL settings ssl_ciphers 'ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS'; ssl_prefer_server_ciphers off; ssl_protocols TLSv1.2 TLSv1.3; ssl_session_cache shared:le_nginx_SSL:10m; ssl_session_tickets off; ssl_session_timeout 1440m; # Additional headers add_header Strict-Transport-Security "max-age=63072000" always;
With the new settings, I’ve added
friend on IRC pointed out I should enable
ssl_prefer_server_ciphers, so this
has been enabled too.
But most notably, the list of
ssl_ciphers has been dramatically reduced. I
still allow TLSv1.2 in order to allow slightly older clients to connect without
any issues, but the ciphers considered WEAK have been disabled explicitly.
This leaves a total of 5 ciphers to use, all of them using ECDHE, so the
ssl_dhparam could be dropped as well.
Lastly, I’ve added a couple headers for security reasons, as recommended by securityheaders.com.
# SSL settings ssl_protocols TLSv1.3 TLSv1.2; ssl_buffer_size 4K; ssl_ecdh_curve secp521r1:secp384r1; ssl_prefer_server_ciphers on; ssl_session_cache shared:le_nginx_SSL:2m; ssl_session_tickets off; ssl_session_timeout 1440m; ssl_ciphers 'EECDH+AESGCM:EECDH+AES256:!ECDHE-RSA-AES256-SHA384:!ECDHE-RSA-AES256-SHA'; # Additional headers add_header Content-Security-Policy "default-src 'self'" always; add_header Referrer-Policy "strict-origin-when-cross-origin" always; add_header Strict-Transport-Security "max-age=63072000" always; add_header X-Content-Type-Options "nosniff" always; add_header X-Frame-Options "SAMEORIGIN" always;
ssl_ciphersto be formatted in a more clean way, which I’ve tried to do with a variable through
set, but it appears variables are not expanded within
ssl_ciphers. If you have any methods to format the list of ciphers used in a cleaner way, I’d be very happy to know!
This configuration is saved as a small snippet which I
include in all other
site configurations, so it is updated everywhere at once as well. Now I should
be able to neglect this for another year or two again.