ReLoad

Thierry Jaouen ~ WikiBlog
"Rien à foutre d'être lu, tant que je peux me relire."

Outils pour utilisateurs

Outils du site


blog:2016:01:27:nginx_et_ssl_client_certificate

Nginx et ssl_client_certificate

Mise en place d'une mini infrastructure NGINX avec SSL , avec des clés SSL signés pour les clients.

Il s'agit pas seulement de chiffrer la communication, mais aussi de refuser les clients qui n'utilisent pas une clé reconnue ou revokée par “notre” autorité.

préparation

# cd /etc/nginx/
# mkdir ssl
# chmod 0700 ssl
# cd ssl
# mkdir mon_site

Serveur

Générer la clé privée avec une pass-phrase…

# openssl genrsa -des3 -out server.key 2048

Virer la pass-phrase:

# cp server.key server.key.bak
# openssl rsa -in server.key.bak -out server.key

Générer un certificat:

# openssl req -new -sha256 -key server.key -out server.csr

Auto-signé le certificat:

# openssl x509 -req -days 3650 -sha256 -in server.csr -signkey server.key -out server.crt

Au final, on a ça d'interessant:

  • server.key
  • server.csr
  • server.crt

CA

Génération de la clé privée:

# openssl genrsa -out ca.key 2048

Génération de la clé publique de l'autorité:

# openssl req -new -sha256 -x509 -nodes -days 3650 -key ca.key -out ca.crt

Remplir les champs, particulièrement le “common name”.

Créer le fichier qui va attribuer un numéro unique pour chaque certificat:

# echo "00" > ca.srl

Pour cette étape, on a généré les fichiers:

  • ca.key
  • ca.crt
  • ca.srl

Clients

Création des clés d'un client:

# openssl req -newkey rsa:2048 -sha256 -nodes -keyout client1.key -out client1.csr

Signer les clés:

# openssl x509 -req -in client1.csr -days 3650 -CA ca.crt -CAkey ca.key -out client1.crt
  • client1.key
  • client1.csr
  • client1.crt

Pour les “serial”, on aurait pu utiliser “-set_serial” ou “-CAcreateserial”, mais on a préféré préparer un fichier “ca.srl” …

Clients : batch

Lors de la création des clés, on peut outre passer la phase de saisie en ajoutant l'option “-subj” suivit des informations qu'on aurait du saisir:

Donc, il suffit d'ajouter l'option “-batch” suivit de (par exemple):

-subj "/C=FR/ST=France/L=Paris/O=Eez.fr/OU=www/CN=client1/emailAddress=nospam-ca@eez.fr"

P12

Conversion en “.p12” avec un mot de passe:

# openssl pkcs12 -export -clcerts -in client1.crt -inkey client1.key -out client1.p12 -passout pass:<PASSWORD>

Remplacer “<PASSWORD>” par le mot de passe de votre choix.

Revokation

Créer le fichier de revokation

Source:

# cd /etc/nginx/ssl/mon_site

Faire une copie de la conf par défaut:

# cp /etc/ssl/openssl.cnf local-openssl.cnf

A apporter les modifications suivantes:

[ ca ]

#default_ca     = CA_default            # The default ca section
default_ca      = myca

[ myca ]
# copy complète de la section "CA_default"
# avec pour changement:

dir             = .

...

crl_extensions  = crl_ext

...

En clair:

  1. le répertoire de travail est le répertoire courant.
  2. on passe en crl V2 (source )

Si on a rien changé d'autres dans la conf par défaut, on peut préparer quelques fichiers comme cela:

# echo 00 > crlnumber
# touch index.txt
# mkdir crl

Générer le fichier des révokations, vide pour l'instant:

# openssl ca -config ./local-openssl.cnf -keyfile ca.key -cert ca.crt -gencrl -out crl/crl.pem

Revoker des clés

:!: Il s'agit de révoker la signature des clés: les clés pourront être re-signés.
# openssl ca -config ./local-openssl.cnf -keyfile ca.key -cert ca.crt -revoke client-client6.crt
Using configuration from ./local-openssl.cnf
Adding Entry with serial number 09 to DB for /C=FR/ST=France/L=Paris/O=Eez.fr/OU=www/CN=client6/emailAddress=ca@eez.fr
Revoking Certificate 09.
Data Base Updated

Après chaque serie de révokation, le fichier “index.txt” est modifié.

Mettre a jour la base de revokation (à partir du fichier “index.txt” sans doute):

# openssl ca -config ./local-openssl.cnf -gencrl -keyfile ca.key -cert ca.crt -out crl/crl.pem -crldays 7

Il faudra aussi relancer “nginx” pour qu'il prenne en charge le nouveau fichier de révokation.

:!: -crldays X permet de dire combien de temps ce fichier est valide !!! Passé cette date limite, “nginx” refuse tous les clients !

Donc: soit mettre un “crldays” très lointain, soit ré-générer le fichier régulièrement, avant l'expiration.

Dans tout les cas, il faudra faire: /etc/init.d/nginx reload.

:!: Le fichier “crl” a vocation a être publique… d'où la date de péremption avec “crldays”.

Tips

Examiner le contenu du fichier des revokations:

# openssl crl -in crl/crl.pem -noout -text

Vérifier si une signature est révoqué ou pas:

# openssl verify -CRLfile crl/crl.pem -CAfile ca.crt -crl_check client1.crt

Quand c'est révoké, on a:

...
error 23 at 0 depth lookup:certificate revoked

Sinon, pour non révoké, on a:

... : OK

Configurer Nginx avec SSL

SSL dans Nginx, pour faire court:

listen 0.0.0.0:443 ssl;

#ssl on;

# Les clés du serveur:

ssl_certificate       /etc/nginx/ssl/mon_site/server.crt;
ssl_certificate_key   /etc/nginx/ssl/mon_site/server.key;

# Le certificat de l'autorité qui vérifie les clients

ssl_client_certificate        /etc/nginx/ssl/mon_site/ca.crt;
ssl_verify_client    on;

# revokation:
ssl_crl               /etc/nginx/ssl/mon_site/crl/crl.pem;

Tips

ssl optional

Il y a des fois, on ne veut pas vérifier la clé de certains clients, parce qu'on estime qu'ils sont dans un réseau (local) de confiance…

Dans ce cas, on peut mettre en place des conditions du style:

  1. Si dans tel ou tel reseau: → ne pas vérifier le certificat et accepter le client.
  2. Sinon → suivre la procédure normale en validant le certificat du client.

Pour cela, voici les modifications a apporter dans la conf Nginx :

ssl_verify_client     optional;          # Au lieu de "on"

Dans la ou les sections “location …” , ajouter:

location / {

  # Une IP amie ?
  if ( $remote_addr != 212.212.212.212 ) {
    # Non
    set $test "1";
  }

  # Le ssl est verifié ?
  if ( $ssl_client_verify != 'SUCCESS' ) {
    # Non
    set $test "${test}2";
  }

  # Pas Amie et SSL non verifié ?
  if ( $test = '12' ) {
    # Oui: rejeter
    return 403;
  }

  # continuer la conf normale...
  
  proxy_pass http://127.0.0.1:8080/;
  access_log off;
  
}

sub_filter

Pour que la réécriture du contenu des pages HTML fonctionne avec “sub_filter”, il faut désactiver la compression “gzip” .

Le plus simple étant de vider l'entête “encoding” comme ceci:

proxy_set_header Accept-Encoding "";

A nous maintenant les:

sub_filter <h3>Hi</h3> '<h3>Hello World!</h3>'

Source: http://forum.nginx.org/read.php?2,229411,229431

examiner les certificats en ligne

$ echo | openssl s_client -connect mon_site:443

Enjoy !

Sources

Comments




Si vous ne pouvez pas lire le code, téléchargez ce fichier .wav pour l'écouter.
blog/2016/01/27/nginx_et_ssl_client_certificate.txt · Dernière modification: 2016/01/27 00:12 par thierry