Table des matières

source : http://www.christopher.compagnon.name/sitewww/https.html

OpenSSL : génération de certificats

Mise en place

Pour créer et utiliser des certificat et autres clefs, il faut installer OpenSSL. Sous FreeBSD, OpenSSL est déjà installé par défaut. Pour les autres systèmes, il faut se référer à la documentation correspondante pour l'installation.

Création de l'autorité de certification

L'autorité de certification a pour objectif de garantir la validité du certificat. En général, cette validation a un coût. Pour un usage personnel ou sur un intranet, il n'est pas forcément utile d'utiliser une autorité de certification reconnue, vous pouvez créer la vôtre. Bien entendu, elle ne sera pas référencée auprès du grand public et l'utilisation de certificats gérés par cette autorité pourra générer un certain nombre d'alerte (que l'on pourra supprimer en référençant manuellement l'autorité créée ad hoc).

Dans /etc/ssl, créons par exemple, l'arborescence suivante :

mondomaine.com/
|-- certs/
|-- crl/
|-- index.txt
|-- newcerts/
|-- private/
|-- serial

avec les commandes suivantes :

mkdir -p /etc/ssl/mondomaine.com/{certs,crl,newcerts,private}
touch /etc/ssl/mondomaine.com/index.txt
echo "01" > /etc/ssl/mondomaine.com/serial

Il faut configurer OpenSSL en modifiant le fichier de configuration /etc/ssl/openssl.cnf en commençant par définir votre domaine :

[ ca ]

default_ca      = mondomaine          # The default ca section


[ mondomaine ]

dir             = /etc/ssl/mondommaine.com  # 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/cacert.pem       # 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/cakey.pem# The private key
RANDFILE        = $dir/private/.rand    # private random number file

x509_extensions = usr_cert              # The extentions to add to the cert

# Comment out the following two lines for the "traditional"
# (and highly broken) format.
name_opt        = ca_default            # Subject Name options
cert_opt        = ca_default            # Certificate field options
                                                                               
# Extension copying option: use with caution.
# copy_extensions = copy
                                                                               
# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs
# so this is commented out by default to leave a V1 CRL.
# crlnumber must also be commented out to leave a V1 CRL.
# crl_extensions        = crl_ext

default_days    = 365                   # how long to certify for
default_crl_days= 30                    # how long before next CRL
default_md      = md5                   # which md to use.
preserve        = no                    # keep passed DN ordering
                                                                                
# A few difference way of specifying how similar the request should look
# For type CA, the listed attributes must be the same, and the optional
# and supplied fields are just that :-)
policy          = policy_match

default_days (durée de vie des certificats émis par l'AC) et default_crl_days (durée de vie d'une CRL) peuvent être modifiées pour vos besoins.

Puis définissez les paramètres par défaut de création de certificats :

[ 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     = Ile-de-France

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

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

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

Dans le cas où vous décidez d'être votre propre autorité, il ne vous reste qu'à créer la double clef auto-signée (certificat racine) pour l'autorité de certification (CA) pour, par exemple, 10 ans (3560 jours) :

cd /etc/ssl/mondomaine.com
openssl req -x509 -newkey rsa:1024 -days 3650 -keyout private/cakey.pem -out cacert.pem
Generating a 1024 bit RSA private key
........++++++
...................++++++
writing new private key to 'private/cakey.pem'
Enter PEM pass phrase:
Verifying - Enter PEM pass phrase:
-----
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) [Ile-de-France]:
Locality Name (eg, city) [Paris]:
Organization Name (eg, company) [Example]:
Organizational Unit Name (eg, section) []:.
Common Name (eg, YOUR name) []:AC Example
Email Address []:admin@mondomaine.com

L'AC est maintenant configurée, on peut commencer à signer des certificats.

Génération de certificats

Dans le cas où nous voudrions chiffrer une connexion client-serveur, il y a plusieurs possibilités. Dans la majorité des cas, nous n'en retiendrons que 2.

Génération de certificats serveur

Le premier cas concerne la génération d'un certificat pour le serveur. Le certificat est placé sur le serveur et permet aux personnes autorisées (autorisations définies au niveau du serveur web) de se connecter et d'avoir une connexion sécurisée, sans qu'il faille gérer les accès d'une autre façon.

Par défaut, le mot de passe du certificat est géré au niveau du serveur ce qui oblige à entrer le mot de passe à chaque redémarrage du serveur HTTP. Or, si l'on n'est pas sur place et qu'un redémarrage est nécessaire, le serveur http ne se lancera pas. L'idéal est donc de créer une clef sans mot de passe, de la façon suivante :

cd /etc/ssl/mondomaine.com
openssl genrsa -out mondomaine.key 1024

Puis, à partir de cette clef, on génère une demande de certificat :

openssl req -new -key mondomaine.key -out mondomaine.csr

Une suite de questions va être posée. Prenez soin de bien y répondre.

Attention !

Dans le cas d'une demande pour un serveur, l'information Common Name (eg, YOUR name) []: doit être initialisée avec le nom de votre domaine, celui que vous utiliserez dans votre configuration apache. Si par exemple, vous désirez définir https://www.mondoamine.com alors vous définirez Common Name (eg, YOUR name) []:www.mondomaine.com.

Cette demande de certificat est soit envoyée à une autorité de certification, soit vous pouvez la valider grâce à l'autorité que nous venons de définir :

openssl x509 -req -days 365 -in mondomaine.csr -signkey mondomaine.key -out mondomaine.crt

Dans cet exemple, le certificat est valable 365 jours.

Nous disposons donc de deux fichiers qui nous intéressent : mondomaine.crt (le certificat) et mondomaine.key (la clef).

Génération de certificats client

Dans le cas où nous voudrions gérer une connexion chiffrée avec contrôle d'accès intégré, il suffirait alors de créer des certificats clients.

Commençons par créer la demande :

cd /etc/ssl/mondomaine.com
openssl req -newkey rsa:1024 -keyout client.key -out client.req

Une suite de questions va être posée. Prenez soin de bien y répondre.

Attention !

Contrairement à la définition pour un serveur, dans le cas d'une demande pour un client, l'information Common Name (eg, YOUR name) []: doit être initialisée avec le nom réel du client. Si par exemple, vous désirez définir un certificat pour Will Smith alors vous définirez Common Name (eg, YOUR name) []: Will Smith.

Signez ensuite le certificat :

openssl ca -in client.req -out client.pem

Pour pouvoir importer le bi-clé de l'utilisateur dans un navigateur web, il faut que celui soit au format PKCS#12, il faut donc créer un tel fichier grâce à la commande :

openssl pkcs12 -export -in client.pem -inkey client.key -out wsmith.p12 -name "Will Smith"

Cette commande va poser des questions afin de définir le mot de passe :

Enter pass phrase for client.key:
Enter Export Password:
Verifying - Enter Export Password:

Serveur web : création de domaine et serveurs virtuels

Une fois les certificats en main, il faut maintenant créer les environnements web sécurisés correspondants.

Tous les exemples seront réalisés sur Apache.

Création d'un serveur virtuel spécifique

Nous sommes en environnement sécurisé par opposition à l'environnement classique. Pour cela, par opposition à http (port 80) nous voudrions https (port 443).

Rien de plus facile. Créons une arborescence :

/usr/local/wwws/
|-- data/
|-- cgi-bin/

avec les commandes suivantes :

mkdir -p /usr/local/wwws/{data,cgi-bin}
echo "Bienvenue sur mon serveur" > /usr/local/wwws/data/index.html

Créons ensuite un nouveau serveur virtuel grâce au fichier httpd-vhosts.conf :

Cas de certificats serveur

Listen 443
NameVirtualHost *:443

<VirtualHost *:443>
#courriel de l'administrateur
ServerAdmin admin@mondomaine

#repertoire des fichiers du site
DocumentRoot /usr/local/wwws/data
<IfModule alias_module>
ScriptAlias /cgi-bin/ "/usr/local/wwws/cgi-bin/"
</IfModule>

#Le nom du serveur
ServerName www.mondomaine.name

#Log d'erreur
ErrorLog /var/log/httpsd-error.log

# Configuration mod_ssl
SSLEngine on
SSLOptions +FakeBasicAuth +ExportCertData +StrictRequire

#On utilise SSLv2, SSLv3 et TSLv1
SSLProtocol All

#Autorise seulement les algo crypt forte pour la création de la session SSL
SSLCipherSuite MEDIUM:HIGH

# Chemin vers le certificat de l'AC
SSLCACertificateFile /etc/ssl/mondomaine.com/cacert.pem

# Chemin vers le certificat du serveur
SSLCertificateFile /usr/local/etc/apache22/mondomaine.crt

# Chemin vers la clé privée associée au certificat
SSLCertificateKeyFile /usr/local/etc/apache22/mondomaine.key
</VirtualHost>

N'oublions pas de copier wwws.crt et wwws.key au bon endroit. Nous pourrions tout aussi bien définir SSLCertificateFile et SSLCertificateKeyFile sur le répertoire /etc/ssl/mondomaine.com/ afin d'éviter de faire la copie des certificats et des clefs.

Tout serait parfait, sauf qu'il faut autoriser les utilisateurs à accéder aux nouveaux répertoires. Sans cela vous auriez le message d'erreur suivant :

client denied by server configuration: /usr/local/wwws/data/index.html

Il faut donc ajouter les autorisations au fichier de paramètres httpd-vhosts.conf :

<Directory "/usr/local/wwws/data">
Allow from all
</Directory>

<Directory "/usr/local/wwws/cgi-bin">
AllowOverride None
Options +ExecCGI 
Order allow,deny
Allow from all
</Directory>

L'option +ExecCGI permet d'activer l'exécution des scripts CGI sous apache.

Maintenant, il faut placer ce fichier dans le répertoire extra de configuration d'apache et activer la ligne httpd-vhosts.conf dans le fichier httpd.conf de façon à ajouter le fichier à la configuration. Puis redémarrer le serveur apache (restart).

Si tout s'est bien passé, vous pouvez accéder au domaine https://www.mondomaine.com, un environnement distinct et différent de http://www.mondomaine.com.

Si votre navigateur crie un peu au moment de la connexion, n'hésitez pas à définir votre autorité de certification en ajoutant cacert.pem au magasin de certificat racine de votre navigateur préféré.

Cette configuration définit deux répertoire séparés, l'un pour les CGI l'autre pour des fichiers simplement qui ne seront pas exécutés. Si nous voulions pouvoir tout rassembler sous un seul répertoire, afin de mélanger HTML et CGI, il faudrait définir alors la configuration suivante :

Listen 443
NameVirtualHost *:443

<VirtualHost *:443>
#courriel de l'administrateur
ServerAdmin admin@mondomaine

#repertoire des fichiers du site
DocumentRoot /usr/local/wwws/data

#Le nom du serveur
ServerName www.mondomaine.name

#Log d'erreur
ErrorLog /var/log/httpsd-error.log

# Configuration mod_ssl
SSLEngine on
SSLOptions +FakeBasicAuth +ExportCertData +StrictRequire

#On utilise SSLv2, SSLv3 et TSLv1
SSLProtocol All

#Autorise seulement les algo crypt forte pour la création de la session SSL
SSLCipherSuite MEDIUM:HIGH

# Chemin vers le certificat de l'AC
SSLCACertificateFile /etc/ssl/mondomaine.com/cacert.pem

# Chemin vers le certificat du serveur
SSLCertificateFile /usr/local/etc/apache22/mondomaine.crt

# Chemin vers la clé privée associée au certificat
SSLCertificateKeyFile /usr/local/etc/apache22/mondomaine.key
</VirtualHost>

<Directory "/usr/local/wwws/data">
Allow from all
AddHandler cgi-script .cgi
Options +FollowSymLinks +Indexes +ExecCGI
DirectoryIndex index.cgi index.html
AllowOverride None
</Directory>

Cette configuration définit alors les fichiers .cgi comme des cgi (exécutables) et pour index index.cgi (au lieu de index.html par défaut).

AllowOverride None permet de ne pas utiliser l'authentification interne à apache (.htaccess).

L'option +FollowSymLinks permet de suivre les liens dans les sous-répertoires et d'autoriser leur accès (dands le cas contraire, votre navigateur vous indiquerait : accès refusé).

Cas de certificats client

Pour le cas du certificat client, il suffit d'effectuer les mêmes opérations que le Cas de certificats serveur, mais en définissant l'authentification du client de la manière suivante :

Listen 443
NameVirtualHost *:443

<VirtualHost *:443>
[...]

# Chemin vers le certificat du serveur
SSLCertificateFile /usr/local/etc/apache22/client.crt

# Chemin vers la clé privée associée au certificat
SSLCertificateKeyFile /usr/local/etc/apache22/client.key

# Demander l'authentification des visiteurs
SSLVerifyClient require

</VirtualHost>

Du côté du client, il faudra importer le fichier wsmith.p12 dans le navigateur et entrer le mot de passe requis pour s'authentifier.

Arborescence spécifique sur un serveur

Dans le cas où nous voudrions simplement sécuriser une sous arborescence spécifique d'un serveur existant. Supposons par exemple que nous voudrions sécuriser l'accès au répertoire /private du serveur http://www.mondomaine.com, dans ce cas, conformément aux exemples précédents, il faudrait créer un fichier httpd-vhosts.conf ainsi :

SSLEngine       on
SSLProtocol     all
SSLCipherSuite  HIGH:MEDIUM

SSLCertificateFile      /usr/local/etc/apache/ssl.crt/mondomaine.pem
SSLCertificateKeyFile   /usr/local/etc/apache/ssl.key/mondomaine.pem

SSLVerifyClient none

SSLCACertificatePath    configuration/certificates
SSLCACertificateFile    configuration/certificates/cacert.pem

<Location /private>
     SSLVerifyClient require
     SSLVerifyDepth  1
</Location>

Conclusion

Une fois votre configuration achevée, il ne faudra pas oublier d'ouvrir le port défini (ici 443) avant de pouvoir utiliser votre nouveau serveur sécurisé afin de pouvoir y accéder depuis l'extérieur. Normalement, si la configuration est correcte, il suffira d'accéder au serveur avec https://www.mondomaine.com/.