Le projet Let's Encrypt propose de fournir gratuitement des certificats TLS valident pour sécuriser les échanges HTTP. Un script python est disponible pour automatiser la génération et la signature des certificats.
Par défaut ce script nécessite les droits root
(via sudo
) car il écrit dans /etc
et modifie la configuration du serveur web. Je n'aime pas trop voir ce genre de script s'exécuter avec des droits importants sur la machine.
Il est possible d'utiliser le script et d'automatiser l'ensemble avec des droits « utilisateur » simples. C'est ce fonctionnement qui est décrit ici.
Oui, Let's Encrypt nécessite un serveur HTTP, sans « S », mais ce n'est pas un problème. On va créer un virtual host HTTP par défaut. Ce virtual host sera utilisé pour la vérification demandée par « let's encrypt ». Pour toutes les autres requêtes, Nginx fera une redirection vers la page équivalente en HTTPS.
La configuration du vhost :
server { listen 80 default_server; listen [::]:80 default_server; access_log /var/log/nginx/default/access.log; error_log /var/log/nginx/default/error.log; # let's encrypt location ~ /.well-known/acme-challenge/.* { default_type application/jose+json; root /srv/www/default; } # redirection vers HTTPS pour tout le reste location / { rewrite ^ https://$host$request_uri? permanent; } }
Pour la suite, on peut créer un utilisateur dédié à letsencrypt.
Ce script va télécharger les sources du logiciel publié par let's encrypt dans le répertoire de l'utilisateur et créer l’environnement Python nécessaire.
L'exécution nécessite les paquets gcc python-dev libffi-dev libssl-dev
.
#!/bin/bash cd $HOME virtualenv --no-site-packages --python python2.7 ~/.local/share/letsencrypt cd .local/share/letsencrypt bin/pip install -U setuptools bin/pip install -U pip bin/pip install -U letsencrypt
Ce script permet d'automatiser la demande de certificat. Il faut lui donner en argument une liste de domaines séparés par des espaces. La validation des domaines par let's encrypt sera prise en charge par le vhost par défaut Nginx en HTTP. Il faut que l'utilisateur qui lance ce script puisse écrire dans le répertoire /srv/www/default/.well-known/
#!/bin/bash domains="" my_mail='postmaster@mondomaine.ui' for domain in "$@" do domains="$domains --domains $domain" done $HOME/.local/share/letsencrypt/bin/letsencrypt \ certonly \ --work-dir $HOME \ --config-dir $HOME/etc \ --logs-dir $HOME/logs \ --authenticator webroot \ --rsa-key-size 4096 \ --webroot-path /srv/www/default \ --server https://acme-v01.api.letsencrypt.org/directory \ --email $my_mail \ --agree-tos \ --renew-by-default \ $domains
Pour chaque domaine, on pourra créer un virtual host accessible en HTTPS. Le script ci-dessous permet de créer un virtual host pour nginx. Il faudra lui passer le nom de domaine en paramètre.
#!/bin/bash cat <<EOF | sudo tee /etc/nginx/sites-available/$1.conf server { listen 443 ssl; listen [::]:443 ssl; server_name $1; root /var/www/html; access_log /var/log/nginx/$1/access.log; error_log /var/log/nginx/$1/error.log debug; keepalive_requests 10; keepalive_timeout 60 60; ssl_certificate /home/letsencrypt/etc/live/$1/fullchain.pem.; ssl_certificate_key /home/letsencrypt/etc/live/$1/privkey.pem; # TLS config # Source https://gist.github.com/gokejnr/a4f9cc2a164a7f928048 ## Send header to tell the browser to prefer https to http traffic add_header Strict-Transport-Security max-age=31536000; # Do not allow this site to be displayed in iframes add_header X-Frame-Options DENY; # Do not permit Content-Type sniffing. add_header X-Content-Type-Options nosniff; ## Use TLS instead of SSL - Compatibility issues with some Java clients ## and older versions of of IE, however, more secure. ssl_protocols TLSv1.2 TLSv1.1 TLSv1; ## Use more secure and less CPU tasking ciphers compared to nginx defaults #ssl_ciphers ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+3DES:!aNULL:!MD5:!DSS; ssl_ciphers AES256+EECDH:AES256+EDH:!aNULL; ## Improves TTFB by using a smaller SSL buffer than the nginx default ssl_buffer_size 8k; ## Specifies that server ciphers should be preferred over client ciphers ssl_prefer_server_ciphers on; ## Enables all nginx worker processes share SSL session information #ssl_session_cache shared:SSL:30m; ## Increases the amount of time SSL session information in the cache is valid ssl_session_timeout 30m; ## Specifies a file with DH parameters for EDH ciphers ## Run "openssl dhparam -out /path/to/ssl/dhparam.pem 2048" in ## terminal to generate it ssl_dhparam dh4096.pem; ## OCSP stapling ssl_stapling on; ssl_stapling_verify on; resolver 213.186.33.99; resolver_timeout 10s; ################################################################################### } # vim: ts=2 sw=2 sts=2 sr noet EOF sudo ln -s /etc/nginx/sites-available/$1.conf /etc/nginx/sites-enabled sudo mkdir /var/log/nginx/$1 # vim: ts=2 sw=2 sts=2 sr noet
Cette configuration devrait permettre d'obtenir un A+ au test Qualys qui permet d'évaluer le niveau de sécurité d'un serveur TLS.