Zum Inhalt

Souveränes rekursives DNS: Unbound Root-Zonen-Auflösung, QNAME-Minimierung & DNSSEC-Validierung

Erstellt: 06.11.2026 Aktualisiert: 06.11.2026

Management Summary: Die Weiterleitung lokaler DNS-Anfragen an kommerzielle Upstream-Resolver (1.1.1.1, 8.8.8.8, 9.9.9.9) – selbst über DoH oder DoT – übermittelt ein lückenloses chronologisches Profil des gesamten Netzwerktraffics an Drittanbieter. Diese Architekturreferenz beschreibt den Betrieb von NLnet Labs Unbound als selbst gehosteten, validierenden, rekursiven Caching-Resolver. Unbound traversiert die globale DNS-Hierarchie direkt ausgehend von den 13 IANA Root-Server-Clustern unter Nutzung von RFC 9156 QNAME-Minimierung, RFC 8198 Aggressivem NSEC-Caching, RFC 8806 Lokalem Root-Mirroring (auth-zone) und Multithreaded-Slab-Cache-Tuning.

  • Direkte Root-Zonen-Rekursion


    Macht DNS-Zwischenhändler überflüssig, indem iterativ von den IANA-Root-Servern (a.root-servers.net–m.root-servers.net) bis zu den autoritativen Nameservern aufgelöst wird.

  • RFC 9156 QNAME-Minimierung


    Sendet auf jeder Delegationsebene nur den minimal notwendigen Domain-Label (.de sieht nur .de, niemals mail.internal.nejat-hakan.de).

  • Kryptografische DNSSEC-Kette


    Validiert DNSKEY-, DS- und RRSIG-Signaturen gegen den IANA Root Trust Anchor (root.key) und synthetisiert Negativantworten via Aggressives NSEC.

  • RFC 8806 Lokale Root-Zone


    Spiegelt die gesamte IANA-Root-Zone lokal via AXFR/HTTPS (auth-zone: "."), um externe Root-Abfragen zu eliminieren und Verkehrsanalysen zu verhindern.


1. Architektur: Iterative Root-Rekursion mit QNAME-Minimierung

Wird vault.infra.nejat-hakan.de ohne QNAME-Minimierung aufgelöst, erfährt bereits der Root-Server sowie der .de-TLD-Server den vollständigen Hostnamen. Mit qname-minimisation: yes schneidet Unbound alle überflüssigen Sublabels ab:

%%{init: {'flowchart': {'wrappingWidth': 600, 'subGraphTitleMargin': {'top': 15, 'bottom': 15}}}}%%
flowchart TB
    subgraph LocalStack["Souveräner DNS-Stack"]
        Sinkhole["Pi-hole / AdGuard Home<br/>127.0.0.1:53"]
        Unbound["Unbound Rekursive Engine<br/>127.0.0.1:5335 (DNSSEC)"]
        LocalRoot[("RFC 8806 Lokaler Root<br/>auth-zone '.' Spiegel")]
    end

    subgraph GlobalHierarchy["Globale autoritative Hierarchie"]
        TLD["DENIC (.de TLD NS)<br/>Sieht NUR: nejat-hakan.de NS?"]
        AuthNS["Autoritativer NS<br/>Sieht: vault.nejat-hakan.de A?"]
    end

    Sinkhole -->|"Anfrage: vault.nejat-hakan.de"| Unbound
    Unbound <-->|"1. Anfrage: .de NS?<br/>(0ms Lokaler Loopback)"| LocalRoot
    Unbound -->|"2. QNAME-minimiert:<br/>nejat-hakan.de NS?"| TLD
    TLD -->|"Referral + DS-Record"| Unbound
    Unbound -->|"3. Finale Anfrage:<br/>vault.nejat-hakan.de A?"| AuthNS
    AuthNS -->|"Signiertes A + RRSIG"| Unbound

Kryptografische & Privatsphäre-Mechanismen

  1. 0x20-Bit-Verfahren (use-caps-for-id: yes): Unbound randomisiert Groß- und Kleinschreibung in ausgehenden Domainanfragen (z. B. vAuLt.NeJaT-hAkAn.De). Da autoritative Nameserver die Schreibweise exakt spiegeln müssen, entsteht zusätzliche Entropie gegen Kaminsky-Cache-Poisoning-Angriffe.
  2. Aggressives NSEC/NSEC3-Caching (aggressive-nsec: yes): Gemäß RFC 8198 nutzt Unbound kryptografische Bereichsbeweise, um NXDOMAIN- und NODATA-Antworten lokal zu generieren, ohne externe Nameserver erneut zu befragen.
  3. Cache-Prefetching (prefetch: yes & serve-expired: yes): Wird ein Eintrag in den letzten 10 % seiner TTL angefragt, liefert Unbound sofort den gecachten Wert aus und aktualisiert den Datensatz asynchron im Hintergrund.

2. Installation & Root Trust Anchor Initialisierung

Unter Debian/Ubuntu stellt das Paket dns-root-data die Root-Hints (/usr/share/dns/root.hints) sowie den automatisierten DNSSEC-Trust-Anchor nach RFC 5011 bereit:

Unbound installieren & RFC 5011 Trust Anchor prüfen
sudo apt update && sudo apt install -y unbound unbound-anchor dns-root-data dnsutils

# DNSSEC Root Trust Anchor (/var/lib/unbound/root.key) überprüfen oder initialisieren
sudo -u unbound unbound-anchor -a /var/lib/unbound/root.key -v

3. Gehärtete Produktivkonfiguration (sovereign-recursive.conf)

Die folgende Konfiguration ist für ein 4-Core-System optimiert, das Unbound auf 127.0.0.1:5335 als Upstream für Pi-hole oder AdGuard Home bereitstellt. Wichtig: Die Slab-Werte (msg-cache-slabs, rrset-cache-slabs, etc.) müssen Zweierpotenzen sein (2, 4, 8), um Lock-Contention zwischen CPU-Cores zu minimieren.

/etc/unbound/unbound.conf.d/sovereign-recursive.conf
server:
    # --- Netzwerk- & Schnittstellen-Binding ---
    interface: 127.0.0.1
    interface: ::1
    port: 5335
    do-ip4: yes
    do-ip6: yes
    do-udp: yes
    do-tcp: yes
    prefer-ip6: no

    # --- Zugriffskontrolllisten (Loopback) ---
    access-control: 127.0.0.0/8 allow
    access-control: ::1/128 allow
    access-control: 0.0.0.0/0 refuse
    access-control: ::0/0 refuse

    # --- Root Hints & Trust Anchor ---
    root-hints: "/usr/share/dns/root.hints"
    auto-trust-anchor-file: "/var/lib/unbound/root.key"

    # --- Härtung & Privatsphäre ---
    hide-identity: yes
    hide-version: yes
    qname-minimisation: yes
    qname-minimisation-strict: no
    harden-glue: yes
    harden-dnssec-stripped: yes
    harden-below-nxdomain: yes
    harden-referral-path: no
    harden-algo-downgrade: yes
    use-caps-for-id: no
    aggressive-nsec: yes

    # --- DNS-Rebinding-Schutz (RFC1918 in öffentlichen Antworten sperren) ---
    private-address: 10.0.0.0/8
    private-address: 172.16.0.0/12
    private-address: 192.168.0.0/16
    private-address: 169.254.0.0/16
    private-address: fd00::/8
    private-address: fe80::/10
    # Lokale Domain darf RFC1918 zurückgeben
    private-domain: "lan.nejat-hakan.de"

    # --- Multi-Core Performance & Slab Memory Allokation ---
    num-threads: 4
    msg-cache-slabs: 4
    rrset-cache-slabs: 4
    infra-cache-slabs: 4
    key-cache-slabs: 4

    # 128MB Message Cache und 256MB RRset Cache (Verhältnis 2:1)
    msg-cache-size: 128m
    rrset-cache-size: 256m
    key-cache-size: 64m
    neg-cache-size: 32m

    # --- Socket-Puffer & EDNS-Optimierung ---
    so-rcvbuf: 4m
    so-sndbuf: 4m
    so-reuseport: yes
    edns-buffer-size: 1232
    num-queries-per-thread: 4096
    outgoing-range: 8192

    # --- Low-Latency Prefetch & Stale Cache ---
    prefetch: yes
    prefetch-key: yes
    serve-expired: yes
    serve-expired-ttl: 86400
    serve-expired-client-timeout: 1800
    cache-min-ttl: 300
    cache-max-ttl: 86400

# --- RFC 8806: IANA Root-Zone lokal spiegeln ---
auth-zone:
    name: "."
    primary: 199.9.14.201         # b.root-servers.net
    primary: 192.33.4.12          # c.root-servers.net
    primary: 199.7.91.13          # d.root-servers.net
    primary: 192.5.5.241          # f.root-servers.net
    primary: 192.112.36.4         # g.root-servers.net
    primary: 193.0.14.129         # k.root-servers.net
    primary: 192.0.47.132         # xfr.cjr.dns.icann.org
    primary: 192.0.32.132         # xfr.lax.dns.icann.org
    fallback-enabled: yes
    for-downstream: no
    for-upstream: yes
    zonefile: "/var/lib/unbound/root.zone"

Warum edns-buffer-size: 1232 entscheidend ist

Gemäß dem Standard des DNS Flag Day 2020 verhindert der Wert 1232 eine Paketfragmentierung über die minimale IPv6-MTU (1280 Bytes minus 40 Byte IPv6- und 8 Byte UDP-Header). Große DNSSEC-Antworten über 1232 Bytes signalisieren sauber TC (Truncated) und wechseln auf TCP, anstatt an fehlerhaften ISP-Routern lautlos verworfen zu werden.


4. Split-Horizon Lokale Zonen (local-zone & local-data)

Interne Netzwerkreferenzen lassen sich direkt in Unbound definieren, sodass interne Hosts selbst bei getrennter Internetverbindung aufgelöst werden können:

/etc/unbound/unbound.conf.d/local-lan-zones.conf
server:
    local-zone: "lan.nejat-hakan.de." static

    local-data: "router.lan.nejat-hakan.de. 3600 IN A 192.168.10.1"
    local-data: "nas.lan.nejat-hakan.de. 3600 IN A 192.168.10.10"
    local-data: "proxmox.lan.nejat-hakan.de. 3600 IN A 192.168.10.20"

    # Automatische Reverse PTR Records
    local-data-ptr: "192.168.10.1 router.lan.nejat-hakan.de."
    local-data-ptr: "192.168.10.10 nas.lan.nejat-hakan.de."
    local-data-ptr: "192.168.10.20 proxmox.lan.nejat-hakan.de."

5. Validierung, DNSSEC-Prüfung & Diagnostik

Konfigurationssyntax testen, Dienst neu starten und das kryptografische AD-Flag (Authenticated Data) prüfen:

Unbound Syntax, DNSSEC AD-Flag & Cache-Statistiken testen
# 1. Konfigurationssyntax vor dem Neustart validieren
sudo unbound-checkconf

# 2. Dienst neu starten und Status prüfen
sudo systemctl restart unbound

# 3. Prüfen, ob gültige DNSSEC-Signatur NOERROR mit gesetztem 'ad'-Flag liefert
dig @127.0.0.1 -p 5335 icann.org A +dnssec +multiline

# 4. Verifizieren, dass gefälschte/abgelaufene Signaturen mit SERVFAIL abgewiesen werden
dig @127.0.0.1 -p 5335 dnssec-failed.org A

# 5. Live-Statistiken und Cache-Trefferquoten auslesen
sudo unbound-control stats_noreset | grep -E "total.num|histogram"