Skip to content

fix(portal,tls): DNS-Prüfung des zusammengesetzten Portal-Hosts + Verwaltungs-Host in TLS-Automation - #231

Merged
CallMeTechie merged 2 commits into
masterfrom
fix/portal-host-dns-acme
Jul 25, 2026
Merged

fix(portal,tls): DNS-Prüfung des zusammengesetzten Portal-Hosts + Verwaltungs-Host in TLS-Automation#231
CallMeTechie merged 2 commits into
masterfrom
fix/portal-host-dns-acme

Conversation

@CallMeTechie

Copy link
Copy Markdown
Owner

Behebt zwei ACME-Defekte aus einem externen Bug-Report gegen 1.118.5.

1. Portal-Host wird ohne DNS-Prüfung übernommen → 30-Tage-ACME-Schleife

validatePortalHost prüfte via domains.isVerified(base) nur den gespeicherten Status der Basisdomain. Der eigentlich genutzte Host <präfix>.<basis> wurde erst danach zusammengesetzt und nur noch auf Kollisionen geprüft — nie aufgelöst. Dass example.com einen A-Eintrag hat, sagt nichts über home.example.com.

Folge: Der nicht auflösbare Host ging in buildTlsAutomation, bekam korrekt eine ACME-Policy, und Caddy versuchte mit max_duration = 2592000 (30 Tage) beim produktiven Let's-Encrypt-CA zu validieren. Let's Encrypt erlaubt 5 fehlgeschlagene Prüfungen pro Konto/Hostname/Stunde — im Report nach ~15 Minuten erschöpft, und die Schleife bewaffnet das einen Monat lang immer neu. Im UI gab es dazu keinerlei Rückmeldung.

Fix: Der zusammengesetzte Host geht durch dasselbe domains.verify(), das die Domain-Registry schon benutzt (Auflösung + Vergleich mit getServerPublicIp()).

  • status === 'failed' (NXDOMAIN oder fremde IP) → 400 mit eigenem Key settings.portal.host_unresolved, der sagt, welcher Eintrag fehlt.
  • status === 'pending' (unser Resolver ist nicht erreichbar) blockiert nicht — wir können nichts entscheiden, also verweigern wir auch nichts.
  • Ist das Präfix leer, ist der Host die bereits verifizierte Basis → kein zweiter Roundtrip.

validatePortalHost ist dadurch async; der einzige Aufrufer (routes/api/settings/portal.js) wurde angepasst.

2. Verwaltungs-Host fehlte in der TLS-Automation (eigener Defekt, gleicher Bereich)

caddyConfig.js baut die TLS-Automation, bevor der Host aus GC_BASE_URL in caddyRoutes eingehängt wird. Bei leerer Routen-Tabelle enthielt die übergebene Domain-Liste damit nur homeHost — der Verwaltungs-Host bekam nie eine explizite Policy und fiel auf Caddys Standard-Automation zurück: ein ACME-Konto ohne Kontaktadresse, obwohl GC_CADDY_EMAIL gesetzt ist. Ergebnis sind zwei LE-Konten auf derselben Installation und keine Ablaufbenachrichtigungen für das Zertifikat des Admin-UI.

gcHost wird jetzt genauso ausdrücklich übergeben wie homeHost — der vorhandene Kommentar nannte für homeHost bereits exakt diesen Grund. Die Liste läuft zusätzlich durch ein Set, damit ein Host, der zugleich Route und Verwaltungs-Host ist, nicht doppelt als Subject landet (buildTlsAutomation dedupliziert nur den privaten Zweig).

Tests

Neu, alle ohne den Fix rot verifiziert:

  • tests/portal_host_helper.test.js: NXDOMAIN → unresolved, fremde IP → unresolved, Resolver-Timeout → durchgelassen, Apex-Fall löst nicht erneut auf.
  • tests/portal_settings_host.test.js: PUT mit unauflösbarem Host → 400, und nichts wird persistiert.
  • tests/caddy_tls_management_host.test.js: Verwaltungs-Host bekommt eine ACME-Policy mit Kontaktadresse; kein doppeltes Subject, wenn eine Route denselben Host bedient.

Die bestehenden Portal-Host-Tests liefen bislang zufällig über den pending-Pfad durch (in der Harness ist keine Server-IP ermittelbar). Sie stubben jetzt server.public_ip und den Resolver explizit und fassen kein Netz mehr an.

Volle Suite: 2305/2308 grün. Der eine Fehlschlag (POST /api/v1/peers … requires wg) besteht unverändert auch ohne diesen Branch — die Umgebung hat kein WireGuard.

Nicht enthalten

Der Report schlägt zusätzlich vor, die ACME-Policy zurückzuhalten, bis der Name auflöst (zweite Verteidigungslinie), bzw. GC_CADDY_ACME_CA bis zur ersten erfolgreichen Auflösung auf Staging zu pinnen. Beides ist hier bewusst weggelassen: validatePortalHost ist der einzige Weg, auf dem portal.base_domain gesetzt wird, die Prüfung sitzt also bereits an der einzigen Stelle, durch die alle Aufrufer laufen. Sinnvoll wird die zweite Linie erst, wenn ein DNS-Eintrag nach dem Speichern wegfällt — das wäre ein eigener Punkt (periodische Re-Verifizierung des Portal-Hosts).

Bestehende Installationen mit bereits gesetztem, kaputtem Portal-Host repariert dieses Update nicht rückwirkend — die Prüfung greift beim Speichern. Dort weiterhin: A-Eintrag anlegen oder die Basisdomain im Portal leeren.

🤖 Generated with Claude Code

https://claude.ai/code/session_01QwdEvuCYgxfjkGdkcPM4vJ

…waltungs-Host in TLS-Automation

Zwei ACME-Defekte aus einem externen Bug-Report (1.118.5):

1. validatePortalHost prüfte nur die DNS-Verifizierung der Basisdomain,
   nie den daraus gebauten Host <präfix>.<basis>. Ohne dessen A/AAAA-Eintrag
   ging er trotzdem in buildTlsAutomation und Caddy versuchte 30 Tage lang
   (max_duration) beim produktiven Let's-Encrypt-CA ein Zertifikat zu holen —
   das Limit von 5 fehlgeschlagenen Prüfungen/Stunde/Hostname war sofort
   erschöpft, ohne Rückmeldung im UI. Der Host wird jetzt selbst aufgelöst
   (domains.verify) und mit der Server-IP verglichen; Status 'failed' → 400
   mit eigenem Fehlertext host_unresolved. 'pending' (Resolver nicht
   erreichbar) blockiert bewusst nicht, und der Apex-Fall (leeres Präfix)
   spart den zweiten Roundtrip.

2. Der Verwaltungs-Host aus GC_BASE_URL erreichte buildTlsAutomation nie,
   weil seine Route erst danach in caddyRoutes eingehängt wird. Er fiel
   damit auf Caddys Standard-Automation zurück — ein ACME-Konto ohne
   Kontaktadresse trotz gesetztem GC_CADDY_EMAIL, also keine
   Ablaufbenachrichtigungen. Er wird jetzt wie homeHost ausdrücklich
   übergeben; die Domain-Liste ist dedupliziert, damit ein Host, der
   zugleich Route ist, nicht doppelt als Subject auftaucht.

Regressionstests für beide Defekte (ohne Fix rot), bestehende
Portal-Host-Tests auf den nun asynchronen Validator umgestellt und ihren
Resolver gestubbt (liefen vorher zufällig über den 'pending'-Pfad durch).
Comment thread tests/caddy_tls_management_host.test.js Fixed
@CallMeTechie
CallMeTechie merged commit 3015046 into master Jul 25, 2026
8 checks passed
@CallMeTechie
CallMeTechie deleted the fix/portal-host-dns-acme branch July 25, 2026 21:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants