Le blog de la CT2C

Installer un certificat SSL sur Apache

Par Régis Millet aka Kulgar , publié le 5 Septembre 2013

Bonjour chers lecteurs ! Je sais, le sujet de cet article ne parle pas de Ruby On Rails, mais j'ai été récemment confronté à l'installation d'un certificat SSL pour une application Ruby On Rails fonctionnant sur Apache + Passenger. Comme la chose n'est pas forcément évidente, je me suis dit qu'un petit tutoriel pourrait en intéresser plus d'un. Les commandes seront fournies pour un système Ubuntu (Linux) en utilisant la bibliothèque cryptographique "openSSL".

Après le passage concernant Apache, nous verrons tout de même comment forcer l'utilisation de https / ssl par l'application Ruby On Rails ! C'est parti !


Qu'est-ce qu'un certificat SSL ?


Il y a de nombreux articles sur le Web qui expliquent ce qu'est un certificat SSL. Toutefois, je pense qu'il est toujours bon de faire un petit rappel. Un certificat SSL est un certificat électronique qui peut être émis lors de communications réseaux pour identifier une personne ou une entité en "signant" les communications. De cette façon, toute personne recevant le certificat lors d'une communication est apte à vérifier que l'expéditeur de cette communication est bien celui attendu.

En plus de cette signature, ces certificats permettent le chiffrement des communications à l'aide d'un couple de clefs appelées clefs publique et privée dans un processus appelé "cryptographie asymétrique". Ce chiffrement offre une sécurité supplémentaire pour sécuriser un échange de données sensibles.

Définition de Cryptographie asymétrique
La cryptographie asymétrique, ou cryptographie à clé publique, est une méthode de chiffrement qui s'oppose à la cryptographie symétrique. Elle repose sur l'utilisation d'une clé publique (qui est diffusée) et d'une clé privée (gardée secrète), l'une permettant de coder le message et l'autre de le décoder. Ainsi, l'expéditeur peut utiliser la clé publique du destinataire pour coder un message que seul le destinataire (en possession de la clé privée) peut décoder, garantissant la confidentialité du contenu. Inversement, l'expéditeur peut utiliser sa propre clé privée pour coder un message que le destinataire peut décoder avec la clé publique ; c'est le mécanisme utilisé par la signature numérique pour authentifier l'auteur d'un message.
( source : Wikipédia - cryptographie asymétrique )

Par exemple : imaginez que vous avez une communication entre votre PC et le serveur Amazon pour effectuer un achat en ligne. Vous allez devoir transmettre les coordonnées de votre carte bancaire. Comme chacun sait, le Web n'est pas sûr, et beaucoup de pirates écoutent et interceptent de nombreuses communications ( cf les analyseurs de paquets - c'est un exemple parmi d'autres).

Pour se prémunir d'un tel vol de données, Amazon, et bien d'autres sites, possèdent un certificat SSL leur donnant un couple de clef privée / clef publique. Lorsque vous arrivez sur une page en https, Amazon va vous transmettre sa clef publique. Votre navigateur (ou terminal) va ensuite utiliser cette clef publique pour chiffrer les communications envoyées vers Amazon. Et grâce à la clef privée, présente sur les serveurs Amazon, ce dernier va être capable de déchiffrer la communication. De cette façon, seul Amazon et son interlocuteur (en l'occurrence, vous) seront capables de communiquer à travers ce canal "sécurisé". Si un pirate venait à intercepter la communication, il serait incapable de déchiffrer les messages car il ne possède pas la clef privée essentielle pour ce déchiffrage. Malheureusement, ce n'est pas toujours vrai, l'attaque man in the middle est parfois toujours possible... (Un pirate intercepte la communication lors de l'échange des clefs et envoie ses propres clefs publiques à Amazon et à votre terminal).

C'est parce que cette attaque "man in the middle" existe que les certificats doivent être émis par des entités agrées de confiance. En effet, un certificat émis par une entité tierce sera lui-même signé par le certificat de cette entité. De cette façon, lorsque votre terminal reçoit la clef publique du serveur auquel vous vous connectez, il reçoit également la clef publique de l'entité tierce de confiance. Ainsi votre terminal peut vérifier auprès de l'entité de confiance que la clef envoyée par le service auquel vous vous connectez est bien la clef enregistrée chez eux, et donc que votre interlocuteur est bien celui qu'il prétend être.

Vous pouvez devez d'ailleurs vérifier : lorsque vous êtes sur une connexion en "https", vous avez normalement un petit cadenas qui apparaît à côté de l'url dans votre navigateur. Si vous cliquez dessus, vous verrez le message : "L'identité de ce site Web a été vérifié par ... Verisign Class 3 Secure Serveur CA - G3" (pour Amazon) indiquant que le site Web possède bien un certificat signé par une entité de confiance.

Notez qu'il est toujours possible d'auto-signer son propre certificat (I.e. le certificat est signé par l'entité qui l'envoie). En revanche, chaque fois que vos utilisateurs se connecteront à votre service en https, ils recevront une alerte de sécurité les mettant en garde car votre certificat n'a pu être vérifié auprès d'une entité tierce de confiance et donc qu'un pirate a potentiellement pu intercepter la communication. Donc, à moins d'être sur un réseau privé ou d'accéder à votre petit site privé, n'utilisez jamais un certificat auto-signé.

Comment générer un certificat ?


Il faut vous adresser à une autorité de confiance. Celle qui fait référence dans ce milieu, c'est Verisign, mais ses certificats coûtent cher (car ils peuvent être utilisés dans de nombreuses situations). Dans notre cas (i.e. le développement Web), un certificat ne devrait être utilisé que pour chiffrer les communications vers un nom de domaine précis, de fait un tel certificat coûte beaucoup moins cher. Il est fort probable que votre registrar vous offre la possibilité d'acheter un tel certificat associé à un nom de domaine. En tout cas, c'est tout à fait possible sur Gandi.net (et en plus ils vous offrent 1 an - comme le nom de domaine était là-bas, j'ai réservé le certificat là-bas), et je suis sûr que d'autres hébergeurs offrent ce même service.

Définition de Wildcard certificate
Vous entendrez sûrement parler très vite des "wildcard certificates". Plus onéreux, ils permettent la protection de tous les sous-domaines d'un nom de domaine. Exemple : vous avez le domaine tintin.fr. Si vous réservez un tel certificat, il protégera *.tintin.fr et donc : milou.tintin.fr, blog.tintin.fr, www.tintin.fr etc.
Attention ! Il ne protégera pas les sous-domaines de niveau 2 (ou +), ni le domaine principal, donc tintin.fr et aventure.milou.tintin.fr ne pourront pas être protégés par ce certificat...

Pour générer un certificat, vous allez avoir besoin d'un CSR (Certificate sign request). Vous avez plusieurs possibilités pour générer le CSR. Si vous avez un panneau administratif (cpanel, plesk...), vous avez sûrement un onglet ou une fonctionnalité pour ajouter un certificat et obtenir une CSR (quoique je déconseille d'utiliser le panneau de plesk...). Vous pouvez peut-être aussi le générer chez le registrar, à l'aide d'un formulaire... Mais là aussi, je déconseille (chez Gandi, je n'ai personnellement pas réussi à récupérer un élément essentiel devant être créé lors de la génération du CSR : la clef privée du serveur pour le nom de domaine ciblé).

Je préconise donc d'utiliser openSSLen ligne de commande directement depuis le serveur hébergeant votre site pour générer le CSR. La première chose consiste à éditer le fichier de configuration de openssl. Ce fichier doit sûrement se trouver ici :

$ sudo vim /etc/ssl/openssl.cnf 

Vérifiez que vous y trouvez bien ceci :
string_mask = utf8only

Autrement, assignez cette variable comme ci-dessus, ceci afin d'être sûr que openSSL va correctement interpréter les éventuels accents. Vous pouvez également lire les autres options si besoin, mais à priori, il n'y a aucun autre point d'attention.

La prochaine commande consiste à générer à la fois le CSR (en fait la clef publique associée à votre nom de domaine) et la clef privée de votre nom de domaine (celle-la même qui sera utilisée pour déchiffrer les communications !) :

$ openssl req -new -newkey rsa:2048 -nodes -sha512 -out votre.domaine.fr.csr -keyout votre.domaine.fr.key

Nous demandons à openssl de générer un couple de clef de 2048 bits, en signant avec sha512 (par défaut openSSL utilise SHA1). Lorsque vous validez la commande, on va vous poser quelques questions, auxquelles il faut répondre le plus exactement possible. Ces questions vont en quelque sorte ajouter des informations concernant votre société dans le certificat. De cette manière, lorsqu'un utilisateur recevra votre certificat, il obtiendra (normalement) aussi ces informations.

writing new private key to 'votre.domaine.fr.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.
-----

Voici les différentes informations à renseigner (évidemment à adapter selon votre société) :
- Country Name (2 letter code) [AU] (code du pays) : FR
- State or Province Name (full name) [Some-State] (Région ou département) : Ile de France
- Locality Name (eg, city) [] (ville) : Paris
- Organization Name (eg, company) [Internet Widgits Pty Ltd] (nom de votre société) : CT2C
- Organizational Unit Name (eg, section) [] (nom du service - facultatif) : Service informatique
- Common Name (e.g. server FQDN or YOUR name) [] (le nom de votre domaine): ct2c.fr !!! très important, ce champ sera utilisé par l'entité où vous réservez le certificat pour détecter le nom de domaine à protéger
- Email Address [] (email):
- A challenge password []: NE RIEN METTRE !!! (j'ai lu à plusieurs reprises que c'était non requis voire non conseillé pour un certificat échangé sur le Web)
- An optional company name []:

Et voilà ! Cela a produit deux fichiers dans votre répertoire courant : le CSR "votre.domaine.fr.csr" et la clef privée "votre.domaine.fr.key".

Important ! Du fait de l'importance de la clef privée de votre domaine, il est rudement conseillé de vérifier modifier les autorisations d'accès à ce fichier. Seul l'utilisateur "root" devrait y avoir un accès en lecture et écriture !
Concernant le CSR, affichez-le et copiez son contenu :

$ cat votre.domaine.fr.csr 

C'est cette longue chaîne de caractères que vous devez entièrement fournir à l'entité chez laquelle vous achetez le certificat SSL. Attention ! Le nom de domaine utilisé pour créer le CSR à la question "Common Name" est très important car lorsque vous fournirez le CSR, ce dernier sera normalement automatiquement détecté.

Continuez maintenant le processus d'achat du certificat en ligne. (Si on vous pose la question, choisissez Apache / modSSL pour le logiciel utilisé). Une fois acheté, l'entité va sûrement vous demander d'effectuer une manip' pour qu'elle vérifie que vous êtes bien le propriétaire du nom de domaine que vous souhaitez protéger. Une fois effectuée, vous devriez obtenir le certificat, ou plutôt 2 certificats : le vôtre, et le certificat "intermédiaire" représentant le certificat de l'entité. Téléchargez-les et placez les sur votre serveur.

Installation du certificat et configuration d'Apache


Nous sommes maintenant sur notre serveur, nous y avons 4 fichiers : le CSR, la clef privée associée à notre nom de domaine, le certificat pour notre nom de domaine et le certificat de l'entité. La CSR n'est plus utile, mais gardez-la quand même sous le coude des fois que vous ayez besoin de générer un nouveau certificat. Quant aux 3 autres fichiers, nous allons les déplacer où il faut :

 
$ sudo mv ./votre.domaine.fr.key /etc/ssl/private
$ sudo mv ./votre_certificat.crt /etc/ssl/certs
$ sudo mv ./certificat_entité.pem /etc/ssl/certs

Certains vieux navigateurs (ainsi que GnuTLS) auront besoin que le certificat de l'entité soit directement à la suite de votre certificat, dans le même fichier. Ca ne coûte rien d'effectuer cette manipulation :
$ sudo cat /etc/ssl/certs/certificat_entité.pem >> /etc/ssl/certs/votre_certificat.crt

Puis exécutons une commande spécifique aux certificats :
$ c_rehash /etc/ssl/certs 

( Plus d'informations sur la commande c_rehash )

Passons maintenant à la configuration d'apache
Commençons par activer le module ssl d'apache :
$ a2enmod ssl

Une fois fait, il nous reste à indiquer à Apache d'écouter sur le port 443, utilisé par défaut pour les communications HTTPS. Modifiez le fichier /etc/apache2/ports.conf :

$ sudo vim /etc/apache2/ports.conf

Et ajoutez-y (si ce n'est pas déjà fait) :

<IfModule mod_ssl.c>
# If you add NameVirtualHost *:443 here, you will also have to change
# the VirtualHost statement in /etc/apache2/sites-available/default-ssl
# to <VirtualHost *:443>
# Server Name Indication for SSL named virtual hosts is currently not
# supported by MSIE on Windows XP.
NameVirtualHost adresse_ip_du_domaine_ou_serveur:443
Listen 443
</IfModule>

Il vous reste ensuite à modifier le virtualhost SSL de votre nom de domaine pour qu'il utilise les certificats que nous venons d'installer. Créez un nouveau fichier dans le dossier /etc/apache2/sites-available :

$ sudo vim /etc/apache2/sites-available/votre.domaine.fr-ssl


Et ajoutez-y les lignes :

<VirtualHost VOTRE_ADRESSE_IP:443>

ServerName votre.domaine.fr
ServerAlias domaine.fr
DocumentRoot /var/www/www.votre.domaine.fr/
CustomLog /var/log/apache2/secure_access.log combined

SSLEngine on
SSLCertificateFile /etc/ssl/certs/votre_certificat.crt
SSLCertificateKeyFile /etc/ssl/private/votre.domaine.fr.key
SSLCACertificateFile /etc/ssl/certs/certificat_entité.pem
SSLVerifyClient None
</VirtualHost>

Les 4 premières lignes sont classiques. Les suivantes servent à activer SSL et à spécifier les chemins vers les différentes certificats et clef privée. SSLVerifyClient spécifie que le certificat du client (i.e. de vos utilisateurs) ne sera pas vérifié. Autrement dit, vous n'attendez pas de vos clients qu'ils possèdent un certificat SSL lorsqu'ils se connectent à votre site. (Ce serait tout à fait possible pour des applications demandant une sécurité encore plus grande, par exemple entre 2 réseaux privés de 2 sociétés différentes).

Enfin, il nous reste à activer le site et à redémarrer apache :
$ a2ensite votre.domaine.fr-ssl
$ /etc/init.d/apache2 restart

Vous pouvez vérifier la bonne installation du certificat à l'aide de cette commande depuis un terminal externe :
$ openssl s_client -connect ip_server:443 


Spécificités avec plesk


Comme en général je travaille avec plesk, je vous ajoute un petit paragraphe le concernant. Il y a en effet quelques petites variantes. Vous noterez aussi que le fichier virtualhost présenté ci-dessous possède davantage de configurations, que vous pouvez réutiliser ailleurs que dans plesk si vous le désirez.

Donc sous plesk (version 10+) :> Connectez-vous à votre espace d'administration plesk,
> Allez dans l'onglet "Sites Web et domaines",
> Cliquez sur "Sécuriser vos sites",
> Cliquez sur "Gérer" à côté du nom de domaine pour lequel vous souhaitez installer le certificat,
> Cliquez sur "Ajouter un certificat",
> Remplissez le nom du certificat (par exemple : mon-domaine.com) puis allez tout en bas et remplissez les champs de texte :
- Le premier avec votre clef privée serveur générée grâce à la commande OpenSSL faite précédemment,
- Le deuxième avec le certificat délivré par votre autorité de certification,
- Le troisième avec le certificat de l'autorité de certification
> Cliquez sur "envoyer le texte"
> Retournez dans l'onglet Sites Web et domaines,
> Cliquez sur le nom de domaine à protéger dans la liste tout en bas,
> Cliquez sur "Activer le certificat",
> Sélectionnez le certificat fraîchement ajouté dans la liste qui apparaît,
> Validez, et voilà !!

Attention ! Vous devez vérifier votre fichier vhost_ssl.conf. Ce fichier se trouve normalement dans : /var/www/vhosts/votre-domaine/conf/vhost_ssl.conf.

Ce fichier ne doit contenir AUCUNE information concernant un éventuel certificat. Donc aucune des trois lignes suivantes ne doit apparaître :
SSLCertificateFile /etc/ssl/certs/mon-cert.crt
SSLCertificateKeyFile /etc/ssl/private/ma-clef.key
SSLCertificateChainFile /etc/ssl/certs/le-ca-autorité.pem


Pourquoi ?
Le serveur plesk génère automatiquement des fichiers de configurations (dans ce même dossier) avec tout ce qu'il faut dedans pour activer le SSL et charger le certificat. Ces mêmes fichiers chargent ensuite le fichier vhost_ssl.conf. Si vous y spécifiez un chemin vers un certificat, les 2 certificats seront chargés par le serveur Apache qui tentera alors d'envoyer 2 certificats. Or, ce n'est pas permis. Si vous le faites, vous aurez dans les journaux apache l'erreur suivante :

Init: Multiple RSA server certificates not allowed

Sachez qu'elle est liée à une tentative, par le serveur, d'envoyer 2 certificats pour un même domaine. Tant que l'erreur sera là, vous ne pourrez plus relancer votre serveur apache, car celle-ci apparaît à l'initialisation du serveur. Faites donc très attention à la configuration de votre fichiers vhost_ssl.conf. Toutefois, ce fichier doit au moins contenir les informations ajoutées dans vhost.conf pour le bon fonctionnement de votre application.

Voici un exemple de configuration du fichier vhost_ssl.conf pour une application Rails :
ServerName my.domain.com
ServerAdmin my.admin@gmail.com
DocumentRoot /var/www/vhosts/my-server/my.domain.com/public
ErrorLog /var/log/apache2/my_domain_com_errors.log
LogLevel warn
CustomLog /var/log/apache2/my_domaine_com_ssl.log combined
BrowserMatch "MSIE [2-6]" nokeepalive ssl-unclean-shutdown downgrade-1.0 force-response-1.0
BrowserMatch "MSIE [17-9]" ssl-unclean-shutdown
SetEnv RAILS_ENV production
<Directory /var/www/vhosts/my-server/my.domain.com/public>
Allow from all
Options -MultiViews
</Directory>


Forcer une application Ruby On Rails à utiliser https / SSL


Eh bien en fait, ce n'est vraiment pas compliqué du tout pour une application Rails de version 3.1 ou supérieure. Il vous suffit d'ajouter cette ligne dans le fichier de configuration de votre application, par exemple dans production.rb:

config.force_ssl = true

Grâce au "middleware" Rack SSL qui se trouve ainsi activé, Ruby On Rails va automatiquement rediriger les requêtes HTTP vers HTTPS. Le middleware va également effectuer quelques autres actions pour renforcer la sécurité de la communication HTTPS.

Mais, me direz-vous, comment faire si on veut que l'application soit accessible à la fois en HTTP et en HTTPS ? Ca peut arriver par exemple lorsque vous migrez votre application vers HTTPS et que tout n'est pas encore opérationnel (notamment au niveau des communications avec des services externes). Pour ce faire, le middleware Rack SSL accepte une option "exclude". La ligne suivante :

config.middleware.insert_before ActionDispatch::Static, Rack::SSL, :exclude => proc { |env| env['HTTPS'] != 'on' }

Permettra d'activer ce middleware uniquement si l'url accédée par l'utilisateur contient "https".

Bien, mais ces solutions forcent l'utilisation de https pour tout le site ! Il peut être parfois nécessaire d'utiliser une connexion https uniquement sur certaines pages. Pour ce faire, vous pouvez utiliser l'option "constraints" dans votre fichier "routes.rb", comme ceci :

scope :constraints => { :protocol => "https" } do
# Vos routes sécurisées, par exemple :
get "/acheter" => "baskets#checkout", :as => :checkout
end

Vous trouverez également d'autres solutions en utilisant la gem rack-ssl-enforcer, qui vous permettra de forcer l'utilisation de SSL seulement sur certaines URLs. La documentation est bien fournie et la gem semble tout à fait intéressante. A vous de choisir votre solution préférée.

Et voilà le site pour lequel j'ai installé un certificat SSL : Unow-mooc, site de cours en ligne massifs. Vous pouvez vérifier, il y a bien le petit cadenas et le certificat est bien vérifié par Gandi !

Cela termine mon tutoriel, j'espère qu'il saura être utile à plus d'un. Je vous dis à bientôt !
Régis.


Sources :
Cultures autour des certificats :
- Les certificats électroniques,
- L'attaque man in the middle,
- La cryptographie asymétrique,

Tutoriels :
- Comment installer un certificat SSL (différents systèmes),
- Comment forcer HTTPS pour certaines URLs avec Apache,
- Comment forcer HTTPS sur une application Rails 3,
- Forcer SSL sur certaines routes en RoR,
- Gem rack-ssl-enforcer,

Docs :
- Options et références du module apache ModSSL.


Index -- --

  • Aucun commentaire - Soyez le premier !

Insérez votre commentaire
  1. Min: 50 caractères, Max: 800. Actuellement: 0 caractères

  2. ne pas remplir