<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Caddy on Clément Joly – Open-Source, Rust &amp; SQLite</title><link>https://joly.pw/tags/caddy/</link><description>Recent content in Caddy on Clément Joly – Open-Source, Rust &amp; SQLite</description><image><title>Clément Joly – Open-Source, Rust &amp; SQLite</title><url>https://joly.pw/images/open-graph-home-original.png</url><link>https://joly.pw/images/open-graph-home-original.png</link></image><generator>Hugo -- 0.154.3</generator><language>en</language><copyright>Clément Joly</copyright><lastBuildDate>Wed, 11 Mar 2026 03:32:38 +0000</lastBuildDate><atom:link href="https://joly.pw/tags/caddy/index.xml" rel="self" type="application/rss+xml"/><item><title>6-day Certificates With Let’s Encrypt and Caddy</title><link>https://joly.pw/blog/6days/</link><pubDate>Sat, 17 Jan 2026 13:36:24 +0000</pubDate><guid>https://joly.pw/blog/6days/</guid><description>First impressions</description><content:encoded><![CDATA[



  
  
  
  

  <div class="alert alert-comment">
    <p class="alert-heading">
      💬
      
        This is a comment on
      
    </p>
    <p><a href="https://letsencrypt.org/2026/01/15/6day-and-ip-general-availability.html">6-day and IP Address Certificates are Generally Available</a> by Matthew McPherrin (<a href="https://lobste.rs/s/boyarm/6_day_ip_address_certificates_are">via</a>)</p>
  </div>



<p>Let’s Encrypt has just announced that short-lived<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup> certificates are generally available.
They can also be used for IP addresses, which is especially useful for <a href="https://en.wikipedia.org/wiki/DNS_over_HTTPS">DNS over HTTPS</a>.
Those certificates <em>could</em> be smaller in the future, if information for validity checks is omitted.
However, for now at least, these certificates still <a href="https://letsencrypt.org/docs/profiles/#shortlived">include revocation information</a>.</p>
<h2 id="using-those-new-certificates-with-caddy">Using Those New Certificates With Caddy</h2>
<p>I wanted to give those certificates a try with Caddy.
Caddy needs to use the <a href="https://letsencrypt.org/docs/profiles/#shortlived"><code>shortlived</code></a> Let’s Encrypt profile.
The profile feature isn’t explicitly mentioned in the <a href="https://caddyserver.com/docs/caddyfile/directives/tls#issuers">docs</a>, but some <a href="https://caddy.community/t/using-setting-acme-profiles-as-of-2-10/31006">community posts</a> use a <code>profile</code> directive.
This also works in the global configuration:</p>
<div class="highlight"><pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-Caddy" data-lang="Caddy"><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#c678dd">cert_issuer</span> <span style="color:#98c379">acme</span> {
</span></span><span style="display:flex;"><span>		<span style="color:#c678dd">profile</span> <span style="color:#98c379">shortlived</span>
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Reloading the Caddy configuration was not enough to prompt an early renewal, so I deleted the underlying certificate files and restarted Caddy:</p>
<div class="highlight"><pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>sudo rm -rf /var/lib/caddy/.local/share/caddy/certificates/acme-v02.api.letsencrypt.org-directory/example.com
</span></span><span style="display:flex;"><span>sudo systemctl restart caddy
</span></span></code></pre></div><p>And I got a brand new certificate for my domain name, valid only for a few days. It’s marginally smaller<sup id="fnref:2"><a href="#fn:2" class="footnote-ref" role="doc-noteref">2</a></sup> than with the <code>classic</code> profile, mostly because these short-lived certificates also use the <a href="https://letsencrypt.org/2025/11/24/gen-y-hierarchy">new generation hierarchy</a>. But they should be roughly the same size as the <code>tlsserver</code> profile.</p>




  
  
  
  

  <div class="alert alert-note">
    <p class="alert-heading">
      ℹ️
      
        Note
      
    </p>
    <p><a href="https://github.com/caddyserver/caddy/issues/7399">Certificates against IPv6 addresses</a> (i.e. not against a domain using IPv6) seem to require an unreleased version of Caddy.</p>
  </div>



<h2 id="conclusion">Conclusion</h2>
<p>With Caddy, certificate renewal should be automated enough that short-lived certificates don’t cause any problems.
But I’ll see with this experiment if there are any surprising pain points.</p>
<p>My understanding is that browsers only cache TLS sessions, not certificates: when a full handshake is performed, the full certificate chain is then sent anyway<sup id="fnref:3"><a href="#fn:3" class="footnote-ref" role="doc-noteref">3</a></sup>.
So even if the certificate expires more frequently, it is not sent more often.
The slightly smaller certificate chain is thus a small net benefit.</p>
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p>The certificates are valid for about 6 days and precisely 160 hours. 160 is the sum of the eleven first prime numbers (2+3+5+7+11+13+17+19+23+29+31) and of the cube of the first three. How cool is that!&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:2">
<p>Comparing the .pem files as a proxy, 1.2k vs 1.3k for the bare certificate, 4.0k vs 4.8k for the whole chain&#160;<a href="#fnref:2" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:3">
<p>According to <a href="https://stackoverflow.com/a/52610552">this StackOverflow answer</a> and <a href="https://www.cloudflare.com/learning/ssl/what-happens-in-a-tls-handshake/">this Cloudflare explanation</a>&#160;<a href="#fnref:3" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>
]]></content:encoded></item><item><title>Let's Encrypt CAA Records with Caddy</title><link>https://joly.pw/blog/lets-encrypt-caa-records-with-caddy/</link><pubDate>Tue, 25 Feb 2025 19:42:01 +0000</pubDate><guid>https://joly.pw/blog/lets-encrypt-caa-records-with-caddy/</guid><description>Limiting certificate issuance to a server that possesses a particular private key</description><content:encoded><![CDATA[<h2 id="a-man-in-the-middle-attack">A Man-in-the-Middle Attack</h2>
<p>I host my own instance of <a href="https://miniflux.app/">miniflux</a>, an RSS reader.
I do it as a hobby, I enjoy the learning opportunities that come along the way.</p>
<p>One such opportunity presented itself in November 2023.</p>
<p>Back then, a Man-in-the-Middle attack was <a href="https://notes.valdikss.org.ru/jabber.ru-mitm">reported against jabber.ru</a>.
You can go read the full details on that blog post, but let’s go over its main aspects.
Without the attacker, a client connects directly to the <code>jabber.ru</code> server over TLS:</p>



<div class="goat svg-container ">
  
    <svg
      xmlns="http://www.w3.org/2000/svg"
      font-family="Menlo,Lucida Console,monospace"
      
        viewBox="0 0 648 73"
      >
      <g transform='translate(8,16)'>
<path d='M 16,16 L 96,16' fill='none' stroke='currentColor'></path>
<path d='M 480,16 L 632,16' fill='none' stroke='currentColor'></path>
<path d='M 112,32 L 472,32' fill='none' stroke='currentColor'></path>
<path d='M 16,48 L 96,48' fill='none' stroke='currentColor'></path>
<path d='M 480,48 L 632,48' fill='none' stroke='currentColor'></path>
<path d='M 480,16 L 480,32' fill='none' stroke='currentColor'></path>
<path d='M 480,32 L 480,48' fill='none' stroke='currentColor'></path>
<path d='M 632,16 L 632,48' fill='none' stroke='currentColor'></path>
<polygon points='480.000000,32.000000 468.000000,26.400000 468.000000,37.599998' fill='currentColor' transform='rotate(0.000000, 472.000000, 32.000000)'></polygon>
<path d='M 16,16 A 16,16 0 0,0 0,32' fill='none' stroke='currentColor'></path>
<path d='M 96,16 A 16,16 0 0,1 112,32' fill='none' stroke='currentColor'></path>
<path d='M 0,32 A 16,16 0 0,0 16,48' fill='none' stroke='currentColor'></path>
<path d='M 112,32 A 16,16 0 0,1 96,48' fill='none' stroke='currentColor'></path>
<text text-anchor='middle' x='16' y='36' fill='currentColor' style='font-size:1em'>X</text>
<text text-anchor='middle' x='24' y='36' fill='currentColor' style='font-size:1em'>M</text>
<text text-anchor='middle' x='32' y='36' fill='currentColor' style='font-size:1em'>P</text>
<text text-anchor='middle' x='40' y='36' fill='currentColor' style='font-size:1em'>P</text>
<text text-anchor='middle' x='56' y='36' fill='currentColor' style='font-size:1em'>c</text>
<text text-anchor='middle' x='64' y='36' fill='currentColor' style='font-size:1em'>l</text>
<text text-anchor='middle' x='72' y='36' fill='currentColor' style='font-size:1em'>i</text>
<text text-anchor='middle' x='80' y='36' fill='currentColor' style='font-size:1em'>e</text>
<text text-anchor='middle' x='88' y='36' fill='currentColor' style='font-size:1em'>n</text>
<text text-anchor='middle' x='96' y='36' fill='currentColor' style='font-size:1em'>t</text>
<text text-anchor='middle' x='248' y='20' fill='currentColor' style='font-size:1em'>c</text>
<text text-anchor='middle' x='256' y='20' fill='currentColor' style='font-size:1em'>o</text>
<text text-anchor='middle' x='264' y='20' fill='currentColor' style='font-size:1em'>n</text>
<text text-anchor='middle' x='272' y='4' fill='currentColor' style='font-size:1em'>T</text>
<text text-anchor='middle' x='272' y='20' fill='currentColor' style='font-size:1em'>n</text>
<text text-anchor='middle' x='280' y='4' fill='currentColor' style='font-size:1em'>L</text>
<text text-anchor='middle' x='280' y='20' fill='currentColor' style='font-size:1em'>e</text>
<text text-anchor='middle' x='288' y='4' fill='currentColor' style='font-size:1em'>S</text>
<text text-anchor='middle' x='288' y='20' fill='currentColor' style='font-size:1em'>c</text>
<text text-anchor='middle' x='296' y='20' fill='currentColor' style='font-size:1em'>t</text>
<text text-anchor='middle' x='304' y='20' fill='currentColor' style='font-size:1em'>i</text>
<text text-anchor='middle' x='312' y='20' fill='currentColor' style='font-size:1em'>o</text>
<text text-anchor='middle' x='320' y='20' fill='currentColor' style='font-size:1em'>n</text>
<text text-anchor='middle' x='496' y='36' fill='currentColor' style='font-size:1em'>j</text>
<text text-anchor='middle' x='504' y='36' fill='currentColor' style='font-size:1em'>a</text>
<text text-anchor='middle' x='512' y='36' fill='currentColor' style='font-size:1em'>b</text>
<text text-anchor='middle' x='520' y='36' fill='currentColor' style='font-size:1em'>b</text>
<text text-anchor='middle' x='528' y='36' fill='currentColor' style='font-size:1em'>e</text>
<text text-anchor='middle' x='536' y='36' fill='currentColor' style='font-size:1em'>r</text>
<text text-anchor='middle' x='544' y='36' fill='currentColor' style='font-size:1em'>.</text>
<text text-anchor='middle' x='552' y='36' fill='currentColor' style='font-size:1em'>r</text>
<text text-anchor='middle' x='560' y='36' fill='currentColor' style='font-size:1em'>u</text>
<text text-anchor='middle' x='576' y='36' fill='currentColor' style='font-size:1em'>s</text>
<text text-anchor='middle' x='584' y='36' fill='currentColor' style='font-size:1em'>e</text>
<text text-anchor='middle' x='592' y='36' fill='currentColor' style='font-size:1em'>r</text>
<text text-anchor='middle' x='600' y='36' fill='currentColor' style='font-size:1em'>v</text>
<text text-anchor='middle' x='608' y='36' fill='currentColor' style='font-size:1em'>e</text>
<text text-anchor='middle' x='616' y='36' fill='currentColor' style='font-size:1em'>r</text>
</g>

    </svg>
  
</div>
<p>TLS encrypts the connection.
A certificate is also presented when the connection is established, to ensure authenticity and integrity.
For this to work, the Certificate Authority (CA), a trusted third party, signs the certificate.
In doing so, it affirms that it saw a given certificate associated with a particular domain<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup>.
This protects against some <a href="https://en.wikipedia.org/wiki/Man-in-the-middle_attack">Man-in-the-Middle attacks</a>, where an attacker inserts itself between a client (say on a public wifi network) and the website, as in the next diagram.
If that attacker does not manage to similarly be between the CA and the website, then it will be unable to decrypt or alter the exchange without being detected, because it can’t present a certificate signed by the CA.</p>
<p>Nonetheless in November 2023, a Man-in-the-Middle attack against <code>jabber.ru</code> succeeded.
In that instance, the attacker leveraged a privileged position on the network.
They intercepted all TLS traffic to the victim’s server, then tricked<sup id="fnref:2"><a href="#fn:2" class="footnote-ref" role="doc-noteref">2</a></sup> the <a href="https://letsencrypt.org/">Let’s Encrypt</a> CA into issuing a certificate for the attacker server.
Then, they could decrypt the traffic from the client, re-encrypt it, potentially alter it and send it to the server.</p>



<div class="goat svg-container ">
  
    <svg
      xmlns="http://www.w3.org/2000/svg"
      font-family="Menlo,Lucida Console,monospace"
      
        viewBox="0 0 648 73"
      >
      <g transform='translate(8,16)'>
<path d='M 16,16 L 96,16' fill='none' stroke='currentColor'></path>
<path d='M 224,16 L 368,16' fill='none' stroke='currentColor'></path>
<path d='M 480,16 L 632,16' fill='none' stroke='currentColor'></path>
<path d='M 112,32 L 216,32' fill='none' stroke='currentColor'></path>
<path d='M 368,32 L 472,32' fill='none' stroke='currentColor'></path>
<path d='M 16,48 L 96,48' fill='none' stroke='currentColor'></path>
<path d='M 224,48 L 368,48' fill='none' stroke='currentColor'></path>
<path d='M 480,48 L 632,48' fill='none' stroke='currentColor'></path>
<path d='M 224,16 L 224,32' fill='none' stroke='currentColor'></path>
<path d='M 224,32 L 224,48' fill='none' stroke='currentColor'></path>
<path d='M 368,16 L 368,32' fill='none' stroke='currentColor'></path>
<path d='M 368,32 L 368,48' fill='none' stroke='currentColor'></path>
<path d='M 480,16 L 480,32' fill='none' stroke='currentColor'></path>
<path d='M 480,32 L 480,48' fill='none' stroke='currentColor'></path>
<path d='M 632,16 L 632,48' fill='none' stroke='currentColor'></path>
<polygon points='224.000000,32.000000 212.000000,26.400000 212.000000,37.599998' fill='currentColor' transform='rotate(0.000000, 216.000000, 32.000000)'></polygon>
<polygon points='480.000000,32.000000 468.000000,26.400000 468.000000,37.599998' fill='currentColor' transform='rotate(0.000000, 472.000000, 32.000000)'></polygon>
<path d='M 16,16 A 16,16 0 0,0 0,32' fill='none' stroke='currentColor'></path>
<path d='M 96,16 A 16,16 0 0,1 112,32' fill='none' stroke='currentColor'></path>
<path d='M 0,32 A 16,16 0 0,0 16,48' fill='none' stroke='currentColor'></path>
<path d='M 112,32 A 16,16 0 0,1 96,48' fill='none' stroke='currentColor'></path>
<text text-anchor='middle' x='16' y='36' fill='currentColor' style='font-size:1em'>X</text>
<text text-anchor='middle' x='24' y='36' fill='currentColor' style='font-size:1em'>M</text>
<text text-anchor='middle' x='32' y='36' fill='currentColor' style='font-size:1em'>P</text>
<text text-anchor='middle' x='40' y='36' fill='currentColor' style='font-size:1em'>P</text>
<text text-anchor='middle' x='56' y='36' fill='currentColor' style='font-size:1em'>c</text>
<text text-anchor='middle' x='64' y='36' fill='currentColor' style='font-size:1em'>l</text>
<text text-anchor='middle' x='72' y='36' fill='currentColor' style='font-size:1em'>i</text>
<text text-anchor='middle' x='80' y='36' fill='currentColor' style='font-size:1em'>e</text>
<text text-anchor='middle' x='88' y='36' fill='currentColor' style='font-size:1em'>n</text>
<text text-anchor='middle' x='96' y='36' fill='currentColor' style='font-size:1em'>t</text>
<text text-anchor='middle' x='128' y='20' fill='currentColor' style='font-size:1em'>c</text>
<text text-anchor='middle' x='136' y='20' fill='currentColor' style='font-size:1em'>o</text>
<text text-anchor='middle' x='144' y='20' fill='currentColor' style='font-size:1em'>n</text>
<text text-anchor='middle' x='152' y='4' fill='currentColor' style='font-size:1em'>T</text>
<text text-anchor='middle' x='152' y='20' fill='currentColor' style='font-size:1em'>n</text>
<text text-anchor='middle' x='160' y='4' fill='currentColor' style='font-size:1em'>L</text>
<text text-anchor='middle' x='160' y='20' fill='currentColor' style='font-size:1em'>e</text>
<text text-anchor='middle' x='168' y='4' fill='currentColor' style='font-size:1em'>S</text>
<text text-anchor='middle' x='168' y='20' fill='currentColor' style='font-size:1em'>c</text>
<text text-anchor='middle' x='176' y='20' fill='currentColor' style='font-size:1em'>t</text>
<text text-anchor='middle' x='184' y='20' fill='currentColor' style='font-size:1em'>i</text>
<text text-anchor='middle' x='192' y='20' fill='currentColor' style='font-size:1em'>o</text>
<text text-anchor='middle' x='200' y='20' fill='currentColor' style='font-size:1em'>n</text>
<text text-anchor='middle' x='240' y='36' fill='currentColor' style='font-size:1em'>a</text>
<text text-anchor='middle' x='248' y='36' fill='currentColor' style='font-size:1em'>t</text>
<text text-anchor='middle' x='256' y='36' fill='currentColor' style='font-size:1em'>t</text>
<text text-anchor='middle' x='264' y='36' fill='currentColor' style='font-size:1em'>a</text>
<text text-anchor='middle' x='272' y='36' fill='currentColor' style='font-size:1em'>c</text>
<text text-anchor='middle' x='280' y='36' fill='currentColor' style='font-size:1em'>k</text>
<text text-anchor='middle' x='288' y='36' fill='currentColor' style='font-size:1em'>e</text>
<text text-anchor='middle' x='296' y='36' fill='currentColor' style='font-size:1em'>r</text>
<text text-anchor='middle' x='312' y='36' fill='currentColor' style='font-size:1em'>s</text>
<text text-anchor='middle' x='320' y='36' fill='currentColor' style='font-size:1em'>e</text>
<text text-anchor='middle' x='328' y='36' fill='currentColor' style='font-size:1em'>r</text>
<text text-anchor='middle' x='336' y='36' fill='currentColor' style='font-size:1em'>v</text>
<text text-anchor='middle' x='344' y='36' fill='currentColor' style='font-size:1em'>e</text>
<text text-anchor='middle' x='352' y='36' fill='currentColor' style='font-size:1em'>r</text>
<text text-anchor='middle' x='384' y='20' fill='currentColor' style='font-size:1em'>c</text>
<text text-anchor='middle' x='392' y='4' fill='currentColor' style='font-size:1em'>n</text>
<text text-anchor='middle' x='392' y='20' fill='currentColor' style='font-size:1em'>o</text>
<text text-anchor='middle' x='400' y='4' fill='currentColor' style='font-size:1em'>e</text>
<text text-anchor='middle' x='400' y='20' fill='currentColor' style='font-size:1em'>n</text>
<text text-anchor='middle' x='408' y='4' fill='currentColor' style='font-size:1em'>w</text>
<text text-anchor='middle' x='408' y='20' fill='currentColor' style='font-size:1em'>n</text>
<text text-anchor='middle' x='416' y='20' fill='currentColor' style='font-size:1em'>e</text>
<text text-anchor='middle' x='424' y='4' fill='currentColor' style='font-size:1em'>T</text>
<text text-anchor='middle' x='424' y='20' fill='currentColor' style='font-size:1em'>c</text>
<text text-anchor='middle' x='432' y='4' fill='currentColor' style='font-size:1em'>L</text>
<text text-anchor='middle' x='432' y='20' fill='currentColor' style='font-size:1em'>t</text>
<text text-anchor='middle' x='440' y='4' fill='currentColor' style='font-size:1em'>S</text>
<text text-anchor='middle' x='440' y='20' fill='currentColor' style='font-size:1em'>i</text>
<text text-anchor='middle' x='448' y='20' fill='currentColor' style='font-size:1em'>o</text>
<text text-anchor='middle' x='456' y='20' fill='currentColor' style='font-size:1em'>n</text>
<text text-anchor='middle' x='496' y='36' fill='currentColor' style='font-size:1em'>j</text>
<text text-anchor='middle' x='504' y='36' fill='currentColor' style='font-size:1em'>a</text>
<text text-anchor='middle' x='512' y='36' fill='currentColor' style='font-size:1em'>b</text>
<text text-anchor='middle' x='520' y='36' fill='currentColor' style='font-size:1em'>b</text>
<text text-anchor='middle' x='528' y='36' fill='currentColor' style='font-size:1em'>e</text>
<text text-anchor='middle' x='536' y='36' fill='currentColor' style='font-size:1em'>r</text>
<text text-anchor='middle' x='544' y='36' fill='currentColor' style='font-size:1em'>.</text>
<text text-anchor='middle' x='552' y='36' fill='currentColor' style='font-size:1em'>r</text>
<text text-anchor='middle' x='560' y='36' fill='currentColor' style='font-size:1em'>u</text>
<text text-anchor='middle' x='576' y='36' fill='currentColor' style='font-size:1em'>s</text>
<text text-anchor='middle' x='584' y='36' fill='currentColor' style='font-size:1em'>e</text>
<text text-anchor='middle' x='592' y='36' fill='currentColor' style='font-size:1em'>r</text>
<text text-anchor='middle' x='600' y='36' fill='currentColor' style='font-size:1em'>v</text>
<text text-anchor='middle' x='608' y='36' fill='currentColor' style='font-size:1em'>e</text>
<text text-anchor='middle' x='616' y='36' fill='currentColor' style='font-size:1em'>r</text>
</g>

    </svg>
  
</div>
<p>There was no need to compromise the server for this attack to work.
It simply leveraged a privileged network position.</p>
<p>In a <a href="https://www.devever.net/~hl/xmpp-incident#narrow">reply on his blog</a>, ACME developer Hugo Landau points out the following mitigation:</p>




  <figure>
    <blockquote cite="https://www.devever.net/~hl/xmpp-incident#narrow">
      <p><strong>Mitigation.</strong> The second area of consideration is mitigation, in which the unauthorized issuance of TLS certificates is prevented from happening in the first place. The entire point of a TLS certificate is, of course, to prevent a man-in-the-middle attack. The fundamental problem here is that the “Domain Validation” model by which CAs validate control of a domain name is ironically itself vulnerable to man-in-the-middle attacks, especially if an attacker can intercept not just some but <em>all</em> traffic to a victim site (as happened in this case).</p>
<p>Some years ago I authored <a href="https://www.rfc-editor.org/rfc/rfc8657">ACME-CAA (RFC 8657)</a>, now <a href="https://www.devever.net/~hl/acme-caa-live">implemented</a> by Let&rsquo;s Encrypt, which can mitigate this in some circumstances. The basic idea is that you can configure a DNS record which specifies that only a <em>specific account</em> of a <em>specific CA</em> is authorised to issue certificates for a domain. Thus simply using the same CA isn&rsquo;t enough; you must gain access to the same account at the CA. With Let&rsquo;s Encrypt, this means gaining access to the ACME private key used to request a certificate. Based on what we know about the attack, it would have been prevented by deploying this extension.</p>

    </blockquote>
    
      <figcaption class="blockquote-caption">
        
          <cite style="text-align: right"><a href="https://www.devever.net/~hl/xmpp-incident#narrow">https://www.devever.net/~hl/xmpp-incident#narrow</a></cite>
          <br/>
        
        
    <p>
          This is just one mitigation strategy and it has caveats. I encourage you to go read the rest of the post, where Hugo also explain how to detect the attack.
    </p>
        
      </figcaption>
    
  </figure>



<p>This got me thinking: how would I implement this mitigation for my self-hosted services?
In this post, we will use the <code>CAA</code> DNS record to limit issuance to one particular account registered at one particular CA, as suggested above.</p>
<h2 id="the-setup">The Setup</h2>
<h3 id="tls-proxy">TLS Proxy</h3>
<p>My setup looks like this:</p>



<div class="goat svg-container ">
  
    <svg
      xmlns="http://www.w3.org/2000/svg"
      font-family="Menlo,Lucida Console,monospace"
      
        viewBox="0 0 616 153"
      >
      <g transform='translate(8,16)'>
<path d='M 224,0 L 600,0' fill='none' stroke='currentColor'></path>
<path d='M 248,32 L 368,32' fill='none' stroke='currentColor'></path>
<path d='M 464,32 L 552,32' fill='none' stroke='currentColor'></path>
<path d='M 16,48 L 96,48' fill='none' stroke='currentColor'></path>
<path d='M 368,48 L 456,48' fill='none' stroke='currentColor'></path>
<path d='M 112,64 L 240,64' fill='none' stroke='currentColor'></path>
<path d='M 464,64 L 552,64' fill='none' stroke='currentColor'></path>
<path d='M 16,80 L 96,80' fill='none' stroke='currentColor'></path>
<path d='M 368,80 L 432,80' fill='none' stroke='currentColor'></path>
<path d='M 248,96 L 368,96' fill='none' stroke='currentColor'></path>
<path d='M 224,128 L 600,128' fill='none' stroke='currentColor'></path>
<path d='M 224,0 L 224,48' fill='none' stroke='currentColor'></path>
<path d='M 224,80 L 224,128' fill='none' stroke='currentColor'></path>
<path d='M 248,32 L 248,64' fill='none' stroke='currentColor'></path>
<path d='M 248,64 L 248,96' fill='none' stroke='currentColor'></path>
<path d='M 368,32 L 368,48' fill='none' stroke='currentColor'></path>
<path d='M 368,48 L 368,80' fill='none' stroke='currentColor'></path>
<path d='M 368,80 L 368,96' fill='none' stroke='currentColor'></path>
<path d='M 464,32 L 464,48' fill='none' stroke='currentColor'></path>
<path d='M 464,48 L 464,64' fill='none' stroke='currentColor'></path>
<path d='M 552,32 L 552,64' fill='none' stroke='currentColor'></path>
<path d='M 600,0 L 600,128' fill='none' stroke='currentColor'></path>
<path d='M 224,48 L 224,56' fill='none' stroke='currentColor'></path>
<path d='M 224,72 L 224,80' fill='none' stroke='currentColor'></path>
<polygon points='248.000000,64.000000 236.000000,58.400002 236.000000,69.599998' fill='currentColor' transform='rotate(0.000000, 240.000000, 64.000000)'></polygon>
<polygon points='440.000000,80.000000 428.000000,74.400002 428.000000,85.599998' fill='currentColor' transform='rotate(0.000000, 432.000000, 80.000000)'></polygon>
<polygon points='464.000000,48.000000 452.000000,42.400002 452.000000,53.599998' fill='currentColor' transform='rotate(0.000000, 456.000000, 48.000000)'></polygon>
<path d='M 16,48 A 16,16 0 0,0 0,64' fill='none' stroke='currentColor'></path>
<path d='M 96,48 A 16,16 0 0,1 112,64' fill='none' stroke='currentColor'></path>
<path d='M 0,64 A 16,16 0 0,0 16,80' fill='none' stroke='currentColor'></path>
<path d='M 112,64 A 16,16 0 0,1 96,80' fill='none' stroke='currentColor'></path>
<text text-anchor='middle' x='16' y='68' fill='currentColor' style='font-size:1em'>W</text>
<text text-anchor='middle' x='24' y='68' fill='currentColor' style='font-size:1em'>e</text>
<text text-anchor='middle' x='32' y='68' fill='currentColor' style='font-size:1em'>b</text>
<text text-anchor='middle' x='48' y='68' fill='currentColor' style='font-size:1em'>b</text>
<text text-anchor='middle' x='56' y='68' fill='currentColor' style='font-size:1em'>r</text>
<text text-anchor='middle' x='64' y='68' fill='currentColor' style='font-size:1em'>o</text>
<text text-anchor='middle' x='72' y='68' fill='currentColor' style='font-size:1em'>w</text>
<text text-anchor='middle' x='80' y='68' fill='currentColor' style='font-size:1em'>s</text>
<text text-anchor='middle' x='88' y='68' fill='currentColor' style='font-size:1em'>e</text>
<text text-anchor='middle' x='96' y='68' fill='currentColor' style='font-size:1em'>r</text>
<text text-anchor='middle' x='136' y='52' fill='currentColor' style='font-size:1em'>c</text>
<text text-anchor='middle' x='144' y='52' fill='currentColor' style='font-size:1em'>o</text>
<text text-anchor='middle' x='152' y='36' fill='currentColor' style='font-size:1em'>T</text>
<text text-anchor='middle' x='152' y='52' fill='currentColor' style='font-size:1em'>n</text>
<text text-anchor='middle' x='160' y='36' fill='currentColor' style='font-size:1em'>L</text>
<text text-anchor='middle' x='160' y='52' fill='currentColor' style='font-size:1em'>n</text>
<text text-anchor='middle' x='168' y='36' fill='currentColor' style='font-size:1em'>S</text>
<text text-anchor='middle' x='168' y='52' fill='currentColor' style='font-size:1em'>e</text>
<text text-anchor='middle' x='176' y='52' fill='currentColor' style='font-size:1em'>c</text>
<text text-anchor='middle' x='184' y='52' fill='currentColor' style='font-size:1em'>t</text>
<text text-anchor='middle' x='192' y='52' fill='currentColor' style='font-size:1em'>i</text>
<text text-anchor='middle' x='200' y='52' fill='currentColor' style='font-size:1em'>o</text>
<text text-anchor='middle' x='208' y='52' fill='currentColor' style='font-size:1em'>n</text>
<text text-anchor='middle' x='264' y='68' fill='currentColor' style='font-size:1em'>c</text>
<text text-anchor='middle' x='272' y='68' fill='currentColor' style='font-size:1em'>a</text>
<text text-anchor='middle' x='280' y='68' fill='currentColor' style='font-size:1em'>d</text>
<text text-anchor='middle' x='288' y='68' fill='currentColor' style='font-size:1em'>d</text>
<text text-anchor='middle' x='288' y='116' fill='currentColor' style='font-size:1em'>r</text>
<text text-anchor='middle' x='296' y='68' fill='currentColor' style='font-size:1em'>y</text>
<text text-anchor='middle' x='296' y='116' fill='currentColor' style='font-size:1em'>e</text>
<text text-anchor='middle' x='304' y='116' fill='currentColor' style='font-size:1em'>m</text>
<text text-anchor='middle' x='312' y='68' fill='currentColor' style='font-size:1em'>s</text>
<text text-anchor='middle' x='312' y='116' fill='currentColor' style='font-size:1em'>o</text>
<text text-anchor='middle' x='320' y='68' fill='currentColor' style='font-size:1em'>e</text>
<text text-anchor='middle' x='320' y='116' fill='currentColor' style='font-size:1em'>t</text>
<text text-anchor='middle' x='328' y='68' fill='currentColor' style='font-size:1em'>r</text>
<text text-anchor='middle' x='328' y='116' fill='currentColor' style='font-size:1em'>e</text>
<text text-anchor='middle' x='336' y='68' fill='currentColor' style='font-size:1em'>v</text>
<text text-anchor='middle' x='344' y='68' fill='currentColor' style='font-size:1em'>e</text>
<text text-anchor='middle' x='344' y='116' fill='currentColor' style='font-size:1em'>s</text>
<text text-anchor='middle' x='352' y='68' fill='currentColor' style='font-size:1em'>r</text>
<text text-anchor='middle' x='352' y='116' fill='currentColor' style='font-size:1em'>e</text>
<text text-anchor='middle' x='360' y='116' fill='currentColor' style='font-size:1em'>r</text>
<text text-anchor='middle' x='368' y='116' fill='currentColor' style='font-size:1em'>v</text>
<text text-anchor='middle' x='376' y='116' fill='currentColor' style='font-size:1em'>e</text>
<text text-anchor='middle' x='384' y='116' fill='currentColor' style='font-size:1em'>r</text>
<text text-anchor='middle' x='400' y='36' fill='currentColor' style='font-size:1em'>s</text>
<text text-anchor='middle' x='400' y='116' fill='currentColor' style='font-size:1em'>(</text>
<text text-anchor='middle' x='408' y='20' fill='currentColor' style='font-size:1em'>u</text>
<text text-anchor='middle' x='408' y='36' fill='currentColor' style='font-size:1em'>o</text>
<text text-anchor='middle' x='408' y='116' fill='currentColor' style='font-size:1em'>n</text>
<text text-anchor='middle' x='416' y='20' fill='currentColor' style='font-size:1em'>n</text>
<text text-anchor='middle' x='416' y='36' fill='currentColor' style='font-size:1em'>c</text>
<text text-anchor='middle' x='416' y='116' fill='currentColor' style='font-size:1em'>i</text>
<text text-anchor='middle' x='424' y='20' fill='currentColor' style='font-size:1em'>i</text>
<text text-anchor='middle' x='424' y='36' fill='currentColor' style='font-size:1em'>k</text>
<text text-anchor='middle' x='424' y='116' fill='currentColor' style='font-size:1em'>c</text>
<text text-anchor='middle' x='432' y='20' fill='currentColor' style='font-size:1em'>x</text>
<text text-anchor='middle' x='432' y='36' fill='currentColor' style='font-size:1em'>e</text>
<text text-anchor='middle' x='432' y='116' fill='currentColor' style='font-size:1em'>k</text>
<text text-anchor='middle' x='440' y='36' fill='currentColor' style='font-size:1em'>t</text>
<text text-anchor='middle' x='440' y='116' fill='currentColor' style='font-size:1em'>n</text>
<text text-anchor='middle' x='448' y='116' fill='currentColor' style='font-size:1em'>a</text>
<text text-anchor='middle' x='456' y='84' fill='currentColor' style='font-size:1em'>o</text>
<text text-anchor='middle' x='456' y='116' fill='currentColor' style='font-size:1em'>m</text>
<text text-anchor='middle' x='464' y='84' fill='currentColor' style='font-size:1em'>t</text>
<text text-anchor='middle' x='464' y='116' fill='currentColor' style='font-size:1em'>e</text>
<text text-anchor='middle' x='472' y='84' fill='currentColor' style='font-size:1em'>h</text>
<text text-anchor='middle' x='480' y='52' fill='currentColor' style='font-size:1em'>m</text>
<text text-anchor='middle' x='480' y='84' fill='currentColor' style='font-size:1em'>e</text>
<text text-anchor='middle' x='480' y='116' fill='currentColor' style='font-size:1em'>O</text>
<text text-anchor='middle' x='488' y='52' fill='currentColor' style='font-size:1em'>i</text>
<text text-anchor='middle' x='488' y='84' fill='currentColor' style='font-size:1em'>r</text>
<text text-anchor='middle' x='488' y='116' fill='currentColor' style='font-size:1em'>l</text>
<text text-anchor='middle' x='496' y='52' fill='currentColor' style='font-size:1em'>n</text>
<text text-anchor='middle' x='496' y='116' fill='currentColor' style='font-size:1em'>i</text>
<text text-anchor='middle' x='504' y='52' fill='currentColor' style='font-size:1em'>i</text>
<text text-anchor='middle' x='504' y='84' fill='currentColor' style='font-size:1em'>s</text>
<text text-anchor='middle' x='504' y='116' fill='currentColor' style='font-size:1em'>v</text>
<text text-anchor='middle' x='512' y='52' fill='currentColor' style='font-size:1em'>f</text>
<text text-anchor='middle' x='512' y='84' fill='currentColor' style='font-size:1em'>e</text>
<text text-anchor='middle' x='512' y='116' fill='currentColor' style='font-size:1em'>i</text>
<text text-anchor='middle' x='520' y='52' fill='currentColor' style='font-size:1em'>l</text>
<text text-anchor='middle' x='520' y='84' fill='currentColor' style='font-size:1em'>r</text>
<text text-anchor='middle' x='520' y='116' fill='currentColor' style='font-size:1em'>n</text>
<text text-anchor='middle' x='528' y='52' fill='currentColor' style='font-size:1em'>u</text>
<text text-anchor='middle' x='528' y='84' fill='currentColor' style='font-size:1em'>v</text>
<text text-anchor='middle' x='528' y='116' fill='currentColor' style='font-size:1em'>e</text>
<text text-anchor='middle' x='536' y='52' fill='currentColor' style='font-size:1em'>x</text>
<text text-anchor='middle' x='536' y='84' fill='currentColor' style='font-size:1em'>i</text>
<text text-anchor='middle' x='536' y='116' fill='currentColor' style='font-size:1em'>)</text>
<text text-anchor='middle' x='544' y='84' fill='currentColor' style='font-size:1em'>c</text>
<text text-anchor='middle' x='552' y='84' fill='currentColor' style='font-size:1em'>e</text>
<text text-anchor='middle' x='560' y='84' fill='currentColor' style='font-size:1em'>s</text>
<text text-anchor='middle' x='568' y='84' fill='currentColor' style='font-size:1em'>.</text>
<text text-anchor='middle' x='576' y='84' fill='currentColor' style='font-size:1em'>.</text>
<text text-anchor='middle' x='584' y='84' fill='currentColor' style='font-size:1em'>.</text>
</g>

    </svg>
  
</div>
<p>Here <a href="https://caddyserver.com/">caddy</a> acts as a TLS proxy.
It manages the TLS certificate, requesting a new one from Let’s Encrypt as needed. It also terminates the TLS connection from the browser and then connects to the underlying service, like miniflux.
This example could of course be generalized to any service proxied by caddy, in particular services handling more personal data, like a self-hosted webmail or contact server.</p>




  
  
  
  

  <div class="alert alert-note">
    <p class="alert-heading">
      ℹ️
      
        Note
      
    </p>
    <p>Here, we do not have a CDN in front of our site.<br>
The whole point is to restrict the certificates issued to a particular Let’s Encrypt account that we control.
A CDN terminates the TLS connection (usually), so it needs a TLS certificates for the domain.</p>
<p>In this context, the server is presumably in one’s house or in a datacenter nearby.
There is thus less of a need for an intermediary cache that would be closer to the user.</p>
  </div>



<h3 id="dns">DNS</h3>
<p>The domain hosting the RSS reader, <code>r.cj.rs</code>, is in fact a <code>CNAME</code> record pointing to the underlying machine hosting the various services, Olivine.
It looks like this:</p>
<div class="highlight"><pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>dog r.cj.rs
</span></span></code></pre></div><pre tabindex="0"><code>CNAME r.cj.rs.             5m00s   &#34;olivine.joly.eu.org.&#34;
    A olivine.joly.eu.org. 5m00s   132.145.68.59
</code></pre><h2 id="caa-records"><code>CAA</code> Records</h2>
<p>Going back to <a href="https://www.devever.net/~hl/xmpp-incident#narrow">the mitigation</a> we want to implement:</p>




  <figure>
    <blockquote cite="https://www.devever.net/~hl/xmpp-incident#narrow">
      <p>The basic idea is that you can configure a DNS record which specifies that only a <em>specific account</em> of a <em>specific CA</em> is authorised to issue certificates for a domain.</p>

    </blockquote>
    
      <figcaption class="blockquote-caption">
        
          <cite style="text-align: right"><a href="https://www.devever.net/~hl/xmpp-incident#narrow">https://www.devever.net/~hl/xmpp-incident#narrow</a></cite>
          <br/>
        
        
      </figcaption>
    
  </figure>



<p>Let’s Encrypt provides <a href="https://letsencrypt.org/docs/caa/">some documentation</a> for the <code>CAA</code> record (which stands for <em>Certification Authority Authorization</em>).
The key points are:</p>
<ul>
<li><code>CAA</code> records closest to the domain take priority: a <code>CAA</code> on <code>r.cj.rs</code> takes precedence over one on <code>cj.rs</code>.</li>
<li><code>CAA</code> follows <code>CNAME</code> redirects.</li>
<li>The <code>issue</code> and <code>issuewild</code> properties control the certificate authority allowed. If only <code>issue</code> is present, then the same constraints apply to both normal and wildcard certificates.</li>
<li>The <code>accounturi</code> parameter can restrict issuance to a particular account, like <code>https://acme-v02.api.letsencrypt.org/acme/acct/1234567890</code></li>
</ul>
<p>So in our case, we can simply add an <code>issue</code> <code>CAA</code> record with the <code>accounturi</code> parameter on the DNS record directly pointing to the machine (<code>olivine.joly.eu.org</code>).
Then other domains can alias with <code>CNAME</code> to that DNS record and will inherit the CAA constraints.
And if a service moves to a different server, the CAA constraint will be that of the new server, if any.</p>
<h3 id="finding-the-accounturi-caddy-uses">Finding the <code>accounturi</code> Caddy Uses</h3>
<p>Caddy automatically creates a Let’s Encrypt account if none is configured.
It then issues certificates against that account.
But where is the account number?</p>
<p>By default on Ubuntu, the parameters for that account are stored in <code>/var/lib/caddy/.local/share/caddy/acme/acme-v02.api.letsencrypt.org-directory/users/default/default.json</code><sup id="fnref:3"><a href="#fn:3" class="footnote-ref" role="doc-noteref">3</a></sup>.
There, the location key contains the accounturi:</p>
<div class="highlight"><pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-json" data-lang="json"><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>  <span style="color:#7f848e">// ...
</span></span></span><span style="display:flex;"><span>  <span style="color:#e06c75">&#34;location&#34;</span>: <span style="color:#98c379">&#34;https://acme-v02.api.letsencrypt.org/acme/acct/1968958296&#34;</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><h2 id="putting-it-all-together">Putting It All Together</h2>
<p>Summing up the above, we know that we need a <code>CAA</code> record with the <code>issue</code> property and the same <code>accounturi</code> as caddy.
It looks like this in the Bind format:</p>
<div class="highlight"><pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bind" data-lang="bind"><span style="display:flex;"><span><span style="color:#c678dd">IN</span> <span style="color:#c678dd">CAA</span>   <span style="color:#98c379">0</span> issue &#34;<span style="color:#e5c07b">letsencrypt.org</span><span style="color:#7f848e">;accounturi=https://acme-v02.api.letsencrypt.org/acme/acct/1968958296&#34;</span>
</span></span></code></pre></div><p>This record is placed on <code>olivine.joly.eu.org</code>, where a <code>A</code> (or <code>AAAA</code>) record contains the IP address of the Olivine server. In turn, the RSS reader host is a <code>CNAME</code> pointing to that <code>A</code> record.</p>
<h3 id="testing">Testing</h3>
<p>To test that the new setup works, we can try to issue a certificate for a new domain.
Just add it to the Caddy configuration as usual, for instance like this:</p>
<div class="highlight"><pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-caddy" data-lang="caddy"><span style="display:flex;"><span>test-caa.cj.rs {
</span></span><span style="display:flex;"><span>  <span style="color:#c678dd">respond</span> <span style="color:#98c379">&#34;Hello, world!&#34;</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Caddy logs should show that the certificate was successfully issued:</p>
<div class="highlight"><pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-json" data-lang="json"><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>  <span style="color:#e06c75">&#34;level&#34;</span>:<span style="color:#98c379">&#34;info&#34;</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#7f848e">// ...
</span></span></span><span style="display:flex;"><span>  <span style="color:#e06c75">&#34;msg&#34;</span>:<span style="color:#98c379">&#34;certificate obtained successfully&#34;</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#e06c75">&#34;identifier&#34;</span>:<span style="color:#98c379">&#34;test-caa.cj.rs&#34;</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>You can similarly test that changing the <code>accounturi</code> in the <code>CAA</code>.
After the various caches expire, attempts to issue a certificate fail:</p>
<div class="highlight"><pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-json" data-lang="json"><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>  <span style="color:#e06c75">&#34;level&#34;</span>:<span style="color:#98c379">&#34;error&#34;</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#7f848e">// ...
</span></span></span><span style="display:flex;"><span>  <span style="color:#e06c75">&#34;msg&#34;</span>:<span style="color:#98c379">&#34;could not get certificate from issuer&#34;</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#e06c75">&#34;error&#34;</span>:<span style="color:#98c379">&#34;HTTP 0 urn:ietf:params:acme:error:caa - During secondary validation: While processing CAA for test-caa.cj.rs: CAA record for olivine.joly.eu.org prevents issuance&#34;</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><h2 id="just-a-mitigation-in-the-end">Just a Mitigation in the End</h2>
<p>We have limited the certificates that can be issued to a particular CA and to a particular account.
In turn, that account is tied to a private key stored on the server.</p>
<p>However, as <a href="https://www.devever.net/~hl/xmpp-incident#narrow">Hugo Landau explains</a>, this is only a mitigation.
A well resourced attacker could still succeed.
For instance, they could alter the <code>CAA</code> record read by the CA.</p>
<p>Thus, complementary defenses include monitoring certificate transparency to spot suspicious issuance.
Cloudflare <a href="https://blog.cloudflare.com/introducing-certificate-transparency-monitoring/">offers such a service</a>.
So does <a href="https://crt.sh">crt.sh</a>.
While CAs sometimes emit certificates without logging them to Certificate Transparency<sup id="fnref:4"><a href="#fn:4" class="footnote-ref" role="doc-noteref">4</a></sup>, those certificates should be rejected by most browsers.
In our case, with web services, that would be enough.
Other clients communicating over TLS might not reject them though, like XMPP clients of the <code>jabber.ru</code> example.</p>
<p>Despite the limitations of this <code>CAA</code>-based approach, it was interesting to learn more about it and see how the various pieces fit together.
I hope you enjoyed reading!</p>
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p>At least that’s the basic domain validation. Other types exist, but they are not necessarily that much more reliable in practice.&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:2">
<p>There is little the certificate authority can do, it’s not really their fault if someone manipulates traffic between them and the server to verify. They do use <a href="https://letsencrypt.org/2020/02/19/multi-perspective-validation/">multi-perspective validation</a> as mitigation measure though.&#160;<a href="#fnref:2" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:3">
<p>That same folder also holds the private key used to sign in with the account.&#160;<a href="#fnref:3" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:4">
<p>A customer can request that, if they want to avoid publishing a domain name in a public log.&#160;<a href="#fnref:4" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>
]]></content:encoded></item></channel></rss>