mirror of
https://github.com/almet/notmyidea.git
synced 2025-04-28 19:42:37 +02:00
169 lines
No EOL
10 KiB
HTML
169 lines
No EOL
10 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="fr">
|
||
<head>
|
||
<title>
|
||
Let’s Encrypt + HAProxy - Alexis Métaireau </title>
|
||
<meta charset="utf-8" />
|
||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||
<link rel="stylesheet"
|
||
href="https://blog.notmyidea.org/theme/css/main.css?v2"
|
||
type="text/css" />
|
||
<link href="https://blog.notmyidea.org/feeds/all.atom.xml"
|
||
type="application/atom+xml"
|
||
rel="alternate"
|
||
title="Alexis Métaireau ATOM Feed" />
|
||
</head>
|
||
<body>
|
||
<div id="content">
|
||
<section id="links">
|
||
<ul>
|
||
<li>
|
||
<a class="main" href="/">Alexis Métaireau</a>
|
||
</li>
|
||
<li>
|
||
<a class=""
|
||
href="https://blog.notmyidea.org/journal/index.html">Journal</a>
|
||
</li>
|
||
<li>
|
||
<a class="selected"
|
||
href="https://blog.notmyidea.org/code/">Code, etc.</a>
|
||
</li>
|
||
<li>
|
||
<a class=""
|
||
href="https://blog.notmyidea.org/weeknotes/">Notes hebdo</a>
|
||
</li>
|
||
<li>
|
||
<a class=""
|
||
href="https://blog.notmyidea.org/lectures/">Lectures</a>
|
||
</li>
|
||
<li>
|
||
<a class=""
|
||
href="https://blog.notmyidea.org/projets.html">Projets</a>
|
||
</li>
|
||
</ul>
|
||
</section>
|
||
|
||
<header>
|
||
<h1 class="post-title">Let’s Encrypt + HAProxy</h1>
|
||
<p><em>Comment j'ai mis en place des certificats SSL avec Let's Encrypt derrière haproxy.</em></p>
|
||
<time datetime="2016-02-11T00:00:00+01:00">11 février 2016</time>
|
||
|
||
|
||
</header>
|
||
<article>
|
||
<p><em>Note : Cet article n’est plus à jour. Il est maintenant (2018) possible d’installer des certificats <span class="caps">SSL</span> Let’s Encrypt d’une manière beaucoup plus simple, en utilisant certbot (et le plugin nginx <code>certbot --nginx</code>).</em></p>
|
||
<blockquote>
|
||
<p>It’s time for the Web to take a big step forward in terms of security
|
||
and privacy. We want to see <span class="caps">HTTPS</span> become the default. Let’s Encrypt
|
||
was built to enable that by making it as easy as possible to get and
|
||
manage certificates.</p>
|
||
<p>— <a href="https://letsencrypt.org/">Let’s Encrypt</a></p>
|
||
</blockquote>
|
||
<p>Depuis début Décembre, la nouvelle <em>autorité de certification</em> Let’s
|
||
Encrypt est passée en version <em>Beta</em>. Les certificats <span class="caps">SSL</span> sont un moyen
|
||
de 1. chiffrer la communication entre votre navigateur et le serveur et
|
||
2. un moyen d’être sur que le site Web auquel vous accédez est celui
|
||
auquel vous pensez vous connecter (pour éviter des <a href="https://fr.wikipedia.org/wiki/Attaque_de_l'homme_du_milieu">attaques de l’homme
|
||
du milieu</a>).</p>
|
||
<p>Jusqu’à maintenant, il était nécessaire de payer une entreprise pour
|
||
faire en sorte d’avoir des certificats qui évitent d’avoir ce genre
|
||
d’erreurs dans vos navigateurs:</p>
|
||
<p><img alt="Message de firefox lorsque une connexion n'est pas
|
||
sécurisée." src="%7Bfilename%7D/static/unsecure-connection.png"></p>
|
||
<p>Maintenant, grâce à Let’s Encrypt il est possible d’avoir des
|
||
certificats <span class="caps">SSL</span> <strong>gratuits</strong>, ce qui représente un grand pas en avant
|
||
pour la sécurité de nos communications.</p>
|
||
<p>Je viens de mettre en place un procédé (assez simple) qui permet de
|
||
configurer votre serveur pour générer des certificats <span class="caps">SSL</span> valides avec
|
||
Let’s Encrypt et le répartiteur de charge
|
||
<a href="http://www.haproxy.org/">HAProxy</a>.</p>
|
||
<p>Je me suis basé pour cet article sur
|
||
d’<a href="https://blog.infomee.fr/p/letsencrypt-haproxy">autres</a>
|
||
<a href="http://blog.victor-hery.com/article22/utiliser-let-s-encrypt-avec-haproxy">articles</a>,
|
||
dont je vous recommande la lecture pour un complément d’information.</p>
|
||
<h2 id="validation-des-domaines-par-lets-encrypt">Validation des domaines par Let’s Encrypt</h2>
|
||
<p>Je vous passe les détails d’installation du client de Let’s Encrypt, qui
|
||
sont <a href="https://github.com/letsencrypt/letsencrypt#installation">très bien expliqués sur leur
|
||
documentation</a>.</p>
|
||
<p>Une fois installé, vous allez taper une commande qui va ressembler à:</p>
|
||
<div class="highlight"><pre><span></span><code>letsencrypt-auto certonly --renew-by-default
|
||
--webroot -w /home/www/letsencrypt-requests/ \
|
||
-d hurl.kinto-storage.org \
|
||
-d forums.kinto-storage.org
|
||
</code></pre></div>
|
||
|
||
<p>Le <em>webroot</em> est l’endroit ou les preuves de détention du domaine vont
|
||
être déposées.</p>
|
||
<p>Lorsque les serveurs de Let’s Encrypt vont vouloir vérifier que vous
|
||
êtes bien à l’origine des demandes de certificats, ils vont envoyer une
|
||
requête <span class="caps">HTTP</span> sur <code>http://domaine.org/.well-known/acme-challenge</code>, ou il
|
||
voudra trouver des informations qu’il aura généré via la commande
|
||
<code>letsencrypt-auto</code>.</p>
|
||
<p>J’ai choisi de faire une règle dans haproxy pour diriger toutes les
|
||
requêtes avec le chemin <code>.well-known/acme-challenge</code> vers un <em>backend</em>
|
||
nginx qui sert des fichiers statiques (ceux contenus dans
|
||
<code>/home/www/letsencrypt-requests/</code>).</p>
|
||
<p>Voici la section de la configuration de HAProxy (et <a href="https://github.com/almet/infra/blob/master/haproxy/haproxy.cfg#L63-L72">la configuration
|
||
complete</a>
|
||
si ça peut être utile):</p>
|
||
<div class="highlight"><pre><span></span><code><span class="nv">frontend</span><span class="w"> </span><span class="nv">http</span>
|
||
<span class="w"> </span><span class="nv">bind</span><span class="w"> </span><span class="mi">0</span>.<span class="mi">0</span>.<span class="mi">0</span>.<span class="mi">0</span>:<span class="mi">80</span>
|
||
<span class="w"> </span><span class="nv">mode</span><span class="w"> </span><span class="nv">http</span>
|
||
<span class="w"> </span><span class="nv">default_backend</span><span class="w"> </span><span class="nv">nginx_server</span>
|
||
|
||
<span class="w"> </span><span class="nv">acl</span><span class="w"> </span><span class="nv">letsencrypt_check</span><span class="w"> </span><span class="nv">path_beg</span><span class="w"> </span><span class="o">/</span>.<span class="nv">well</span><span class="o">-</span><span class="nv">known</span><span class="o">/</span><span class="nv">acme</span><span class="o">-</span><span class="nv">challenge</span>
|
||
<span class="w"> </span><span class="nv">use_backend</span><span class="w"> </span><span class="nv">letsencrypt_backend</span><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="nv">letsencrypt_check</span>
|
||
|
||
<span class="w"> </span><span class="nv">redirect</span><span class="w"> </span><span class="nv">scheme</span><span class="w"> </span><span class="nv">https</span><span class="w"> </span><span class="nv">code</span><span class="w"> </span><span class="mi">301</span><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="o">!</span>{<span class="w"> </span><span class="nv">ssl_fc</span><span class="w"> </span>}<span class="w"> </span><span class="o">!</span><span class="nv">letsencrypt_check</span>
|
||
|
||
<span class="nv">backend</span><span class="w"> </span><span class="nv">letsencrypt_backend</span>
|
||
<span class="w"> </span><span class="nv">http</span><span class="o">-</span><span class="nv">request</span><span class="w"> </span><span class="nv">set</span><span class="o">-</span><span class="nv">header</span><span class="w"> </span><span class="nv">Host</span><span class="w"> </span><span class="nv">letsencrypt</span>.<span class="nv">requests</span>
|
||
<span class="w"> </span><span class="nv">dispatch</span><span class="w"> </span><span class="mi">127</span>.<span class="mi">0</span>.<span class="mi">0</span>.<span class="mi">1</span>:<span class="mi">8000</span>
|
||
</code></pre></div>
|
||
|
||
<p>Et celle de <span class="caps">NGINX</span>:</p>
|
||
<div class="highlight"><pre><span></span><code>server {
|
||
listen 8000;
|
||
server_name letsencrypt.requests;
|
||
root /home/www/letsencrypt-requests;
|
||
}
|
||
</code></pre></div>
|
||
|
||
<h2 id="installation-des-certificats-dans-haproxy">Installation des certificats dans HAProxy</h2>
|
||
<p>Vos certificats <span class="caps">SSL</span> devraient être générés dans <code>/etc/letsencrypt/live</code>,
|
||
mais ils ne sont pas au format attendu par haproxy. Rien de grave, la
|
||
commande suivant convertit l’ensemble des certificats en une version
|
||
compatible avec HAProxy:</p>
|
||
<div class="highlight"><pre><span></span><code>cat /etc/letsencrypt/live/domaine.org/privkey.pem /etc/letsencrypt/live/domaine.org/fullchain.pem > /etc/ssl/letsencrypt/domaine.org.pem
|
||
</code></pre></div>
|
||
|
||
<p>Et ensuite dans la configuration de haproxy, pour le (nouveau)
|
||
<em>frontend</em> https:</p>
|
||
<div class="highlight"><pre><span></span><code>bind 0.0.0.0:443 ssl no-sslv3 crt /etc/ssl/letsencrypt
|
||
</code></pre></div>
|
||
|
||
<p>Faites bien attention à avoir un <em>frontend</em> https pour tous vos sites en
|
||
<span class="caps">HTTPS</span>. <a href="https://github.com/almet/infra/blob/master/haproxy/haproxy.cfg#L38-L60">Pour moi cela ressemble à
|
||
ça</a>.</p>
|
||
<p>Une fois tout ceci fait, redémarrez votre service haproxy et zou !</p>
|
||
<h2 id="automatisation">Automatisation</h2>
|
||
<p>Pour automatiser un peu tout ça, j’ai choisi de faire ça comme suit:</p>
|
||
<ul>
|
||
<li>Un fichier domaine dans <code>letsencrypt/domains/domain.org</code> qui
|
||
contient le script <code>letsencrypt</code>.</li>
|
||
<li>Un fichier d’installation de certificats dans
|
||
<code>letsencrypt/install-certs.sh</code> qui s’occupe d’installer les
|
||
certificats déjà générés.</li>
|
||
</ul>
|
||
<p>Et voila ! <a href="https://github.com/almet/infra/">Le tout est dans un dépot
|
||
github</a>, si jamais ça peut vous servir,
|
||
tant mieux !</p>
|
||
</article>
|
||
<footer>
|
||
<a id="feed" href="/feeds/all.atom.xml">
|
||
<img alt="RSS Logo" src="/theme/rss.svg" />
|
||
</a>
|
||
</footer>
|
||
</div>
|
||
</body>
|
||
</html> |