<?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>Zertifikate – Serverküche</title><link>https://serverkueche.de/tags/zertifikate/</link><description>Zertifikate – Neueste Beiträge von Serverküche</description><generator>Hugo</generator><language>de-DE</language><managingEditor>feedback@serverkueche.de (Serverküche)</managingEditor><webMaster>feedback@serverkueche.de (Serverküche)</webMaster><copyright>2026 Serverküche</copyright><lastBuildDate>Tue, 18 Aug 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://serverkueche.de/tags/zertifikate/index.xml" rel="self" type="application/rss+xml"/><item><title>Wie HTTPS eigentlich funktioniert (und was Traefik dir abnimmt)</title><link>https://serverkueche.de/tutorials/wie-tls-funktioniert/</link><pubDate>Tue, 18 Aug 2026 00:00:00 +0000</pubDate><author>feedback@serverkueche.de (Serverküche)</author><guid>https://serverkueche.de/tutorials/wie-tls-funktioniert/</guid><description>Zertifikat, Vertrauenskette, Let's Encrypt, Handshake: Dieser Grundlagen-Guide erklärt HTTPS an echten Befehlen – und was Traefik davon automatisiert.</description><content:encoded><![CDATA[<p>Das Schloss-Symbol im Browser ist die am meisten benutzte und am wenigsten verstandene Sicherheitsfunktion des Webs. In diesem Konzept-Guide schaust du einmal dahinter – mit echten Befehlen statt grauer Theorie. Danach liest du Zertifikatsfehler wie eine Zutatenliste.</p>
<h2 id="was-bauen-wir">Was bauen wir?</h2>
<p>Diesmal keinen neuen Dienst, sondern Verständnis: Am Ende weißt du, was ein TLS-Zertifikat ist, warum dein Browser ihm vertraut, wie Let&rsquo;s Encrypt kostenlos beweist, dass eine Domain dir gehört, und was beim TLS-Handshake passiert. Jeden Baustein prüfst du selbst mit <code>openssl</code> und <code>curl</code> – die Beispiele sind mit <strong>OpenSSL 3.5</strong> auf Debian 13 gegen die echte <code>serverkueche.de</code> ausgeführt und funktionieren gegen jede HTTPS-Website. Genau dieses Wissen setzt <a href="/tutorials/reverse-proxy-traefik/">Traefik</a> für dich in Automatik um – und wenn dort mal etwas klemmt, weißt du künftig, <em>wo</em>.</p>
<h2 id="voraussetzungen">Voraussetzungen</h2>
<ul>
<li>Verständnis, wie eine <a href="/tutorials/domain-mit-server-verbinden/">Domain auf deinen Server zeigt</a> (A-Record, <code>dig</code>)</li>
<li>Irgendein Linux-Terminal – dein Server oder dein Laptop; gebraucht werden nur Standardwerkzeuge (<code>openssl</code>, <code>curl</code>, <code>dig</code> aus dem Paket <code>dnsutils</code>)</li>
<li>Kein laufender Webserver nötig – wir schauen uns bestehende Websites an</li>
</ul>
<div class="not-prose my-6 overflow-hidden rounded-xl border border-paprika-200 bg-paprika-50 dark:border-paprika-800 dark:bg-paprika-900/20"
     data-track-content data-content-name="Affiliate-Box · /tutorials/wie-tls-funktioniert/" data-content-piece="VPS 1000 G12">
  <div class="flex items-center justify-between border-b border-paprika-200 bg-paprika-100 px-4 py-1.5 text-xs font-semibold uppercase tracking-wide text-paprika-700 dark:border-paprika-800 dark:bg-paprika-900/40 dark:text-paprika-300">
    <span>🍳 Empfehlung</span>
    <span title="Mit * markierte Links sind Affiliate-Links.">Anzeige</span>
  </div>
  <div class="flex flex-col gap-4 p-4 sm:flex-row sm:items-center sm:justify-between">
    <div>
      <p class="text-lg font-bold text-slate-900 dark:text-white">VPS 1000 G12</p>
      <p class="mt-1 text-sm text-slate-600 dark:text-slate-300">4 vCore · 8 GB RAM · 256 GB NVMe</p>
      <p class="mt-1 text-sm font-semibold text-paprika-700 dark:text-paprika-400">ab 10,36 €/Monat</p>
      <p class="mt-2 text-sm text-slate-600 dark:text-slate-400">Zum Nachvollziehen reicht jeder Rechner – fürs eigene HTTPS-Setup später ein kleiner VPS.</p>
    </div>
    <a href="https://www.netcup.com/de/server/vps/vps-1000-g12-12m?ref=44083" rel="sponsored noopener" target="_blank"
   data-track-event="Affiliate|netcup: Affiliate-Box|VPS 1000 G12 · {page}"
   class="inline-flex shrink-0 items-center justify-center rounded-lg bg-paprika-600 px-5 py-2.5 font-semibold text-white transition-colors hover:bg-paprika-700">
  Zu netcup →
</a>

  </div><div class="px-4 pb-4"><p class="not-prose my-3 flex flex-wrap items-center gap-x-2 gap-y-1 rounded-lg border border-herb-500/40 bg-herb-50 px-3 py-2 text-sm text-slate-700 dark:bg-herb-900/20 dark:text-slate-200">
  <span>💶 <strong>5 € Gutschein</strong> für netcup-Neukunden:</span><code data-track-voucher="36nc17844976032"
        class="rounded bg-white px-2 py-0.5 font-mono text-sm font-semibold text-herb-800 dark:bg-slate-800 dark:text-herb-400">36nc17844976032</code>
  <span class="text-xs text-slate-500 dark:text-slate-400">(nur Neukunden, keine Domains)</span>
</p></div>
</div>

<h2 id="schritt-für-schritt">Schritt für Schritt</h2>
<h3 id="schritt-1-welche-zwei-probleme-tls-löst">Schritt 1: Welche zwei Probleme TLS löst</h3>
<p>HTTPS ist normales HTTP, transportiert durch einen TLS-Tunnel (Transport Layer Security). Der Tunnel löst zwei Probleme gleichzeitig:</p>
<ol>
<li><strong>Vertraulichkeit:</strong> Niemand zwischen Browser und Server kann mitlesen oder unbemerkt verändern – nicht das WLAN im Café, nicht der Provider.</li>
<li><strong>Authentizität:</strong> Du redest wirklich mit dem Server hinter <code>DEINE_DOMAIN</code> – nicht mit einem Angreifer, der sich dazwischengeschaltet hat.</li>
</ol>
<p>Für Punkt 2 braucht es einen Ausweis: das <strong>Zertifikat</strong>.</p>
<div class="not-prose my-6 rounded-lg border-l-4 p-4 border-sky-300 bg-sky-50 dark:border-sky-800 dark:bg-sky-900/20">
  <p class="mb-1 flex items-center gap-2 font-semibold text-slate-900 dark:text-white">
    <span aria-hidden="true">ℹ️</span>Das Schloss heißt nicht „harmlos“
  </p>
  <div class="prose-kitchen text-sm">Das Schloss-Symbol bestätigt nur die verschlüsselte Verbindung zur angezeigten Domain. Auch eine Phishing-Seite bekommt problemlos ein gültiges Zertifikat – TLS beglaubigt die <em>Leitung</em>, nicht den <em>Inhalt</em>.</div>
</div>
<h3 id="schritt-2-ein-echtes-zertifikat-ansehen">Schritt 2: Ein echtes Zertifikat ansehen</h3>
<p><code>openssl s_client</code> baut eine TLS-Verbindung auf und zeigt, was der Server vorlegt. Ersetze <code>DEINE_DOMAIN</code> durch eine beliebige HTTPS-Domain – hier läuft der Befehl gegen <code>serverkueche.de</code>:</p>
<div class="sk-code">
  <span class="sk-code-head">Terminal</span>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">echo</span> <span class="p">|</span> openssl s_client -connect DEINE_DOMAIN:443 -servername DEINE_DOMAIN 2&gt;/dev/null <span class="p">|</span> openssl x509 -noout -subject -issuer -dates</span></span></code></pre></div>
</div>
<p>Das <code>echo |</code> beendet die Verbindung sofort wieder, der zweite <code>openssl</code>-Aufruf übersetzt das vorgelegte Zertifikat in Klartext:</p>
<div class="sk-code">
  <span class="sk-code-head">Ausgabe</span>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">subject=CN=serverkueche.de
</span></span><span class="line"><span class="cl">issuer=C=US, O=Let&#39;s Encrypt, CN=YR1
</span></span><span class="line"><span class="cl">notBefore=Jul 16 11:33:26 2026 GMT
</span></span><span class="line"><span class="cl">notAfter=Oct 14 11:33:25 2026 GMT</span></span></code></pre></div>
</div>
<p>Diese Angaben solltest du lesen können:</p>
<ul>
<li><strong>subject</strong> – für wen der Ausweis gilt. Für welche Hostnamen genau, steht im Feld <em>Subject Alternative Name</em> (hier: <code>serverkueche.de</code> und <code>www.serverkueche.de</code> – eine Subdomain wie <code>blog.serverkueche.de</code> wäre <strong>nicht</strong> abgedeckt und bräuchte ein eigenes Zertifikat).</li>
<li><strong>issuer</strong> – wer ihn ausgestellt hat: die Zertifizierungsstelle (CA), hier Let&rsquo;s Encrypt mit ihrem Zwischenzertifikat <code>YR1</code>.</li>
<li><strong>notBefore/notAfter</strong> – die Gültigkeit. Rechne nach: 16. Juli bis 14. Oktober sind <strong>90 Tage</strong>, die Standard-Laufzeit von Let&rsquo;s Encrypt. Deshalb ist automatische Erneuerung keine Komfortfunktion, sondern Pflicht.</li>
</ul>
<h3 id="schritt-3-die-vertrauenskette--warum-dein-browser-dem-ausweis-glaubt">Schritt 3: Die Vertrauenskette – warum dein Browser dem Ausweis glaubt</h3>
<p>Woher weiß dein Browser, dass <code>YR1</code> kein Fantasiename ist? Über eine Kette. Lass dir alle Zertifikate der Verbindung zeigen:</p>
<div class="sk-code">
  <span class="sk-code-head">Terminal</span>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">echo</span> <span class="p">|</span> openssl s_client -connect DEINE_DOMAIN:443 -servername DEINE_DOMAIN 2&gt;/dev/null <span class="p">|</span> grep -E <span class="s2">&#34;^ *[0-9] s:|^ *i:&#34;</span></span></span></code></pre></div>
</div>
<div class="sk-code">
  <span class="sk-code-head">Ausgabe</span>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl"> 0 s:CN=serverkueche.de
</span></span><span class="line"><span class="cl">   i:C=US, O=Let&#39;s Encrypt, CN=YR1
</span></span><span class="line"><span class="cl"> 1 s:C=US, O=Let&#39;s Encrypt, CN=YR1
</span></span><span class="line"><span class="cl">   i:C=US, O=ISRG, CN=Root YR
</span></span><span class="line"><span class="cl"> 2 s:C=US, O=ISRG, CN=Root YR
</span></span><span class="line"><span class="cl">   i:C=US, O=Internet Security Research Group, CN=ISRG Root X1</span></span></code></pre></div>
</div>
<p>Lies es von oben nach unten (<code>s:</code> = subject, <code>i:</code> = ausgestellt von): Das Domain-Zertifikat (0) wurde vom Zwischenzertifikat <code>YR1</code> unterschrieben (1), das wiederum von einem <strong>Root-Zertifikat</strong> der ISRG, der Organisation hinter Let&rsquo;s Encrypt (2). Root-Zertifikate sind der Vertrauensanker: Sie sind in deinem Betriebssystem und Browser fest hinterlegt (der „Root Store“, auf Debian das Paket <code>ca-certificates</code>). Kann der Browser eine lückenlose Unterschriftenkette vom Server-Zertifikat bis zu einem Root aus seinem Store bilden, gilt die Verbindung als vertrauenswürdig – <code>openssl</code> meldet das in der <code>s_client</code>-Ausgabe als:</p>
<div class="sk-code">
  <span class="sk-code-head">Ausgabe</span>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">Verify return code: 0 (ok)</span></span></code></pre></div>
</div>
<p>Alles andere als <code>0 (ok)</code> ist einer der Fehlerfälle aus „Wenn es nicht funktioniert“.</p>
<h3 id="schritt-4-wie-lets-encrypt-prüft-dass-die-domain-dir-gehört">Schritt 4: Wie Let&rsquo;s Encrypt prüft, dass die Domain dir gehört</h3>
<p>Eine CA darf ein Zertifikat nur ausstellen, wenn du die Kontrolle über die Domain nachweist. Das läuft über das <strong>ACME-Protokoll</strong>, vollautomatisch, in zwei Varianten:</p>
<ul>
<li><strong>HTTP-01:</strong> Die CA sagt „lege die Datei X unter <code>http://DEINE_DOMAIN/.well-known/acme-challenge/X</code> ab“. Nur wer den Server hinter dem A-Record kontrolliert, kann das. Deshalb muss <strong>Port 80 aus dem Internet erreichbar</strong> sein – und deshalb steht der <code>dig</code>-Check im <a href="/tutorials/domain-mit-server-verbinden/">Domain-Tutorial</a> <em>vor</em> dem ersten Zertifikat: Zeigt der A-Record ins Leere, findet die CA die Datei nie.</li>
<li><strong>DNS-01:</strong> Statt einer Datei setzt du einen TXT-Record <code>_acme-challenge.DEINE_DOMAIN</code>. Das braucht API-Zugriff auf deine DNS-Zone, funktioniert dafür ohne offenen Port – und ist der einzige Weg zu Wildcard-Zertifikaten (<code>*.DEINE_DOMAIN</code>).</li>
</ul>
<p>Besteht dein Server die Challenge, unterschreibt Let&rsquo;s Encrypt dein Zertifikat mit <code>YR1</code> – und die Kette aus Schritt 3 ist komplett.</p>
<h3 id="schritt-5-der-handshake--was-bei-jedem-verbindungsaufbau-passiert">Schritt 5: Der Handshake – was bei jedem Verbindungsaufbau passiert</h3>
<p>Das Zertifikat beweist die Identität, verschlüsselt wird mit etwas anderem. Beim <strong>TLS-Handshake</strong> einigen sich Browser und Server in wenigen Millisekunden auf einen gemeinsamen Sitzungsschlüssel. <code>curl</code> zeigt dir das Ergebnis:</p>
<div class="sk-code">
  <span class="sk-code-head">Terminal</span>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">curl -sIv https://DEINE_DOMAIN/ 2&gt;<span class="p">&amp;</span><span class="m">1</span> <span class="p">|</span> grep -E <span class="s2">&#34;SSL connection|HTTP/&#34;</span></span></span></code></pre></div>
</div>
<div class="sk-code">
  <span class="sk-code-head">Ausgabe</span>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">* SSL connection using TLSv1.3 / TLS_AES_128_GCM_SHA256 / x25519 / RSASSA-PSS
</span></span><span class="line"><span class="cl">* using HTTP/2
</span></span><span class="line"><span class="cl">HTTP/2 200</span></span></code></pre></div>
</div>
<p>Die eine Zeile fasst den ganzen Handshake zusammen: Protokoll <strong>TLS 1.3</strong> (der aktuelle Standard), Schlüsselaustausch über die Kurve <code>x25519</code> – dabei entsteht der Sitzungsschlüssel, ohne dass er je über die Leitung geht –, danach verschlüsselt <strong>AES-128-GCM</strong> den eigentlichen HTTP-Verkehr, und <code>RSASSA-PSS</code> ist die Unterschrift des Servers mit dem privaten Schlüssel zu seinem Zertifikat. Dieser private Schlüssel ist das eigentliche Geheimnis: Wer ihn hat, kann sich als deine Domain ausgeben.</p>
<h3 id="schritt-6-was-traefik-dir-davon-abnimmt">Schritt 6: Was Traefik dir davon abnimmt</h3>
<p>Jetzt kannst du einordnen, was <a href="/tutorials/reverse-proxy-traefik/">Traefik</a> im Hintergrund alles erledigt:</p>
<ul>
<li><strong>ACME-Client:</strong> Zertifikat bestellen, HTTP-01-Challenge auf Port 80 beantworten, Kette abholen – beim ersten Start einer neuen App automatisch.</li>
<li><strong>Speicherung:</strong> Zertifikate samt privater Schlüssel landen in <code>acme.json</code> – deshalb besteht Traefik dort auf den strengen Dateirechten (<code>chmod 600</code>).</li>
<li><strong>Erneuerung:</strong> Rund 30 Tage vor Ablauf holt Traefik ohne dein Zutun ein frisches Zertifikat – von der 90-Tage-Laufzeit merkst du nichts.</li>
<li><strong>Auslieferung:</strong> Pro Anfrage wählt Traefik anhand des angefragten Hostnamens (SNI) das passende Zertifikat aus und leitet HTTP auf HTTPS um.</li>
</ul>
<p>Ohne diese Automatik wäre HTTPS Handarbeit im Monatsrhythmus – abgelaufene Zertifikate sind einer der häufigsten selbstverschuldeten Ausfälle überhaupt.</p>
<h2 id="wenn-es-nicht-funktioniert">Wenn es nicht funktioniert</h2>
<div class="troubleshoot not-prose">
<p><strong>Browser meldet <code>NET::ERR_CERT_AUTHORITY_INVALID</code>, <code>curl</code> sagt <code>self-signed certificate</code>.</strong> Der Server liefert das eingebaute Traefik-Notzertifikat (<code>TRAEFIK DEFAULT CERT</code>) aus, weil die Ausstellung fehlschlug. Fast immer: Der A-/AAAA-Record zeigt auf die falsche IP (<code>dig DEINE_DOMAIN</code> prüfen) oder Port 80 ist <a href="/tutorials/firewall-ufw-einrichten/">in der Firewall</a> zu – die HTTP-01-Challenge kommt nie an. Die genaue Ursache steht in den Traefik-Logs: <code>docker compose logs traefik | grep -i acme</code>.</p>
<p><strong>Im <code>issuer</code> steht <code>(STAGING) Ersatz Emmer YR2</code>.</strong> Die Test-CA von Let&rsquo;s Encrypt ist noch aktiv – Browser vertrauen ihr absichtlich nicht. Staging-Zeile aus der Traefik-Konfiguration entfernen, <code>acme.json</code> leeren, Container neu starten (<a href="/tutorials/reverse-proxy-traefik/">Details im Traefik-Tutorial</a>).</p>
<p><strong><code>certificate has expired</code>.</strong> Die automatische Erneuerung scheitert seit mindestens 30 Tagen – gleiche Ursachenliste wie beim ersten Fehler, nur lange unbemerkt. Falls die Meldung <em>nur auf einem Gerät</em> auftaucht: dessen Systemuhr prüfen, TLS ist zeitkritisch.</p>
<p><strong>Let&rsquo;s Encrypt meldet <code>too many certificates already issued</code>.</strong> Rate-Limit gerissen, meist durch Experimentier-Schleifen gegen die Produktiv-CA. Auf die Staging-CA wechseln, bis das Setup steht – und <code>acme.json</code> ins Backup nehmen, statt Zertifikate neu auszustellen.</p>
<p><strong><code>unable to get local issuer certificate</code> auf einem alten Client.</strong> Dem System fehlt das Root-Zertifikat aus Schritt 3 – der Root Store ist veraltet. Auf Debian: <code>apt update &amp;&amp; apt install ca-certificates</code>.</p>

</div>

<h2 id="wartung--backups">Wartung &amp; Backups</h2>
<ul>
<li><strong>Bei automatisierter Ausstellung: nichts Monatliches.</strong> Genau das ist der Punkt der Traefik-Automatik. Was du stattdessen tust: den Ablauf <strong>überwachen</strong> – <a href="/tutorials/uptime-kuma-monitoring/">Uptime Kuma</a> prüft bei HTTPS-Monitoren das Zertifikat mit und warnt rechtzeitig vor dem Ablaufdatum. So fällt eine seit Wochen scheiternde Erneuerung auf, <em>bevor</em> Besucher Fehlermeldungen sehen.</li>
<li><strong><code>acme.json</code> gehört ins Backup</strong> – sie enthält private Schlüssel, also nur verschlüsselt sichern, z. B. <a href="/tutorials/backups-mit-restic/">mit Restic</a>. Nach einem Server-Neuaufbau müssen sonst alle Zertifikate neu ausgestellt werden, was am Rate-Limit scheitern kann.</li>
<li><strong>Die Laufzeiten schrumpfen branchenweit:</strong> Die CA/Browser-Gremien haben beschlossen, die maximale Zertifikatslaufzeit schrittweise zu senken – von 200 Tagen (ab 2026) über 100 Tage (ab 2027) bis auf 47 Tage ab 2029. Die 90 Tage von Let&rsquo;s Encrypt sind also nicht knauserig, sondern die Zukunft für alle. Wer heute automatisiert, merkt davon nichts.</li>
</ul>
]]></content:encoded></item></channel></rss>