Setting up an A+-grade nginx SSL server
(Updated: )
Because I don’t want to expose smarthome dashboards (like domoticz or grafana) directly to the internet, I’ve set up a separate server to publish data beyond my local network. For this I’ve chosen nginx (nginx.org) using let’s encrypt certificates (letsencrypt.org) renewed by certbot (eff.org), enabling hsts (nginx.com) and fixing the logjam vulnerability (weakdh.org).
Rationale ¶
Integrating a web server in a smarthome dashboard violates the Unix philosophy (wikipedia.org) of doing one thing only and doing it well. It’s unclear which web server domoticz/grafana uses, and why it’s integrated in their codebase. If it’s a custom web server, the chances that security is properly implemented is small. Additionally, setting up a separate web server allows me to choose what content I do and don’t want to serve.
The reason I’ve chosen for nginx is that it’s widely used (netcraft.com) (and thus hopefully well-tested) and faster (wikipedia.org) than apache.
Setting up nginx ¶
Install ¶
Install the server as usual
sudo apt install nginx
Enable HTTPS in sites-enabled/default
and nginx.conf
- no need to make certificates yet.
Get SSL certificate ¶
Get certbot-auto (eff.org) to automatically deploy certificates:
sudo /path/to/certbot-auto —nginx
First dry-run a renew
sudo /path/to/certbot-auto renew --dry-run
then add to crontab, using random delay to load balance for let’s encrypt (eff.org)
0 0,12 * * * python -c 'import random; import time; time.sleep(random.random() * 3600)' && /path/to/certbot/certbot-auto renew
Harden security ¶
Now enable HSTS (wikipedia.org) to prevent MITM sslstrip attacks (stackexchange.com). Add the following to your sites-enabled/default config (source (nginx.com)):
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
By default, nginx https is pretty secure, fixing many known vulnerabilities. The logjam attack (weakdh.org) however, is not mitigated. To fix, follow these instructions (weakdh.org):
sudo su
cd /etc/ssl/private
openssl dhparam -out dhparams.pem 2048
in sites-enabled/default, add:
ssl_dhparam "/etc/ssl/private/dhparams.pem"
Redirect HTTP to HTTPS ¶
To limit HTTP exposure to the web, one can redirect all HTTP traffic to HTTPS. However, since certbot only works over HTTP, an exception has to be made to have certificate renewal working.
I’ve followed these instructions here (letsencrypt.org) and here (letsencrypt.org) to implement this.
There are three ways certbot can renew certificates, unfortunately none allowing a HTTPS-only server (letsencrypt.org).
- HTTP-01: Store a token on your webserver that is retrieved over HTTP
- DNS-01: Store a token in your DNS records
- TLS-SNI-01: Change the SSL certificate on the server - this method is deprecated
Verify setup ¶
Finally, test your configuration (ssllabs.com) which should give you an A+ grade: