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.
This commit is contained in:
@@ -1,31 +1,24 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
# Ensure dependencies are installed
|
# DNS-Monitor v2.0 - Optimized for Synology/Docker stability
|
||||||
# We check for 'dig' specifically. If missing, we try to install bind-tools.
|
# Monitoring: Public IP vs. Cloudflare DNS (1.1.1.1)
|
||||||
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
|
|
||||||
|
|
||||||
# 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
|
if ! command -v curl >/dev/null 2>&1; then
|
||||||
echo "[DNS-MONITOR] 'curl' not found. Installing curl..."
|
|
||||||
apk add --no-cache curl
|
apk add --no-cache curl
|
||||||
fi
|
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
|
while true; do
|
||||||
# 1. Fetch Public IP (via external service)
|
# 1. Fetch Public IP
|
||||||
# We use -4 to force IPv4
|
PUBLIC_IP=$(curl -s -4 -m 15 https://api.ipify.org)
|
||||||
PUBLIC_IP=$(curl -s -4 -m 10 https://api.ipify.org)
|
|
||||||
|
|
||||||
if [ -z "$PUBLIC_IP" ]; then
|
if [ -z "$PUBLIC_IP" ]; then
|
||||||
PUBLIC_IP="Error: Could not fetch IP"
|
PUBLIC_IP="Error: Public IP fetch failed"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Get the first subdomain to check
|
# Get the first subdomain to check
|
||||||
@@ -36,32 +29,30 @@ while true; do
|
|||||||
else
|
else
|
||||||
FULL_DOMAIN="${FIRST_SUB}.duckdns.org"
|
FULL_DOMAIN="${FIRST_SUB}.duckdns.org"
|
||||||
|
|
||||||
# 2. Resolve Global IP (Google DNS @8.8.8.8) to check propagation
|
# 2. Resolve Global IP (Cloudflare 1.1.1.1)
|
||||||
# We look for the A record (IPv4)
|
# Using +time and +tries for high reliability on shaky connections
|
||||||
if command -v dig >/dev/null 2>&1; then
|
GLOBAL_IP=$(dig @1.1.1.1 +short +time=8 +tries=3 A "$FULL_DOMAIN" | head -n 1)
|
||||||
GLOBAL_IP=$(dig @8.8.8.8 +short A "$FULL_DOMAIN" | head -n 1)
|
|
||||||
LOCAL_IP=$(dig +short A "$FULL_DOMAIN" | head -n 1)
|
# 3. Resolve Local IP (Internal Docker/Host DNS)
|
||||||
else
|
# This checks if the local cache is still stuck
|
||||||
GLOBAL_IP="Error: dig missing"
|
LOCAL_IP=$(dig +short +time=8 +tries=3 A "$FULL_DOMAIN" | head -n 1)
|
||||||
LOCAL_IP="Error: dig missing"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -z "$GLOBAL_IP" ]; then GLOBAL_IP="Unresolved"; fi
|
if [ -z "$GLOBAL_IP" ]; then GLOBAL_IP="Unresolved"; fi
|
||||||
if [ -z "$LOCAL_IP" ]; then LOCAL_IP="Unresolved"; fi
|
if [ -z "$LOCAL_IP" ]; then LOCAL_IP="Unresolved"; fi
|
||||||
|
|
||||||
TIMESTAMP=$(date '+%Y-%m-%d %H:%M:%S')
|
TIMESTAMP=$(date '+%Y-%m-%d %H:%M:%S')
|
||||||
|
|
||||||
# Logic to determine status
|
# Status Logic
|
||||||
|
if [ "$PUBLIC_IP" = "$GLOBAL_IP" ]; then
|
||||||
STATUS="OK"
|
STATUS="OK"
|
||||||
if [ "$PUBLIC_IP" != "$GLOBAL_IP" ]; then
|
elif [ "$GLOBAL_IP" = "Unresolved" ]; then
|
||||||
STATUS="ALERT"
|
STATUS="NETWORK_WAIT" # Network or DNS provider issue, not necessarily DuckDNS
|
||||||
elif [ "$PUBLIC_IP" != "$LOCAL_IP" ]; then
|
else
|
||||||
# If Global is correct but Local is wrong, it's a local caching issue, still an alert but specific
|
STATUS="ALERT" # Public IP != Global IP (DuckDNS update missing or zombie active)
|
||||||
STATUS="CACHE_ALERT"
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Log format: Time | Status | Public vs Global vs Local
|
# Log entry
|
||||||
echo "[$TIMESTAMP] [DNS-MONITOR] $STATUS | Public: $PUBLIC_IP | Global(8.8.8.8): $GLOBAL_IP | Local: $LOCAL_IP"
|
echo "[$TIMESTAMP] [$STATUS] Pub: $PUBLIC_IP | CF: $GLOBAL_IP | Loc: $LOCAL_IP"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Check every 5 minutes
|
# Check every 5 minutes
|
||||||
|
|||||||
@@ -39,13 +39,17 @@ Dieser Container sorgt dafür, dass DuckDNS immer die aktuelle IP kennt.
|
|||||||
### 2. Der Monitor (Sidecar)
|
### 2. Der Monitor (Sidecar)
|
||||||
Dieser Container prüft alle 5 Minuten die DNS-Auflösung und schreibt das Ergebnis ins Log. Er vergleicht:
|
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).
|
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.
|
3. **Local DNS:** Die IP laut Container-Resolver -> Prüft lokales Caching.
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
dns-monitor:
|
dns-monitor:
|
||||||
image: alpine
|
image: alpine
|
||||||
container_name: dns-monitor
|
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:
|
environment:
|
||||||
- SUBDOMAINS=deine-subdomains
|
- SUBDOMAINS=deine-subdomains
|
||||||
- TZ=Europe/Berlin
|
- 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`).
|
**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
|
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.
|
||||||
```bash
|
|
||||||
docker logs duckdns
|
|
||||||
```
|
|
||||||
|
|
||||||
### DNS-Konsistenz prüfen (WICHTIG!)
|
### 1. FritzBox DNS-Rebind-Schutz
|
||||||
Hier sehen wir, ob die Welt (bzw. der Container) die Domain korrekt auflöst.
|
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).
|
||||||
|
|
||||||
```bash
|
**Lösung:**
|
||||||
docker logs dns-monitor
|
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"**.
|
||||||
**Szenario OK:**
|
4. Dort **alle** genutzten Subdomains eintragen (eine pro Zeile):
|
||||||
```text
|
```text
|
||||||
[TIMESTAMP] [DNS-MONITOR] OK | Public: 87.x.x.x | Global(8.8.8.8): 87.x.x.x | Local: 87.x.x.x
|
floke.duckdns.org
|
||||||
|
floke-ai.duckdns.org
|
||||||
|
floke-gitea.duckdns.org
|
||||||
|
floke-ha.duckdns.org
|
||||||
|
floke-n8n.duckdns.org
|
||||||
|
duckdns.org
|
||||||
```
|
```
|
||||||
Alles synchron.
|
5. Speichern.
|
||||||
|
|
||||||
**Szenario ALERT (Zombie-Updater / Propagation):**
|
### 2. Client DNS Cache leeren
|
||||||
```text
|
Nach Änderungen an DuckDNS oder der FritzBox halten Windows-Clients oft noch stundenlang an der alten IP fest.
|
||||||
[TIMESTAMP] [DNS-MONITOR] ALERT | Public: 87.x.x.x | Global(8.8.8.8): 87.y.y.y | Local: 87.y.y.y
|
|
||||||
|
**Lösung (Windows CMD als Admin):**
|
||||||
|
```cmd
|
||||||
|
ipconfig /flushdns
|
||||||
|
ping floke.duckdns.org
|
||||||
```
|
```
|
||||||
Dies deutet darauf hin, dass entweder die Propagation noch läuft oder ein anderes Gerät (FritzBox, HA) die IP überschreibt.
|
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.
|
||||||
|
|
||||||
**Szenario CACHE_ALERT (Lokales Problem):**
|
## Troubleshooting
|
||||||
```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).
|
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:**
|
**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.
|
4. `docker-compose up -d duckdns` ausführen.
|
||||||
5. Damit werden alle alten Updater ausgesperrt.
|
5. Damit werden alle alten Updater ausgesperrt.
|
||||||
|
|
||||||
|
### Logs prüfen
|
||||||
|
**Update-Status:** `docker logs duckdns`
|
||||||
|
**DNS-Konsistenz:** `docker logs dns-monitor`
|
||||||
|
|
||||||
## Dateien
|
## Dateien
|
||||||
- `/app/docker-compose.yml`: Definition der Services.
|
- `/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.
|
||||||
Reference in New Issue
Block a user