mirror of
https://github.com/almet/notmyidea.git
synced 2025-04-28 19:42:37 +02:00
264 lines
No EOL
15 KiB
HTML
264 lines
No EOL
15 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="en">
|
||
<head>
|
||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||
<meta http-equiv="content-type" content="text/html; charset=utf-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1">
|
||
<link rel="shortcut icon" type="image/x-icon" href="favicon.ico" />
|
||
|
||
<title>Let's Encrypt + HAProxy - Alexis - Carnets en ligne</title>
|
||
|
||
<meta charset="utf-8" />
|
||
<link href="https://blog.notmyidea.org/feeds/all.atom.xml" type="application/atom+xml" rel="alternate" title="Alexis - Carnets en ligne Full Atom Feed" />
|
||
<link rel="stylesheet" href="https://blog.notmyidea.org/theme/css/poole.css"/>
|
||
<link rel="stylesheet" href="https://blog.notmyidea.org/theme/css/syntax.css"/>
|
||
<link rel="stylesheet" href="https://blog.notmyidea.org/theme/css/lanyon.css"/>
|
||
<link rel="stylesheet" href="//fonts.googleapis.com/css?family=PT+Serif:400,400italic,700%7CPT+Sans:400">
|
||
<link rel="stylesheet" href="https://blog.notmyidea.org/theme/css/styles.css"/>
|
||
|
||
|
||
|
||
<style>
|
||
|
||
h1 {
|
||
font-family: "Avant Garde", Avantgarde, "Century Gothic", CenturyGothic, "AppleGothic", sans-serif;
|
||
padding: 80px 50px;
|
||
text-align: center;
|
||
text-transform: uppercase;
|
||
text-rendering: optimizeLegibility;
|
||
color: #202020;
|
||
letter-spacing: .1em;
|
||
text-shadow:
|
||
-1px -1px 1px #111,
|
||
2px 2px 1px #eaeaea;
|
||
}
|
||
|
||
#main {
|
||
text-align: justify;
|
||
text-justify: inter-word;
|
||
}
|
||
#main h1 {
|
||
padding: 10px;
|
||
}
|
||
|
||
.post-headline {
|
||
padding: 15px;
|
||
}
|
||
</style>
|
||
</head>
|
||
|
||
<body>
|
||
<!-- Target for toggling the sidebar `.sidebar-checkbox` is for regular
|
||
styles, `#sidebar-checkbox` for behavior. -->
|
||
<input type="checkbox" class="sidebar-checkbox" id="sidebar-checkbox">
|
||
<!-- Toggleable sidebar -->
|
||
<div class="sidebar" id="sidebar">
|
||
<div class="sidebar-item">
|
||
<div class="profile">
|
||
<img src="https://blog.notmyidea.org/theme/img/profile.png"/>
|
||
</div>
|
||
</div>
|
||
|
||
<nav class="sidebar-nav">
|
||
<a class="sidebar-nav-item" href="/">Articles</a>
|
||
|
||
<a class="sidebar-nav-item" href="https://www.vieuxsinge.com">Brasserie du Vieux Singe</a>
|
||
<a class="sidebar-nav-item" href="http://blog.notmyidea.org/pages/about.html">A propos</a>
|
||
<a class="sidebar-nav-item" href="https://twitter.com/ametaireau">Messages courts</a>
|
||
<a class="sidebar-nav-item" href="https://github.com/almet">Code</a>
|
||
</nav>
|
||
</div> <div class="wrap">
|
||
<div class="masthead">
|
||
<div class="container">
|
||
<h3 class="masthead-title">
|
||
<a href="https://blog.notmyidea.org/" title="Home">Alexis - Carnets en ligne</a>
|
||
</h3>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="container content">
|
||
<div id="main" class="posts">
|
||
<h1 class="post-title">Let's Encrypt + HAProxy</h1>
|
||
<span class="post-date">11 février 2016, dans <a class="no-color" href="category/technologie.html">Technologie</a></span>
|
||
<img id="illustration" src="" />
|
||
|
||
<div class="post article">
|
||
<h2 class="post-headline">Comment j'ai mis en place des certificats SSL avec Let's Encrypt derrière haproxy.</h2>
|
||
<div id="toc_container">
|
||
<div class="toc">
|
||
<ul>
|
||
<li><a href="#validation-des-domaines-par-lets-encrypt">Validation des domaines par Let's Encrypt</a></li>
|
||
<li><a href="#installation-des-certificats-dans-haproxy">Installation des certificats dans HAProxy</a></li>
|
||
<li><a href="#automatisation">Automatisation</a></li>
|
||
</ul>
|
||
</div>
|
||
|
||
</div>
|
||
<h1>🌟</h1>
|
||
<p><em>Note : Cet article n'est plus à jour. Il est maintenant (2018) possible d'installer des certificats SSL 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 HTTPS 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 SSL 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 SSL <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 SSL 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><span class="n">letsencrypt</span><span class="o">-</span><span class="n">auto</span> <span class="n">certonly</span> <span class="c1">--renew-by-default</span>
|
||
<span class="c1">--webroot -w /home/www/letsencrypt-requests/ \</span>
|
||
<span class="o">-</span><span class="n">d</span> <span class="n">hurl</span><span class="p">.</span><span class="n">kinto</span><span class="o">-</span><span class="k">storage</span><span class="p">.</span><span class="n">org</span> <span class="err">\</span>
|
||
<span class="o">-</span><span class="n">d</span> <span class="n">forums</span><span class="p">.</span><span class="n">kinto</span><span class="o">-</span><span class="k">storage</span><span class="p">.</span><span class="n">org</span>
|
||
</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 HTTP 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><span class="nv">frontend</span> <span class="nv">http</span>
|
||
<span class="nv">bind</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="nv">mode</span> <span class="nv">http</span>
|
||
<span class="nv">default_backend</span> <span class="nv">nginx_server</span>
|
||
|
||
<span class="nv">acl</span> <span class="nv">letsencrypt_check</span> <span class="nv">path_beg</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="nv">use_backend</span> <span class="nv">letsencrypt_backend</span> <span class="k">if</span> <span class="nv">letsencrypt_check</span>
|
||
|
||
<span class="nv">redirect</span> <span class="nv">scheme</span> <span class="nv">https</span> <span class="nv">code</span> <span class="mi">301</span> <span class="k">if</span> <span class="o">!</span>{ <span class="nv">ssl_fc</span> } <span class="o">!</span><span class="nv">letsencrypt_check</span>
|
||
|
||
<span class="nv">backend</span> <span class="nv">letsencrypt_backend</span>
|
||
<span class="nv">http</span><span class="o">-</span><span class="nv">request</span> <span class="nv">set</span><span class="o">-</span><span class="nv">header</span> <span class="nv">Host</span> <span class="nv">letsencrypt</span>.<span class="nv">requests</span>
|
||
<span class="nv">dispatch</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>
|
||
</pre></div>
|
||
|
||
|
||
<p>Et celle de NGINX:</p>
|
||
<div class="highlight"><pre><span></span><span class="n">server</span> <span class="err">{</span>
|
||
<span class="k">listen</span> <span class="mi">8000</span><span class="p">;</span>
|
||
<span class="k">server_name</span> <span class="n">letsencrypt</span><span class="p">.</span><span class="n">requests</span><span class="p">;</span>
|
||
<span class="n">root</span> <span class="o">/</span><span class="n">home</span><span class="o">/</span><span class="n">www</span><span class="o">/</span><span class="n">letsencrypt</span><span class="o">-</span><span class="n">requests</span><span class="p">;</span>
|
||
<span class="err">}</span>
|
||
</pre></div>
|
||
|
||
|
||
<h2 id="installation-des-certificats-dans-haproxy">Installation des certificats dans HAProxy</h2>
|
||
<p>Vos certificats SSL 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><span class="n">cat</span> <span class="o">/</span><span class="n">etc</span><span class="o">/</span><span class="n">letsencrypt</span><span class="o">/</span><span class="n">live</span><span class="o">/</span><span class="n">domaine</span><span class="p">.</span><span class="n">org</span><span class="o">/</span><span class="n">privkey</span><span class="p">.</span><span class="n">pem</span> <span class="o">/</span><span class="n">etc</span><span class="o">/</span><span class="n">letsencrypt</span><span class="o">/</span><span class="n">live</span><span class="o">/</span><span class="n">domaine</span><span class="p">.</span><span class="n">org</span><span class="o">/</span><span class="n">fullchain</span><span class="p">.</span><span class="n">pem</span> <span class="o">></span> <span class="o">/</span><span class="n">etc</span><span class="o">/</span><span class="n">ssl</span><span class="o">/</span><span class="n">letsencrypt</span><span class="o">/</span><span class="n">domaine</span><span class="p">.</span><span class="n">org</span><span class="p">.</span><span class="n">pem</span>
|
||
</pre></div>
|
||
|
||
|
||
<p>Et ensuite dans la configuration de haproxy, pour le (nouveau)
|
||
<em>frontend</em> https:</p>
|
||
<div class="highlight"><pre><span></span><span class="n">bind</span> <span class="mi">0</span><span class="p">.</span><span class="mi">0</span><span class="p">.</span><span class="mi">0</span><span class="p">.</span><span class="mi">0</span><span class="p">:</span><span class="mi">443</span> <span class="n">ssl</span> <span class="k">no</span><span class="o">-</span><span class="n">sslv3</span> <span class="n">crt</span> <span class="o">/</span><span class="n">etc</span><span class="o">/</span><span class="n">ssl</span><span class="o">/</span><span class="n">letsencrypt</span>
|
||
</pre></div>
|
||
|
||
|
||
<p>Faites bien attention à avoir un <em>frontend</em> https pour tous vos sites en
|
||
HTTPS. <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>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<label for="sidebar-checkbox" class="sidebar-toggle"></label>
|
||
|
||
<script>
|
||
(function(document) {
|
||
var i = 0;
|
||
// snip empty header rows since markdown can't
|
||
var rows = document.querySelectorAll('tr');
|
||
for(i=0; i<rows.length; i++) {
|
||
var ths = rows[i].querySelectorAll('th');
|
||
var rowlen = rows[i].children.length;
|
||
if (ths.length > 0 && ths.length === rowlen) {
|
||
rows[i].remove();
|
||
}
|
||
}
|
||
})(document);
|
||
</script>
|
||
|
||
<script>
|
||
/* Lanyon & Poole are Copyright (c) 2014 Mark Otto. Adapted to Pelican 20141223 and extended a bit by @thomaswilley */
|
||
(function(document) {
|
||
var toggle = document.querySelector('.sidebar-toggle');
|
||
var sidebar = document.querySelector('#sidebar');
|
||
var checkbox = document.querySelector('#sidebar-checkbox');
|
||
document.addEventListener('click', function(e) {
|
||
var target = e.target;
|
||
if(!checkbox.checked ||
|
||
sidebar.contains(target) ||
|
||
(target === checkbox || target === toggle)) return;
|
||
checkbox.checked = false;
|
||
}, false);
|
||
})(document);
|
||
</script>
|
||
<!-- Piwik -->
|
||
<script type="text/javascript">
|
||
var _paq = _paq || [];
|
||
_paq.push(['trackPageView']);
|
||
_paq.push(['enableLinkTracking']);
|
||
(function() {
|
||
var u="//tracker.notmyidea.org/";
|
||
_paq.push(['setTrackerUrl', u+'piwik.php']);
|
||
_paq.push(['setSiteId', 3]);
|
||
var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0];
|
||
g.type='text/javascript'; g.async=true; g.defer=true; g.src=u+'piwik.js'; s.parentNode.insertBefore(g,s);
|
||
})();
|
||
</script>
|
||
<noscript><p><img src="//tracker.notmyidea.org/piwik.php?idsite=3" style="border:0;" alt="" /></p></noscript>
|
||
<!-- End Piwik Code -->
|
||
</div>
|
||
</body>
|
||
</html> |