Faire du https avec nginx

Posted on 2014-06-29 in Auto-hébergement Last modified on: 2015-09-23

Dans cet article, je ne vais pas du tout rentrer dans les détails de la cryptographie ou de SSL, TLS, https, … Je présente juste comment faire rapidement du https avec nginx. Si vous voulez plus d'informations (ce qui est une bonne idée), je vous invite à consulter le web.

Pour faire du https, nous avons besoin de certificats et de modifier la configuration du serveur web. Nous allons générer nos certificats. Ils seront auto-signés. Quand vous vous y connecterez, vous aurez donc un message d'erreur vous disant que la connection n'est pas de confiance (sauf si vous ajoutez manuellement le certificat à ceux de confiances au niveau système). Ce type de certificat est donc à réserver à son propre usage.

Générer les certificats

Préparation

Pour générer les certificats, nous avons besoin d'OpenSSL. Ce logiciel est présent dans toutes les distributions GNU/Linux dignes de ce nom. Installez le de la façon habituelle.

Nous allons placer les certificats dans un dossier dédié. Ce dossier contiendra 3 sous dossiers :

  • private pour les clés de notre CA (Certificate Authority)
  • certs pour les certificats
  • newcerts pour les nouveaux cerfiticats
  • crl pour le Ceritificate Revocation List (crl)

On ajoute les deux fichiers :

  • index.txt qui est utilisé par OpenSSL pour stocker les informations sur les certificats
  • serial qui contint le numéro des certificats crées. Il est automatiquement incrémenté.

Par exemple :

mkdir -p /root/certs/{private,certs,newcerts,crl}
cd /root/certs
touch index.txt
echo "01" > serial

Toutes les commandes seront à exécuter depuis ce dossier.

On crée le fichier de configuration d'OpenSSL afin de faciliter la génération des clés de la CA dans ca.cnf :

[ ca ]
default_ca      = CA_default            # The default ca section


[ CA_default ]

dir = . # Where everything is kept
certs = $dir/certs # Where the issued certs are kept
crl_dir = $dir/crl # Where the issued crl are kept
database = $dir/index.txt # database index file.
#unique_subject = no # Set to 'no' to allow creation of
# several ctificates with same subject.
new_certs_dir = $dir/newcerts # default place for new certs.

certificate = $dir/certs/ca.crt # The CA certificate
serial = $dir/serial # The current serial number
#crlnumber = $dir/crlnumber # the current crl number
# must be commented out to leave a V1 CRL
crl = $dir/crl.pem # The current CRL
private_key = $dir/private/ca.key # The private key
default_days = 365 # how long to certify for
default_crl_days= 365 # how long before next CRL
default_md = sha512 # use SHA-512 by default
x509_extensions = usr_cert


[ req ]
distinguished_name = req_distinguished_name


[ req_distinguished_name ]
countryName = Country Name (2 letter code)
countryName_default = FR
countryName_min = 2
countryName_max = 2

stateOrProvinceName = State or Province Name (full name)
stateOrProvinceName_default = PACA

localityName = Locality Name (eg, city)
localityName_default = MARSEILLE

0.organizationName = Organization Name (eg, company)
0.organizationName_default = jujens.eu

organizationalUnitName = Organizational Unit Name (eg, section)
#organizationalUnitName_default =

commonName = Common Name (eg, YOUR name)
commonName_max = 64

emailAddress = Email Address
emailAddress_max = 64
default_days = 365 # how long to certify for


[ policy_anything ]
countryName = optional
stateOrProvinceName = optional
localityName = optional
organizationName = optional
organizationalUnitName = optional
commonName = supplied
emailAddress = optional


[ usr_cert ]
basicConstraints = CA:TRUE
crlDistributionPoints = URI:http://dl.jujens.eu/jujens-eu.crl


[ v3_ca ]


# Extensions for a typical CA


# PKIX recommendation.

subjectKeyIdentifier=hash

authorityKeyIdentifier=keyid:always,issuer

# This is what PKIX recommends but some broken software chokes on critical
# extensions.
#basicConstraints = critical,CA:true
# So we do this instead.
basicConstraints = CA:true

# Key usage: this is typical for a CA certificate. However since it will
# prevent it being used as an test self-signed certificate it is best
# left out by default.
# keyUsage = cRLSign, keyCertSign

# Some might want this also
# nsCertType = sslCA, emailCA

# Include email address in subject alt name: another PKIX recommendation
# subjectAltName=email:copy
# Copy issuer details
# issuerAltName=issuer:copy

# DER hex encoding of an extension: beware experts only!
# obj=DER:02:03
# Where 'obj' is a standard or added object
# You can even override a supported extension:
# basicConstraints= critical, DER:30:03:01:01:FF

Note : le champ commonName de la section policy_anything est indispensable, il ne peut donc pas avoir la valeur optional. Vous pouvez rendre obligatoire n'importe quel autre champ à la création d'un certificat.

Création de l'autorité

Nous créons le certificat de l'autorité qui servira à signer les autres certificats et la clé associé. L'option -nodes permet de ne pas chiffrer la clé privée.

openssl req -new -x509 -extensions v3_ca -newkey rsa:4096 -keyout private/ca.key -out certs/ca.crt -config ca.conf -days 730

Generating a 4096 bit RSA private key
............................................................................................................................++
....................................................................................................................................................................................................................................................................................................................................................++
writing new private key to 'private/ca.key'
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [FR]:
State or Province Name (full name) [PACA]:
Locality Name (eg, city) [MARSEILLE]:
Organization Name (eg, company) [jujens.eu]:
Organizational Unit Name (eg, section) []:
Common Name (eg, YOUR name) []:jujens.eu
Email Address []:admin@jujens.eu
  1. req est la commande de génération de certificat
  2. -new pour créer un nouveau certificat
  3. -x509 pour créer un certificat auto signé ce qui permet de créer le certificat d'une CA (ou de faire un certificat de test).
  4. -extensions v3_ca pour utiliser l'extension CA.
  5. -newkey rsa:4096 pour générer une clé rsa de 4096 bits
  6. -keyout private/ca.key dans quel fichier écrire la clé
  7. -out certs/ca.crt dans quel fichier écrire le certificat
  8. -config ca.conf pour utiliser notre fichier de configuration

Ne perdez pas la passphrase (que vous pouvez choisir comme vous voulez).

L'option -pasout pass:x permet de ne pas avoir à entrer de passphrase, openssl va utiliser la passphrase passée en paramètre.

Générer le CSR (Certificate Signing Request)

Puisque le certificat va être utilisé par nginx, il ne faut pas qu'il soit protégé par une passphrase. On utilise presque la même commande que tout à l'heure.

openssl req -new -nodes -newkey rsa:4096 -keyout private/jujens-eu.key -out certs/jujens-eu.csr -config ca.conf -set_serial 10

Generating a 4096 bit RSA private key
.++
...............................................................................................++
writing new private key to 'private/jujens-eu.key'
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [FR]:
State or Province Name (full name) [PACA]:
Locality Name (eg, city) [MARSEILLE]:
Organization Name (eg, company) [jujens.eu]:
Organizational Unit Name (eg, section) []:
Common Name (eg, YOUR name) []:*.jujens.eu
Email Address []:admin@jujens.eu

Le champ Common Name doit correspondre au nom de domaine du serveur. Wildcard autorisé.

Retirer la passphrase de la clé

L'inconvénient que l'on a avec cette clé chiffrée avec une passphrase est qu'il faut entrer cette passphrase à chaque fois que l'on démarre le serveur. Ce qui n'est ni pratique ni forcément possible (reboot, crash, …). On peut retirer la passphrase de la clé. Cela peut présenter des risques de sécurité. Cette version de la clé ne doit donc être accessible qu'à l'utilisateur root.

[jenselme@fastolfe tmp]% cp server.key server.key.org

[jenselme@fastolfe tmp]% openssl rsa -in server.key.org -out server.key
Enter pass phrase for server.key.org:
writing RSA key

Vous pouvez également utiliser l'option -passin pass:x pour passer la clé à la commande.

Générer le certificat auto-signé

On génère enfin le certificat auto-signé.

openssl ca -extensions usr_cert -config ca.conf -policy policy_anything -out certs/jujens-eu.crt -infiles certs/jujens-eu.csr

Using configuration from ca.conf
Check that the request matches the signature
Signature ok
The Subject's Distinguished Name is as follows
countryName           :PRINTABLE:'FR'
stateOrProvinceName   :ASN.1 12:'PACA'
localityName          :ASN.1 12:'MARSEILLE'
organizationName      :ASN.1 12:'jujens.eu'
commonName            :ASN.1 12:'*.jujens.eu'
emailAddress          :IA5STRING:'admin@jujens.eu'
Certificate is to be certified until Aug 20 18:24:46 2016 GMT (365 days)
Sign the certificate? [y/n]:y


1 out of 1 certificate requests certified, commit? [y/n]y
Write out database with 1 new entries
Data Base Updated

Vous pouvez vérifier votre certificat avec : openssl x509 -noout -text -in server.crt.

Générer la liste de révocation de certificats (CRL)

Cette liste contient des informations sur quels certificats ont été révoqué. Certaines applications (comme les navigateurs web) vont périodiquement télécharger ce fichier pour savoir si un certificat est toujours valide. Si ce téléchargement échoue, le certificat sera considéré comme étant invalide.

La période au bout de laquelle la liste est téléchargée est définie par l'option default_crl_days de la section CA_default dans la configuration. L'adresse où le CRL est disponible est elle définie dans la section usr_cert avec la clé crlDistributionPoints.

Si vous ne voulez pas gérer ce paramètre, configurer simplement la durée du crl comme étant égale ou supérieure à la durée du certificat.

openssl ca -config ca.conf -gencrl -out crl/jujens-eu.crl

Configurer nginx

Pour rediriger le trafic vers https, on utilise une rewrite rule :

server {
       listen 80;
       server_name ttrss.jujens.eu;
       root /var/www/framanews;

       location / {
           rewrite ^ https://$server_name$request_uri? permanent;
       }
}

On ajoute ensuite une entrée serveur qui écoute sur le port 443 et on donne les chemins des certificats. Le reste est identique à la configuration http "standard".

server {
       listen 443 ssl;
       server_name ttrss.jujens.eu;
       root /var/www/framanews;
       index index.php;

       ssl_prefer_server_ciphers on;
       ssl_session_cache shared:SSL:10m;
       ssl_protocols TLSv1.2 TLSv1.1 TLSv1;
       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_certificate /root/certs/certs/jujens-eu.crt;
       ssl_certificate_key /root/certs/private/jujens-eu.key;

       location ~* \.php {
           try_files $uri =404;
           fastcgi_pass unix:/var/run/php5-fpm.sock;
           fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
           include fastcgi_params;
       }
}

L'option ssl_prefer_server_ciphers force l'utilisation d'un algorithme donné par le serveur (par défaut, c'est la préférence du client qui est importante).

Importer le certificat au niveau système

Linux

Récupérer le certificat de votre autorité (ca.crt) et lancer :

trust anchor Downloads/ca.crt
update-ca-trust

Windows

Exportez le certificat puis double cliquez sur celui-ci pour lancer la procédure d'installation. Laissez toutes les options avec les valeurs par défaut.