HTTPS is of course one of the most basic cornerstones of a secure website, whether it handles user data or serves static content.
It doesn't matter how secure the site itself is if it lacks this basic component. Sure you prevent XSS and SQLi, but the world can see the password your user submits. Whatever selection and options they make, the resource they request (URI), and their session cookie are plain to see. Even if you're serving static content, someone may intercept the connection and manipulate your site (man in the middle), and the visitor would see the altered site. HTTPS ensures no one else sees what the user submits, no one else sees what the user looks at, and that the user receives the real website.
Of course, HTTPS doesn't protect users if the website is inherently vulnerable. SSL/TLS also isn't without faults that allows attackers to decrypt or redirect the traffic. Despite it's shortcomings, it's far better than nothing.
It's easy to get started with Let's Encrypt, which provides free certificates. Below shows you how to set it up.
Download the Let's Encrypt official client, certbot, from its git repository.
sudo git clone https://github.com/certbot/certbot.git /opt/certbot
cd /opt/certbot
One of the methods Let's Encrypt confirms domain ownership is via a challenge, basically a file with a long random name. It's placed in your website's root directory and Let's Encrypt attempts to access it via $HOSTNAME.com/challenge and verify your ownership of $HOSTNAME. Launch the client and obtain a certificate using this method.
sudo ./certbot-auto certonly --webroot -w /var/www/$YOUR_DIR/ -d $HOSTNAME.com -d www.$HOSTNAME.com
certonly
: obtain certificate and set up yourself-a
: authenticator name, specify how to verify ownership of server--webroot
: verify by creating challenge in root dir of web server-w
: webroot path, where root dir of web server is located-d
: domain, domain names to assign cert toAdd other roots and subdomains as necessary using -w
and -d
.
Certbot will go through the set up process automatically and you'll receive a new certificate. For the first time, some information will be prompted such as email address.
To view active certificates, tree
the cert directory.
tree /etc/letsencrypt/live/
A Diffie-Hellman group also needs to get generated.
sudo openssl dhparam -out /etc/ssl/certs/dhparam.pem 2048
Change the SSL settings in Nginx's config file at /etc/nginx/nginx.conf
.
ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # Dropping SSLv3, ref: POODLE
ssl_prefer_server_ciphers on;
Change the server block in /etc/nginx/sites-enabled/
to use SSL/TLS. The below example uses relatively strong settings.
listen 443 ssl default_server;
# SSL/TLS stuff
ssl_certificate /etc/letsencrypt/live/$HOSTNAME.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/$HOSTNAME.com/privkey.pem;
ssl_trusted_certificate /etc/letsencrypt/live/$HOSTNAME.com/fullchain.pem;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_dhparam /etc/ssl/certs/dhparam.pem;
ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH";
ssl_session_timeout 1d;
ssl_ecdh_curve secp384r1;
ssl_session_cache shared:SSL:50m;
ssl_session_tickets off;
ssl_stapling on;
ssl_stapling_verify on;
add_header Strict-Transport-Security "max-age=63072000; includeSubdomains; preload";
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;
Create an additional server block to redirect regular HTTP requests to HTTPS.
server {
listen 80;
server_name $HOSTNAME.com www.$HOSTNAME.com;
return 301 https://$host$request_uri;
}
The assigned certificate will inevitably expire. Note that Let's Encrypt will remind you via email if it's expiring soon. Certbot can easily renew certs.
cd /opt/certbot
sudo ./certbot-auto renew --force-renewal --pre-hook "service nginx stop" --post-hook "service nginx start"
renew
: perform renewal operation--force-renewal
: renew regardless of expiry, otherwise renewals only happen if within 30 days from expiration--pre-hook
: perform operation before renewal--post-hook
: perform operation after renewal