From 8b9dfb2d2c1e18f9f4f7b4094a212377542334a5 Mon Sep 17 00:00:00 2001 From: Floke Date: Tue, 6 Jan 2026 13:19:32 +0000 Subject: [PATCH] Docs: Add FritzBox Rebind Protection & Client Troubleshooting guides. - Updated 'duckdns_setup.md' with critical instructions for configuring FritzBox DNS Rebind Protection to enable internal access (NAT Loopback). - Added steps for clearing client-side DNS cache (Windows). - Included Cloudflare DNS switch in documentation reflecting recent monitor script changes. --- dns-monitor/monitor.sh | 63 ++++++++++++++++-------------------- duckdns_setup.md | 72 ++++++++++++++++++++++++------------------ 2 files changed, 68 insertions(+), 67 deletions(-) diff --git a/dns-monitor/monitor.sh b/dns-monitor/monitor.sh index 07f330df..116da8a4 100644 --- a/dns-monitor/monitor.sh +++ b/dns-monitor/monitor.sh @@ -1,31 +1,24 @@ #!/bin/sh -# Ensure dependencies are installed -# We check for 'dig' specifically. If missing, we try to install bind-tools. -if ! command -v dig >/dev/null 2>&1; then - echo "[DNS-MONITOR] 'dig' not found. Installing bind-tools..." - if apk add --no-cache bind-tools; then - echo "[DNS-MONITOR] bind-tools installed successfully." - else - echo "[DNS-MONITOR] ERROR: Failed to install bind-tools. Check internet connection or repo mirrors." - fi -fi +# DNS-Monitor v2.0 - Optimized for Synology/Docker stability +# Monitoring: Public IP vs. Cloudflare DNS (1.1.1.1) -# Ensure curl is installed (though it seems to be present based on logs) +# Ensure dependencies +if ! command -v dig >/dev/null 2>&1; then + apk add --no-cache bind-tools +fi if ! command -v curl >/dev/null 2>&1; then - echo "[DNS-MONITOR] 'curl' not found. Installing curl..." apk add --no-cache curl fi -echo "[DNS-MONITOR] Service started. Monitoring $SUBDOMAINS every 5 minutes..." +echo "[DNS-MONITOR] Service started. Monitoring $SUBDOMAINS via Cloudflare (1.1.1.1)" while true; do - # 1. Fetch Public IP (via external service) - # We use -4 to force IPv4 - PUBLIC_IP=$(curl -s -4 -m 10 https://api.ipify.org) + # 1. Fetch Public IP + PUBLIC_IP=$(curl -s -4 -m 15 https://api.ipify.org) if [ -z "$PUBLIC_IP" ]; then - PUBLIC_IP="Error: Could not fetch IP" + PUBLIC_IP="Error: Public IP fetch failed" fi # Get the first subdomain to check @@ -36,34 +29,32 @@ while true; do else FULL_DOMAIN="${FIRST_SUB}.duckdns.org" - # 2. Resolve Global IP (Google DNS @8.8.8.8) to check propagation - # We look for the A record (IPv4) - if command -v dig >/dev/null 2>&1; then - GLOBAL_IP=$(dig @8.8.8.8 +short A "$FULL_DOMAIN" | head -n 1) - LOCAL_IP=$(dig +short A "$FULL_DOMAIN" | head -n 1) - else - GLOBAL_IP="Error: dig missing" - LOCAL_IP="Error: dig missing" - fi + # 2. Resolve Global IP (Cloudflare 1.1.1.1) + # Using +time and +tries for high reliability on shaky connections + GLOBAL_IP=$(dig @1.1.1.1 +short +time=8 +tries=3 A "$FULL_DOMAIN" | head -n 1) + + # 3. Resolve Local IP (Internal Docker/Host DNS) + # This checks if the local cache is still stuck + LOCAL_IP=$(dig +short +time=8 +tries=3 A "$FULL_DOMAIN" | head -n 1) if [ -z "$GLOBAL_IP" ]; then GLOBAL_IP="Unresolved"; fi if [ -z "$LOCAL_IP" ]; then LOCAL_IP="Unresolved"; fi TIMESTAMP=$(date '+%Y-%m-%d %H:%M:%S') - # Logic to determine status - STATUS="OK" - if [ "$PUBLIC_IP" != "$GLOBAL_IP" ]; then - STATUS="ALERT" - elif [ "$PUBLIC_IP" != "$LOCAL_IP" ]; then - # If Global is correct but Local is wrong, it's a local caching issue, still an alert but specific - STATUS="CACHE_ALERT" + # Status Logic + if [ "$PUBLIC_IP" = "$GLOBAL_IP" ]; then + STATUS="OK" + elif [ "$GLOBAL_IP" = "Unresolved" ]; then + STATUS="NETWORK_WAIT" # Network or DNS provider issue, not necessarily DuckDNS + else + STATUS="ALERT" # Public IP != Global IP (DuckDNS update missing or zombie active) fi - # Log format: Time | Status | Public vs Global vs Local - echo "[$TIMESTAMP] [DNS-MONITOR] $STATUS | Public: $PUBLIC_IP | Global(8.8.8.8): $GLOBAL_IP | Local: $LOCAL_IP" + # Log entry + echo "[$TIMESTAMP] [$STATUS] Pub: $PUBLIC_IP | CF: $GLOBAL_IP | Loc: $LOCAL_IP" fi # Check every 5 minutes sleep 300 -done +done \ No newline at end of file diff --git a/duckdns_setup.md b/duckdns_setup.md index 8442c552..cfed7627 100644 --- a/duckdns_setup.md +++ b/duckdns_setup.md @@ -39,13 +39,17 @@ Dieser Container sorgt dafür, dass DuckDNS immer die aktuelle IP kennt. ### 2. Der Monitor (Sidecar) Dieser Container prüft alle 5 Minuten die DNS-Auflösung und schreibt das Ergebnis ins Log. Er vergleicht: 1. **Public IP:** Die tatsächliche externe IP (via ipify). -2. **Global DNS:** Die IP laut Google DNS (8.8.8.8) -> Prüft Internet-Propagation. +2. **Global DNS:** Die IP laut Cloudflare DNS (1.1.1.1) -> Prüft Internet-Propagation (Google 8.8.8.8 erwies sich als zu langsam/unzuverlässig). 3. **Local DNS:** Die IP laut Container-Resolver -> Prüft lokales Caching. ```yaml dns-monitor: image: alpine container_name: dns-monitor + # Explizite DNS-Server im Container setzen, um Synology-Timeouts zu umgehen: + dns: + - 8.8.8.8 + - 1.1.1.1 environment: - SUBDOMAINS=deine-subdomains - TZ=Europe/Berlin @@ -57,39 +61,41 @@ Dieser Container prüft alle 5 Minuten die DNS-Auflösung und schreibt das Ergeb **Wichtig:** Das Skript `monitor.sh` liegt im Host-Verzeichnis `/app/dns-monitor/` und installiert zur Laufzeit fehlende Pakete (`bind-tools`, `curl`). -## Logs & Monitoring +## Peripherie-Konfiguration (FritzBox / Router) -### Update-Status prüfen -```bash -docker logs duckdns +Damit die Dienste auch aus dem **internen Netzwerk (WLAN/LAN)** erreichbar sind, müssen Router-Einstellungen angepasst werden. Ohne diese Anpassungen blockiert der Router den Zugriff auf die eigene externe IP ("NAT Loopback" Problem) oder Clients cachen alte IPs. + +### 1. FritzBox DNS-Rebind-Schutz +Die FritzBox blockiert standardmäßig DNS-Antworten, die auf private IP-Adressen zeigen (Rebind-Schutz). Dies verhindert oft auch das korrekte "Hairpinning" (Zugriff auf eigene externe IP von innen). + +**Lösung:** +1. FritzBox Oberfläche öffnen (`http://fritz.box`). +2. Navigieren zu: **Heimnetz** -> **Netzwerk** -> Reiter **Netzwerkeinstellungen**. +3. Ganz unten (ggf. "weitere Einstellungen" aufklappen) zu **"DNS-Rebind-Schutz"**. +4. Dort **alle** genutzten Subdomains eintragen (eine pro Zeile): + ```text + floke.duckdns.org + floke-ai.duckdns.org + floke-gitea.duckdns.org + floke-ha.duckdns.org + floke-n8n.duckdns.org + duckdns.org + ``` +5. Speichern. + +### 2. Client DNS Cache leeren +Nach Änderungen an DuckDNS oder der FritzBox halten Windows-Clients oft noch stundenlang an der alten IP fest. + +**Lösung (Windows CMD als Admin):** +```cmd +ipconfig /flushdns +ping floke.duckdns.org ``` +Der Ping muss die aktuelle **externe IP** (z.B. `.252`) zurückgeben, nicht die alte. Wenn er die externe IP zeigt und `<1ms` Antwortzeit hat, funktioniert das NAT-Loopback korrekt. -### DNS-Konsistenz prüfen (WICHTIG!) -Hier sehen wir, ob die Welt (bzw. der Container) die Domain korrekt auflöst. +## Troubleshooting -```bash -docker logs dns-monitor -``` - -**Szenario OK:** -```text -[TIMESTAMP] [DNS-MONITOR] OK | Public: 87.x.x.x | Global(8.8.8.8): 87.x.x.x | Local: 87.x.x.x -``` -Alles synchron. - -**Szenario ALERT (Zombie-Updater / Propagation):** -```text -[TIMESTAMP] [DNS-MONITOR] ALERT | Public: 87.x.x.x | Global(8.8.8.8): 87.y.y.y | Local: 87.y.y.y -``` -Dies deutet darauf hin, dass entweder die Propagation noch läuft oder ein anderes Gerät (FritzBox, HA) die IP überschreibt. - -**Szenario CACHE_ALERT (Lokales Problem):** -```text -[TIMESTAMP] [DNS-MONITOR] CACHE_ALERT | Public: 87.x.x.x | Global(8.8.8.8): 87.x.x.x | Local: 87.y.y.y -``` -Das Internet kennt die neue IP schon, aber lokal wird noch die alte gecacht. - -## Troubleshooting: "IP Flapping" (Zombie-Updater) +### "IP Flapping" (Zombie-Updater) Wenn die IP im Monitor ständig zwischen der aktuellen (`...252`) und einer alten (`...49`) springt, gibt es einen zweiten Updater im Netzwerk (z.B. Router, Home Assistant, alte Skripte). **Lösung:** @@ -99,6 +105,10 @@ Wenn die IP im Monitor ständig zwischen der aktuellen (`...252`) und einer alte 4. `docker-compose up -d duckdns` ausführen. 5. Damit werden alle alten Updater ausgesperrt. +### Logs prüfen +**Update-Status:** `docker logs duckdns` +**DNS-Konsistenz:** `docker logs dns-monitor` + ## Dateien - `/app/docker-compose.yml`: Definition der Services. -- `/app/dns-monitor/monitor.sh`: Das Shell-Skript für den Monitor-Container. +- `/app/dns-monitor/monitor.sh`: Das Shell-Skript für den Monitor-Container. \ No newline at end of file