feat(cert-manager): Fehlendes Zertifikat holen, gehärteter Adressschutz

- Neuer Knopf „Fehlendes Zertifikat holen“ nur auf Klick: POST fetch-issuer liest die
  Aussteller-Adresse (AIA) serverseitig aus dem Zertifikat, nie vom Browser; nur Standardport,
  Adressschutz vor jedem Sprung, Aufloesung beim Verbinden geprueft, 8 s und 256 KiB, hoechstens
  3 Weiterleitungen; angenommen wird nur ein Zertifikat, das wirklich ausgestellt hat
- Geholte Zertifikate erscheinen als „nachgeladen von <Server>“ in der Liste und auf der Karte
- Gemeinsamer Adressschutz gehaertet: versteckte IPv6-Schreibweisen interner Adressen
  (IPv4-gemappt in Hex, NAT64, 6to4, Teredo, Zonenkennung u. a.), neues Spec
- Modul-Changelog 1.2.0, CHANGELOG (Sicherheit), drei Anleitungen

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-10-09 16:10:39 +02:00
parent 47b26219b2
commit a2fc2cb300
32 changed files with 1630 additions and 36 deletions
+10 -1
View File
@@ -156,10 +156,19 @@ Der Zertifikat-Manager hilft Ihnen, Zertifikate, Schlüssel und Zertifikatsanfra
- **Dateien** — Hier sammeln Sie alles. Ziehen Sie Dateien in das Feld oder klicken Sie hinein und wählen Sie Dateien aus, so oft und in beliebiger Menge nacheinander; **jede neue Datei kommt zur Liste hinzu und ersetzt nie eine frühere**. Sie können auch die ZIP-Datei Ihres Zertifikatsausstellers hochladen: Tessera schaut hinein und nennt zu jedem enthaltenen Eintrag, was es darin gefunden hat. Überflüssiges wie Ordner mit dem Namen `__MACOSX` überspringt Tessera still; verschachtelte oder passwortgeschützte ZIP-Dateien nennt es mit dem Grund, warum es sie nicht öffnet. Zusätzlich können Sie PEM-Text einfügen („PEM-Text einfügen“, Text beginnt mit `-----BEGIN`); er erscheint als eigener Eintrag. Die Liste fasst bis zu 30 Einträge, höchstens 5 MB je Datei und zusammen höchstens 10 MB; dieselbe Datei kann nicht zweimal hinzugefügt werden. Zu jedem Eintrag zeigt die Liste, was erkannt wurde: Serverzertifikat, Zwischenzertifikat, Stammzertifikat, privater Schlüssel oder Zertifikatsanfrage. Mit dem Knopf am Eintrag nehmen Sie eine einzelne Datei wieder aus der Liste. Ist eine Datei durch ein Passwort geschützt (PFX-/P12-Datei oder verschlüsselter Schlüssel), erscheint beim Eintrag ein Feld für das Passwort; es gilt nur für diese eine Datei. Hat Tessera zum Serverzertifikat schon einen Schlüssel, erscheint eine passwortgeschützte PFX-Datei nur als ruhiger Hinweis, den Sie nicht beachten müssen.
- **Analysieren** — Zeigt zu jedem erkannten Teil die Einzelheiten: Name, Aussteller, Gültigkeit (mit den verbleibenden Tagen), Schlüsselart (RSA oder EC mit Kurve), die Namen, für die das Zertifikat gilt, sowie Seriennummer und Fingerabdrücke. Außerdem sehen Sie, was zusammengehört: welcher Schlüssel zu welchem Zertifikat passt und welche Zertifikatsanfrage zu welchem Zertifikat gehört. Tessera ordnet nie nach dem Namen zu, sondern prüft den Schlüssel selbst.
- **Aufteilen** — Zerlegt Ihre Dateien in die einzelnen Teile. Jedes Teil laden Sie in seinem natürlichen Format herunter (Zertifikat als `.crt`, Schlüssel als `.key`, Anfrage als `.csr`) oder alle zusammen als ZIP-Datei.
- **Zusammenführen** — Tessera ordnet Serverzertifikat, Zwischenzertifikate und Stammzertifikat **selbst**; die Reihenfolge Ihrer Dateien spielt keine Rolle. Dabei prüft es nicht nur Namen, sondern die echte Unterschrift jedes Zertifikats, sodass ein gleichnamiges, aber falsches Zwischenzertifikat nie verwendet wird. Gibt es mehrere Möglichkeiten, wählt Tessera nachvollziehbar die beste (zum Beispiel nicht abgelaufen). Sie können herunterladen: **Fullchain** (Serverzertifikat plus Zwischenzertifikate), **Nur Kette** (nur die Zwischenzertifikate, zum Beispiel für Systeme, die das Serverzertifikat getrennt wollen), **Zertifikat und Schlüssel** in einer PEM-Datei sowie eine **PFX-Datei**. Fullchain und Nur Kette gibt es als PEM, als `.p7b` oder als binäre `.p7c`. Für die PFX-Datei vergeben Sie ein Passwort (zweimal eingeben) und wählen die Verschlüsselung: **„Kompatibel (auch ältere Windows-Server)“** ist vorgewählt und die sichere Wahl, wenn Sie nicht wissen, wo die Datei eingespielt wird; **„Modern (AES-256)“** ist stärker, wird aber von älteren Systemen wie Windows Server 2016 oft nicht gelesen. Das Häkchen **„Root-Zertifikat mitnehmen“** ist standardmäßig aus, denn die meisten Server und Browser kennen die Wurzel schon und brauchen sie nicht; setzen Sie es nur, wenn ein Gerät es ausdrücklich verlangt (manche Geräte, Java-Anwendungen oder eigene Firmenwurzeln). Fehlt ein Aussteller in Ihrer Liste, sagt Tessera das ausdrücklich: **„Zwischenzertifikat fehlt“** heißt, dass direkt über dem Serverzertifikat das Zwischenzertifikat nicht in der Liste ist; fehlt dagegen nur das Zertifikat ganz oben (meist die Wurzel), erscheint ein ruhiger Hinweis, denn das ist für die meisten Server in Ordnung. Fügen Sie das fehlende Zertifikat im Reiter „Dateien“ hinzu.
- **Zusammenführen** — Tessera ordnet Serverzertifikat, Zwischenzertifikate und Stammzertifikat **selbst**; die Reihenfolge Ihrer Dateien spielt keine Rolle. Dabei prüft es nicht nur Namen, sondern die echte Unterschrift jedes Zertifikats, sodass ein gleichnamiges, aber falsches Zwischenzertifikat nie verwendet wird. Gibt es mehrere Möglichkeiten, wählt Tessera nachvollziehbar die beste (zum Beispiel nicht abgelaufen). Sie können herunterladen: **Fullchain** (Serverzertifikat plus Zwischenzertifikate), **Nur Kette** (nur die Zwischenzertifikate, zum Beispiel für Systeme, die das Serverzertifikat getrennt wollen), **Zertifikat und Schlüssel** in einer PEM-Datei sowie eine **PFX-Datei**. Fullchain und Nur Kette gibt es als PEM, als `.p7b` oder als binäre `.p7c`. Für die PFX-Datei vergeben Sie ein Passwort (zweimal eingeben) und wählen die Verschlüsselung: **„Kompatibel (auch ältere Windows-Server)“** ist vorgewählt und die sichere Wahl, wenn Sie nicht wissen, wo die Datei eingespielt wird; **„Modern (AES-256)“** ist stärker, wird aber von älteren Systemen wie Windows Server 2016 oft nicht gelesen. Das Häkchen **„Root-Zertifikat mitnehmen“** ist standardmäßig aus, denn die meisten Server und Browser kennen die Wurzel schon und brauchen sie nicht; setzen Sie es nur, wenn ein Gerät es ausdrücklich verlangt (manche Geräte, Java-Anwendungen oder eigene Firmenwurzeln). Fehlt ein Aussteller in Ihrer Liste, sagt Tessera das ausdrücklich: **„Zwischenzertifikat fehlt“** heißt, dass direkt über dem Serverzertifikat das Zwischenzertifikat nicht in der Liste ist; fehlt dagegen nur das Zertifikat ganz oben (meist die Wurzel), erscheint ein ruhiger Hinweis, denn das ist für die meisten Server in Ordnung. Das fehlende Zertifikat können Sie selbst im Reiter „Dateien“ hinzufügen oder, wie unten beschrieben, von Tessera holen lassen.
- **Konvertieren** — Wandelt ein einzelnes Teil in ein anderes Format um: Zertifikate als PEM, DER, PKCS#7 (`.p7b`, `.p7c`); Schlüssel als PKCS#8, klassisch (PKCS#1 bei RSA, SEC1 bei EC) oder DER, auf Wunsch mit eigenem Passwort verschlüsselt; Zertifikatsanfragen als PEM oder DER.
- **Vorlagen** — Wählen Sie das System, auf dem Ihr Zertifikat laufen soll, und Tessera erzeugt mit einem Klick die passenden Dateien und zeigt die Zeilen für die Einrichtung (mit „Kopieren“). Mehrere Dateien kommen in einer ZIP-Datei, die zusätzlich eine kurze Anleitung enthält. Jede Vorlage braucht das Serverzertifikat **und** den dazu passenden privaten Schlüssel; fehlt der Schlüssel, erklärt Tessera das. Es gibt sieben Vorlagen: **Nginx** (`fullchain.pem` und `privkey.pem`); **Apache 2.4.8 und neuer** (ebenfalls `fullchain.pem` und `privkey.pem`); **Apache älter als 2.4.8** (getrennt `cert.pem`, `chain.pem` und `privkey.pem`); **Windows / IIS** (eine PFX-Datei mit dem Passwort, das Sie vergeben, vorgewählt ist „Kompatibel“); **Nginx Proxy Manager** (`certificate.pem`, `intermediate.pem` und `privkey.pem`; die Anleitung nennt, welche Datei in welches Feld unter „SSL Certificates“, „Add SSL Certificate“, „Custom“ gehört); **HAProxy** (eine einzige PEM-Datei mit Zertifikat, Zwischenzertifikaten und Schlüssel) und **Tomcat / Java** (eine `.p12`-Datei mit dem Passwort, das Sie vergeben, ebenfalls mit vorgewähltem „Kompatibel“). Das Passwort steht nie in den angezeigten Zeilen; dort steht stattdessen `IHR-PASSWORT`.
**Fehlendes Zertifikat holen:** Fehlt ein Zwischenzertifikat, erscheint unter der Meldung „Zwischenzertifikat fehlt“ der Knopf **„Fehlendes Zertifikat holen“**. Er steht in den Reitern „Analysieren“, „Zusammenführen“ und „Vorlagen“ an der Stelle, an der die Kette unterbrochen ist. Die Sache funktioniert so: Fast jedes Serverzertifikat trägt eine Adresse in sich, unter der sein Aussteller das Zwischenzertifikat bereithält. Wenn Sie auf den Knopf klicken, fragt Tessera genau diese Adresse einmal ab und fügt das Ergebnis Ihrer Liste hinzu. Dabei gilt:
- **Nur auf Ihren Klick.** Tessera holt nie von sich aus etwas aus dem Internet, auch nicht beim Öffnen des Reiters oder wenn Sie Dateien hinzufügen oder entfernen. Der Hinweis über dem Knopf nennt den Server, bei dem Tessera nachfragt.
- **Nur eine geprüfte Antwort wird übernommen.** Tessera nimmt das heruntergeladene Zertifikat nur an, wenn es das betroffene Zertifikat wirklich ausgestellt hat (die Unterschrift wird geprüft). Alles andere verwirft Tessera; Sie sehen dann einen Hinweis, dass die Adresse kein passendes Zertifikat geliefert hat.
- **Nur öffentliche Adressen.** Adressen im eigenen Firmennetz oder auf dem Tessera-Server selbst ruft Tessera nie ab, ebenso keine Adressen mit besonderen Anschlussnummern oder Zugangsdaten. Dafür gibt es dann den Hinweis, dass die Adresse nicht abgerufen wird.
- **Gekennzeichnet als „nachgeladen“.** Das geholte Zertifikat erscheint in der Liste im Reiter „Dateien“ als eigener Eintrag mit dem Vermerk „nachgeladen von“ und dem Namen des Servers, ebenso auf seiner Karte im Reiter „Analysieren“. Wie jeden anderen Eintrag können Sie ihn mit dem Knopf am Eintrag wieder entfernen.
- **Unter Umständen ein zweiter Klick.** Ein Klick holt genau eine Stufe. Fehlt über dem geholten Zwischenzertifikat noch ein weiteres (zum Beispiel das Stammzertifikat), erscheint an dieser Stelle der Knopf erneut, und Sie können noch einmal klicken. Das Stammzertifikat brauchen Sie für eine Fullchain meist nicht.
- **Wenn es nicht klappt.** Ist der Server des Ausstellers nicht erreichbar (zum Beispiel, weil der Tessera-Server selbst keinen Zugang zum Internet hat), meldet Tessera das. Laden Sie das Zertifikat dann beim Aussteller herunter und fügen Sie es im Reiter „Dateien“ hinzu. Steht im Zertifikat gar keine Adresse, gibt es keinen Knopf, sondern nur diesen Hinweis.
Unterstützte Eingaben sind unter anderem `.pem`, `.crt`, `.cer`, `.der`, `.pfx`, `.p12`, `.p7b`, `.p7c`, Schlüssel (`.key`, PKCS#1, PKCS#8 und SEC1, im Text oder binär, mit und ohne Passwort), Zertifikatsanfragen (`.csr`) und ZIP-Dateien. Tessera erkennt Dateien an ihrem Inhalt, nicht an der Endung, sodass auch eine Datei ohne passende Endung geöffnet wird. Zertifikate und Schlüssel mit elliptischen Kurven (EC) werden ebenso verarbeitet wie RSA.
### Domaincheck
+2 -1
View File
@@ -201,7 +201,7 @@ Das Modul „Dateien“ spricht aus dem `api`-Container mit der Nextcloud der In
Das Modul „Zertifikat-Manager“ braucht keine Einstellungen und keine eigene Konfiguration. Es speichert nichts: Zertifikate, Schlüssel und Passwörter kommen mit jeder Anfrage aus dem Browser, werden im Arbeitsspeicher des `api`-Containers verarbeitet und nicht in der Datenbank oder in Protokollen abgelegt. Für den Betrieb gilt:
- **Größe der Anfragen:** Die Dateien gehen über `/api-proxy` an die API. Eine einzelne Analyse schickt höchstens 10 MB (höchstens 30 Dateien, je Datei bis 5 MB). Die Voraussetzung am Proxy ist dieselbe wie im Abschnitt „Dateien (Nextcloud)“: `client_max_body_size` von mindestens `10m`. Beim Herunterladen eines Ergebnisses schickt der Browser nur Zertifikate und höchstens einen Schlüssel als JSON, höchstens 512 KiB je Anfrage (Tessera legt für genau diese Anfrage eine eigene Grenze fest, alle anderen JSON-Anfragen bleiben bei 100 kB).
- **Ausgehender Zugriff:** Der Zertifikat-Manager ruft von sich aus nichts im Internet ab.
- **Ausgehender Zugriff:** Der Zertifikat-Manager ruft von sich aus nichts im Internet ab. Eine Ausnahme gibt es: Klickt ein Benutzer auf „Fehlendes Zertifikat holen“, schickt der `api`-Container eine einzelne Anfrage an die Adresse, die im Zertifikat als Aussteller-Adresse steht (meist `http://`, selten `https://`). Dafür muss der `api`-Container ausgehend per HTTP und HTTPS (Ports 80 und 443) ins Internet kommen; andere Ports ruft Tessera nie ab. Ist das ausgehend gesperrt (Firewall, Proxy-Pflicht), meldet der Knopf „nicht erreichbar“, alles andere im Modul funktioniert weiter, und die Benutzer laden das Zertifikat selbst herunter. Tessera ruft dabei nur öffentliche Adressen ab (keine internen Rechner, keine Adressen des eigenen Netzes), prüft die Adresse im Moment des Verbindens noch einmal, folgt höchstens drei Weiterleitungen, begrenzt Wartezeit (8 Sekunden) und Antwortgröße (256 KiB) und übernimmt nur ein Zertifikat, das das betroffene Zertifikat wirklich ausgestellt hat. Im Protokoll steht bei einem Fehler genau eine Zeile mit dem Servernamen und einem Fehlercode, nie ein Zertifikat.
- **Rechenaufwand:** Passwortgeschützte PFX-Dateien und verschlüsselte Schlüssel öffnet Tessera mit den eingegebenen Passwörtern (je Datei höchstens zehn verschiedene Versuche); das kostet kurz Rechenzeit, belastet den Server aber nicht dauerhaft.
## 4. Neue Fassung einspielen
@@ -774,5 +774,6 @@ Für die Desktop-Auslieferung ist keine neue Pflichtvariable nötig.
| Eine Fehlermeldung aus der Desktop-App nennt als Herkunft „Desktop-App (unbekannt)“ ohne Version, Betreff-Kürzel `[Desktop]` | Der Client ist älter als diese Fassung: er meldet dem Server beim Start nur `desktop=1`, nicht Version, Stand und Betriebssystem (Parameter `dv`, `dc`, `dos`, aus denen `web` das Cookie `tessera_desktop_client` bildet) | Kein Fehler, die Meldung ist trotzdem als Desktop-App erkennbar. Client über „Auf Version … aktualisieren“ im Infobereich oder den Browser-Installer aktualisieren; danach stehen Betriebssystem, Version und Stand in der Meldung. |
| Beim Hochladen in „Dateien“ bricht jede größere Datei beim ersten 8-MB-Stück ab (Fehler „Die Verbindung wurde unterbrochen“, im Proxy-Protokoll `413`) | Der Proxy vor Tessera (Nginx Proxy Manager) lässt keine Anfragen über seiner Größengrenze durch (`client_max_body_size`), oder sein Zeitlimit ist zu kurz | Für die Tessera-Adresse `client_max_body_size` auf mindestens `10m` und die Lese-/Sendezeitlimits auf mindestens 120 Sekunden stellen (Kapitel 3, Abschnitt „Dateien (Nextcloud)“). |
| Im Zertifikat-Manager bricht das Hochladen mehrerer Dateien ab (Fehlertext „Die Dateien sind zusammen zu groß“ oder `413` im Proxy-Protokoll) | Der Proxy vor Tessera (Nginx Proxy Manager) lässt Anfragen über seiner Größengrenze nicht durch (`client_max_body_size`); die Analyse schickt bis zu 10 MB | Für die Tessera-Adresse `client_max_body_size` auf mindestens `10m` stellen (Kapitel 3, Abschnitt „Dateien (Nextcloud)“); Tessera selbst erlaubt höchstens 20 MB je Analyse. |
| Im Zertifikat-Manager meldet „Fehlendes Zertifikat holen“, der Server des Ausstellers sei nicht erreichbar | Der `api`-Container kommt ausgehend nicht per HTTP/HTTPS (Ports 80 und 443) ins Internet, oder der Server des Ausstellers antwortet nicht; steht die Meldung, die Adresse werde nicht abgerufen, zeigt die Adresse im Zertifikat auf einen internen Rechner oder einen besonderen Anschluss, was Tessera absichtlich nie abruft | Ausgehenden Zugriff für den `api`-Container freigeben (`docker compose exec api node -e "fetch('http://ye2.i.lencr.org/').then(r=>console.log(r.status))"` muss `200` ausgeben); sonst das Zertifikat beim Aussteller herunterladen und im Reiter „Dateien“ hinzufügen. |
| In „Dateien“ tragen öffentliche Links eine interne Adresse (zum Beispiel ein interner Rechnername oder eine IP-Adresse) und lassen sich von außen nicht öffnen | Die Nextcloud baut die Adresse eines Links aus dem Namen, unter dem Tessera sie aufruft; in Tessera ist die interne Adresse der Nextcloud eingetragen | In den Einstellungen des Moduls die von außen erreichbare Adresse der Nextcloud eintragen, oder in der `config.php` der Nextcloud `overwritehost`, `overwriteprotocol` und `overwrite.cli.url` auf die externe Adresse setzen; bereits erstellte Links ändern sich nicht rückwirkend, sie müssen neu erstellt werden. |
| In „Dateien“ erscheint „Sie haben in kurzer Zeit viele Freigaben angelegt. Bitte warten Sie einige Minuten.“ | Tessera hat für den Benutzer 10 neue Freigaben innerhalb von 10 Minuten angelegt oder mehr als 40 Versuche in 10 Minuten gezählt (auch abgelehnte) | Einige Minuten abwarten (der Zähler läuft nach 10 Minuten ab); ein Neustart des `api`-Containers setzt den Zähler zurück, ist aber nur im Ausnahmefall nötig. |
+33
View File
@@ -942,3 +942,36 @@ Schlüssel der CAs werden nach der Erzeugung gelöscht). Dateinamen enden **nie*
`-key-….der`. Die Specs lesen die Dateien mit `readFileSync` und rufen OpenSSL nie auf (die CI hat
es nicht); die Live-Prüfung mit OpenSSL-Gegenprobe (`openssl verify`, `pkcs12 -info`,
`pkcs7 -print_certs`, `pkey`) liegt im Skript `e2e-cert.sh` der Aufgabe.
*Fehlendes Zertifikat holen und der gemeinsame Adressschutz.* `POST fetch-issuer` (`cert-aia.ts`,
`dto/cert-fetch-issuer.dto.ts`) nimmt **nur** `pem`; die Adresse liest der Server selbst aus dem
Zertifikat (`toLegacyObject().infoAccess['CA Issuers - URI']`), der Browser nennt nie eine
(die `ValidationPipe` mit `whitelist` entfernt jedes weitere Feld, das Controller-Spec prüft es).
Es werden höchstens drei Adressen der Reihe nach versucht: nur `http`/`https`, ohne
Zugangsdaten, höchstens 2048 Zeichen, nur der Standardport (ein Abruf auf `:8080` ist ein
Portscanner). Die Schleife ist die von `nextcloud-status/nextcloud-logo-fetch.ts` (Adressschutz vor
der ersten Anfrage und vor jeder Weiterleitung, `redirect: 'manual'`, höchstens drei Sprünge, ein
Zeitlimit von 8 s mit Wette gegen den Abbruch, 256 KiB, `content-length` vorab und beim Lesen), dazu
zwei Unterschiede: Erstens läuft der echte Abruf über einen eigenen `undici`-`Agent`, dessen
`connect.lookup` (`createGuardedLookup`) jede aufgelöste Adresse prüft und bei einer nicht
öffentlichen abbricht. Das schließt für diese Funktion das DNS-Rebinding-Fenster, das die anderen
Nutzer des Adressschutzes bewusst offen lassen (Name wird vorher aufgelöst und beim Verbinden noch
einmal). Zweitens wird eine Antwort nur angenommen, wenn `target.checkIssued(c)` **und**
`target.verify(c.publicKey)` gelten (DER-Zertifikat, PKCS#7 als DER oder PEM, PEM-Text; sonst
`aiaNotIssuer`). Der bewusst akzeptierte Rest steht im Kopfkommentar von `cert-aia.ts`: Jeder
angemeldete Benutzer des Moduls kann den API-Server dazu bringen, einen einzigen GET an eine
öffentliche Adresse zu senden, die in einem von ihm hochgeladenen Zertifikat steht. Die Oberfläche
holt nie von selbst etwas (`ChainView`, Knopf), das geholte Zertifikat wird als Eintrag mit Herkunft
`fetched` und Server (`working-set.ts`, `addFetched`) angehängt und beim nächsten Durchlauf mit allem
anderen analysiert.
Der **gemeinsame Adressschutz** `common/public-url-guard.ts` (Favoriten-Symbole, Logo-Abruf von
Nextcloud-Status und dieser Abruf) wurde dafür gehärtet: `isPrivateIpv6` zerlegt eine Adresse
vollständig in acht Gruppen (`expandIpv6`) und erkennt damit auch versteckte Schreibweisen interner
Adressen, nämlich IPv4-gemappt in Hex-Form (`::ffff:7f00:1`), IPv4-kompatibel (`::7f00:1`), NAT64
(`64:ff9b::/96` nach eingebetteter IPv4, `64:ff9b:1::/48` immer), 6to4 (`2002::/16`), Teredo,
Dokumentationsbereiche, `100::/64`, Unique-Local, Link-Local (auch mit Zonenkennung `%eth0`),
Site-Local und Multicast; nicht lesbare Adressen bleiben gesperrt. `isPrivateIpAddress` ist jetzt
exportiert, das neue Spec `public-url-guard.spec.ts` prüft jede dieser Schreibweisen und
`isPublicHttpUrl` mit einer nachgebildeten Namensauflösung. Wer den Schutz erweitert, lässt die
Specs von `favorites` und `nextcloud-status` mitlaufen.