Ich bin in das gleiche Problem gelaufen und habe mal was gebastelt, vielleicht hilft es ja.
0. Problem
Ich habe einen Glasfaseranschluss bekommen und konnte von extern nicht mehr auf mein Home Assistant zugreifen, da zwar vom DuckDNS Add-one eine IPv4 Adresse eingetragen wurde, diese aber nicht über IPv6 aufgelöst werden kann.
1. Ziel / TL;DR
Ziel: Home Assistant (HA) hinter einem DS-Lite-Anschluss von außen erreichbar machen – ohne:
-
öffentliche IPv4
-
Nabu Casa
-
Cloudflare-Tunnel
Stattdessen nur mit:
Kernidee:
So bleibt HA dauerhaft über https://deine-ha-subdomain.duckdns.org:8123 erreichbar, obwohl sich das IPv6-Präfix ändert und keine IPv4-Adresse vorhanden ist.
2. Ausgangslage / Voraussetzungen
Typisches Setup:
DynDNS / Dienste:
Außerdem:
-
Zugriff auf das Webinterface des Routers (z.B. FritzBox)
-
Zugriff auf das HA-Dateisystem (/config) + Terminal/Shell in HA
-
Tools im HA-Container: ip, nslookup, curl (normalerweise vorhanden)
Wichtig: IPv6 muss auf dem HA-Interface aktiv sein. Ob in der UI „Statisch“ oder „Automatisch“ ausgewählt ist, ist für das Skript zweitrangig – im beschriebenen Setup steht es auf „Statisch“, die extern erreichbare GUA wird aber vom Skript gesetzt.
3. Grundprinzip
Wir trennen Router-DNS und HA-DNS:
-
Router-DuckDNS (z.B. meinrouter123.duckdns.org):
zeigt auf die aktuelle WAN-IPv6 des Routers (vom Router selbst aktualisiert).
-
HA-DuckDNS (z.B. meinha123.duckdns.org):
zeigt auf die aktuelle globale IPv6 des HA-Geräts im LAN (vom HA-Skript aktualisiert).
Ein Skript auf HA macht:
-
AAAA-Lookup auf meinrouter123.duckdns.org → WAN-IPv6 des Routers, z.B.
2001:db8:1111:1000::1
-
berechnet aus dem 4. Block des Präfixes +1 → LAN-PREFIX, z.B.
2001:db8:1111:1001::/64
-
hängt ein stabiles Suffix (Interface-ID) an → Ziel-GUA LAN-PREFIX:SUFFIX, z.B.
2001:db8:1111:1001:1234:5678:9abc:def0
-
löscht auf dem HA-Interface alle bestehenden globalen IPv6-Adressen
-
fügt genau diese Ziel-GUA hinzu
-
testet per HTTP, ob HA unter http://[Ziel-IP]:8123 antwortet
-
aktualisiert meinha123.duckdns.org mit dieser Ziel-IPv6
Die Portfreigabe im Router zeigt auf das Gerät bzw. dessen Interface-ID; da wir genau diese ID verwenden, passt alles zusammen.
4. Router vorbereiten (z.B. FritzBox)
4.1 IPv6 aktivieren
Im Router-Webinterface (z.B. FritzBox):
4.2 Stabile Interface-ID für Home Assistant setzen
Im Bereich „Heimnetz / Netzwerk“ bzw. „LAN-Geräte“:
-
HA-Gerät auswählen → Bearbeiten
-
Im Bereich IPv6:
-
Diese letzten vier Blöcke (1234:5678:9abc:def0) sind der stabile Suffix für HA.
-
Einmal sinnvoll setzen und danach nicht mehr ändern.
Diese Interface-ID ist der Kern: Das Skript verwendet genau diesen Suffix, um die globale IPv6 zusammenzubauen.
4.3 DynDNS für den Router (Router-Domain)
Im Router-Webinterface:
-
Bereich ähnlich „Internet → Freigaben → DynDNS“
-
Anbieter: „Anderer Anbieter“ (oder direkt DuckDNS, falls vorhanden)
-
Beispiel Update-URL:
https://www.duckdns.org/update?domains=meinrouter123&token=DEIN_DUCKDNS_TOKEN&ipv6=<ip6addr>
Ab jetzt zeigt meinrouter123.duckdns.org immer auf die aktuelle WAN-IPv6 des Routers.
4.4 IPv6-Portfreigabe für Home Assistant
Im Router-Webinterface:
Der Router leitet damit eingehende IPv6-Verbindungen an 2001:db8:1111:1001:1234:5678:9abc:def0 (bzw. das jeweils aktuelle Präfix + Suffix) weiter.
5. Home Assistant vorbereiten
5.1 IPv6 im HA-Netzwerk-Interface
In Home Assistant:
Die UI-Konfiguration (statische IP) ist aber weniger entscheidend, weil das Skript:
Wichtig:
-
IPv6 muss aktiv sein,
-
das Interface muss existieren,
-
und die Link-Local-Adresse (fe80::1234:5678:9abc:def0) sollte vorhanden sein – darüber findet das Skript das richtige Interface.
5.2 Ordner für Skripte
Im HA-Config-Ordner (/config) einen Unterordner anlegen, z.B.:
/config/bashscripts
6. Bash-Skripte
6.1 Hauptskript: update_ha_ipv6_from_duckdns.sh
Datei: /config/bashscripts/update_ha_ipv6_from_duckdns.sh
#!/usr/bin/env bash
set -euo pipefail
# === Einstellungen ===
ROUTER_DOMAIN="meinrouter123.duckdns.org" # DuckDNS-Domain des Routers (nur lesen!)
HA_DOMAIN="meinha123" # NUR Subdomain, ohne .duckdns.org
TOKEN="DEIN_DUCKDNS_TOKEN"
SUFFIX="1234:5678:9abc:def0" # stabiler Suffix aus Interface-ID im Router
PORT="8123"
# =====================
log() {
echo "[update_ha_ipv6] $*"
}
# 1) WAN-IPv6 des Routers von DuckDNS holen (AAAA)
WAN6=$(nslookup -type=AAAA "$ROUTER_DOMAIN" 8.8.8.8 2>/dev/null \
| awk '/Address: / {print $2}' \
| grep ':' \
| tail -n1 || true)
if [ -z "${WAN6:-}" ]; then
log "FEHLER: Konnte IPv6 für $ROUTER_DOMAIN nicht auflösen."
exit 1
fi
log "Router-WAN-IPv6: $WAN6"
# Beispiel: WAN6 = 2001:db8:1111:1000::1
# 2) LAN-Prefix aus WAN-IPv6 bauen (4. Block +1)
IFS=':' read -r r0 r1 r2 r3 _ <<< "$WAN6"
r3_int=$(( 0x$r3 + 1 ))
r3_lan=$(printf '%x' "$r3_int")
LAN_PREFIX="${r0}:${r1}:${r2}:${r3_lan}"
log "Erwarteter HA-LAN-Prefix: ${LAN_PREFIX}::/64"
# Beispiel: LAN_PREFIX = 2001:db8:1111:1001
# 3) Ziel-GUA aus Prefix + Suffix bauen
TARGET_IP="${LAN_PREFIX}:${SUFFIX}"
log "Ziel-HA-IPv6 (Prefix+Suffix): $TARGET_IP"
# Beispiel: TARGET_IP = 2001:db8:1111:1001:1234:5678:9abc:def0
# 4) Interface finden, auf dem die Link-Local mit diesem Suffix liegt
IFACE=$(ip -6 addr show | awk '
/^[0-9]+: / { iface=$2; sub(":", "", iface) } # Zeilen wie "2: eth0:" → iface=eth0
/fe80::'"$SUFFIX"'/ { print iface; exit } # Zeile mit fe80::SUFFIX → dieses iface ausgeben
')
if [ -z "${IFACE:-}" ]; then
log "FEHLER: Konnte Interface mit Link-Local fe80::${SUFFIX} nicht finden."
exit 1
fi
log "Verwendetes Interface: $IFACE"
# 5) ALLE globalen IPv6-Adressen auf diesem Interface löschen
CURRENT_ADDRS=$(ip -6 addr show dev "$IFACE" scope global | awk '/inet6/ {print $2}' | cut -d/ -f1)
if [ -n "${CURRENT_ADDRS:-}" ]; then
for addr in $CURRENT_ADDRS; do
log "Entferne alte globale Adresse $addr/64 von $IFACE"
ip -6 addr del "$addr/64" dev "$IFACE" || true
done
else
log "Keine bestehenden globalen IPv6-Adressen auf $IFACE gefunden."
fi
# 6) Neue Ziel-Adresse hinzufügen
log "Füge Adresse $TARGET_IP/64 zu $IFACE hinzu."
ip -6 addr add "$TARGET_IP/64" dev "$IFACE"
# 7) HTTP-Test auf neuer Adresse
log "Teste HTTP auf http://[$TARGET_IP]:$PORT/"
if curl -g -6 -s --connect-timeout 5 "http://[$TARGET_IP]:$PORT/" >/dev/null; then
log "HTTP-Test erfolgreich, aktualisiere DuckDNS für $HA_DOMAIN"
else
log "WARNUNG: HTTP-Test fehlgeschlagen – DuckDNS wird trotzdem aktualisiert."
fi
# 8) DuckDNS für HomeAssistant-Domain aktualisieren
UPDATE_URL="https://www.duckdns.org/update?domains=${HA_DOMAIN}&token=${TOKEN}&ipv6=${TARGET_IP}&verbose=true"
log "Rufe DuckDNS auf: $UPDATE_URL"
curl -s "$UPDATE_URL"
echo
6.2 Sensor-Skript: WAN-IPv6 des Routers von DuckDNS
Datei: /config/bashscripts/sensor_fritz_ipv6.sh (Name beliebig, Inhalt generisch):
#!/usr/bin/env bash
set -euo pipefail
ROUTER_DOMAIN="meinrouter123.duckdns.org"
WAN6=$(nslookup -type=AAAA "$ROUTER_DOMAIN" 8.8.8.8 2>/dev/null \
| awk '/Address: / {print $2}' \
| grep ':' \
| tail -n1 || true)
if [ -z "${WAN6:-}" ]; then
echo "unknown"
exit 0
fi
echo "$WAN6"
6.3 Sensor-Skript: HA-IPv6 mit Suffix
Datei: /config/bashscripts/sensor_ha_ipv6_suffix.sh:
#!/usr/bin/env bash
set -euo pipefail
SUFFIX="1234:5678:9abc:def0"
LOCAL_V6=$(
ip -6 addr show scope global | \
awk '/inet6/ && $2 ~ /'"$SUFFIX"'/ {print $2}' | \
head -n1 | cut -d/ -f1
)
if [ -z "${LOCAL_V6:-}" ]; then
echo "unknown"
exit 0
fi
echo "$LOCAL_V6"
7. Home Assistant Konfiguration
7.1 command_line-Sensoren
In configuration.yaml:
command_line:
- sensor:
name: fritzbox_ipv6_duckdns
command: "bash /config/bashscripts/sensor_fritz_ipv6.sh"
scan_interval: 300
command_timeout: 30
- sensor:
name: ha_ipv6_suffix_1234
command: "bash /config/bashscripts/sensor_ha_ipv6_suffix.sh"
scan_interval: 300
command_timeout: 30
Resultierende Entities:
Die Namen kannst du natürlich anpassen, die Inhalte sind nur Beispiele.
7.2 shell_command
In configuration.yaml:
shell_command:
update_ha_ipv6_from_duckdns: >
bash /config/bashscripts/update_ha_ipv6_from_duckdns.sh
7.3 Automationen
Beim Präfixwechsel des Routers oder HA-Neustart setzen
alias: HA-Neustart / Fritzbox IPv6 Wechsel erkannt
description: Speichert alte IPv6 in Helfern und startet DuckDNS-Update-Script
triggers:
- entity_id:
- sensor.fritzbox_ipv6_duckdns
- sensor.ha_ipv6_suffix_6acb
trigger: state
- trigger: homeassistant
event: start
conditions:
- condition: template
value_template: |
{{ trigger.to_state.state not in ['unknown','unavailable',''] }}
actions:
- data:
entity_id: input_text.last_fritzbox_ipv6
value: "{{ states('sensor.fritzbox_ipv6_duckdns') }}"
action: input_text.set_value
- data:
entity_id: input_text.last_ha_ipv6
value: "{{ states('sensor.ha_ipv6_suffix_6acb') }}"
action: input_text.set_value
- action: shell_command.update_ha_ipv6_from_duckdns
mode: single
8. Tests
Im LAN:
-
HA-Terminal:
ip -6 addr show dev wlan0
# oder: ip -6 addr show dev eth0
Erwartung:
-
Router → Gerätedetails für HA
- IPv6-Adresse = dieselbe GUA wie oben.
-
nslookup auf HA-DuckDNS:
nslookup meinha123.duckdns.org 8.8.8.8
Erwartung:
Address: 2001:db8:1111:1001:1234:5678:9abc:def0
-
Browser im LAN:
http://[2001:db8:1111:1001:1234:5678:9abc:def0]:8123
http://meinha123.duckdns.org:8123
Von außen (Mobilfunk, WLAN aus):
Voraussetzung: dein Mobilfunk-Netz hat IPv6-Konnektivität.
9. Stolpersteine
-
Interface-ID falsch oder geändert
→ Suffix im Skript (SUFFIX="...") und Interface-ID im Router-Webinterface müssen zusammenpassen.
-
Falscher DuckDNS-Token / Subdomain
→ Router-Domain (ROUTER_DOMAIN) und HA-Domain (HA_DOMAIN) genau prüfen.
-
Kein IPv6 im Quellnetz
→ Wenn das externe Netz (Hotel-WLAN etc.) kein IPv6 hat, geht der Zugriff nicht – unabhängig von deiner Config.
-
IPv6-Filter des Routers
→ Im Router-Webinterface (z.B. Menü „Internet → Filter“) sicherstellen, dass eingehende IPv6-Verbindungen für die Portfreigabe erlaubt sind.
10. Warum so und nicht mit Nabu Casa / Cloudflare?
Nabu Casa und Cloudflare Tunnel sind komfortable, gepflegte Lösungen – für viele Szenarien völlig ausreichend.
Diese Lösung richtet sich an alle, die:
-
bereits DS-Lite + Router (z.B. FritzBox) + IPv6 haben,
-
keine zusätzlichen Tunnel-Dienste einsetzen möchten,
-
volle Kontrolle über die Adressierung (Präfix + Suffix) haben wollen,
-
und verstehen möchten, warum ihr Home Assistant von außen erreichbar ist – und nicht nur, dass er es ist. 
Wenn jemand daraus ein Add-on baut (UI für Domains, Token, Suffix, Schalter „alle globalen IPs löschen / nur eine zusätzliche hinzufügen“), wäre das der logische nächste Schritt.
Grüße, sedowan