Ga naar inhoud

πŸ”€ Migratie van Pi-hole naar een High-Availability Technitium DNS Cluster

Na de recente migratie van mijn homelab DNS-infrastructuur van Pi-hole naar een High-Availability (HA) Technitium DNS-cluster, deel ik in dit projectverslag de complete architectuur, bevindingen en real-world benchmark-resultaten.

Bij het ontwerpen van een homelab DNS-architectuur sta je voor cruciale keuzes. Omdat mijn twee DNS-instanties op sterk verschillende hardwaregeneraties draaien, was een grondige prestatietest vereist om de optimale netwerkbalans te vinden.


πŸ–₯️ De Hardware & Netwerktopologie

Mijn Proxmox VE-omgeving maakt gebruik van twee fysiek gescheiden hosts met een duidelijke asymmetrie in rekenkracht:

  • Node 1 (Lenovo ThinkStation P520): Uitgerust met een Intel Xeon W-2135 CPU (gelanceerd in 2017).

  • Node 2 (AOOSTAR WTR Pro Max): Uitgerust met een AMD Ryzen 7 8845HS CPU (gelanceerd in 2024).

De Ryzen CPU uit 2024 is aanzienlijk krachtiger dan de Xeon uit 2017. Om deze hardware-asymmetrie optimaal te benutten, is de DHCP-scope van mijn router zo geconfigureerd dat de AOOSTAR-instantie (192.168.11.51) als Primaire DNS-server wordt uitgegeven, and de Lenovo-instantie (192.168.11.50) als Secundaire DNS-server.

Hierdoor wordt het bulkverkeer afgehandeld door de snelste processor, terwijl de oudere hardware stand-by staat als een naadloze failover-node. Beide servers blijven continu perfect synchroon lopen via de ingebouwde Technitium Cluster Sync applicatie.


πŸ›‘οΈ De Architectuur: Encryptie vs. Autonomie

Het doel van deze inrichting is absolute privacy binnen het lokale netwerk, gecombineerd met volledige onafhankelijkheid van publieke upstream DNS-providers (zoals Cloudflare, Google of Quad9). Dit vereist een strakke scheiding tussen inkomend en uitgaand verkeer:

1. Inkomend (Client naar Homelab): DNS-over-HTTPS (DoH)

Om het lokale netwerkverkeer te versleutelen, is Nginx Proxy Manager (NPM) ingezet binnen de Docker VM. NPM handles de inkomende beveiligde HTTPS-verbindingen af op poort 443 met behulp van een geldig Let's Encrypt Wildcard-certificaat.

Om complexe databasefouten of SSL-handshake-problemen (ERR_SSL_UNRECOGNIZED_NAME_ALERT) te voorkomen, is NPM bewust eenvoudig gehouden: * Er zijn twee recht toe recht aan Proxy Hosts aangemaakt (dns1.example.com en dns2.example.com). * NPM stuurt het verkeer op de achtergrond rechtstreeks door naar de Technitium LXC-containers op een specifieke DNS-over-HTTP poort (8053).

  • Split-Horizon DNS: Om dit lokaal bereikbaar te maken zonder internet-omweg, is er binnen Technitium een lokale zone ingericht voor patad.nl die dns1 en dns2 direct naar het lokale IP-adres van NPM laat verwijzen.

  • Client Identificatie: In Technitium zijn de opties EDNS Client Subnet (ECS) and de X-Real-IP header geactiveerd. Hierdoor tonen de Technitium-logs exact welke lokale client de aanvraag doet, in plaats van dat overal het IP-adres van de proxy verschijnt.

2. Uitgaand (Homelab naar Internet): Pure Recursie + DNSSEC

Alle upstream forwarders zijn volledig uitgeschakeld. Technitium acteert als een Recursieve DNS-server. Dit betekent dat de server zelfstandig and direct de wereldwijde Root-servers, TLD-servers (Top-Level Domain) en geautoriseerde Name-servers raadpleegt.

Omdat de wereldwijde publieke DNS-infrastructuur momenteel nog geen TLS ondersteunt voor recursieve queries, maakt dit uitgaande verkeer gebruik van standaard UDP. Om absolute veiligheid tegen cache-poisoning en spoofing te garanderen, is DNSSEC-validatie strikt afgedwongen. Technitium valideert elke respons cryptografisch vanaf de root-server tot aan het eindstation.


πŸ“Š Benchmark Resultaten

Om de prestaties in de praktijk te meten, is een uitgebreid PowerShell-script geschreven. Het script leegt de lokale Windows DNS-cache vΓ³Γ³r elke aanvraag en plakt een willekeurig voorvoegsel (prefix) voor het doeldomein (bijv. ://google.com). Dit omzeilt de lokale cache van Technitium volledig and dwingt het cluster om voor elke controle een live, rauwe uitgaande recursie-query uit te voeren.

De testsuite bestaat uit exact 100 unieke top-domeinen verspreid over 5 verschillende geografische en regelgevende zones: Nederland (.nl), Duitsland (.de), Frankrijk (.fr), de Verenigde Staten (.com/.gov) and het Verenigd Koninkrijk (.uk).

De resultaten zijn fenomenaal:

  • dns1.example.com (Primair / 2024 AOOSTAR CPU): Behaalde een verbluffend gemiddelde van slechts 3 tot 5 milliseconden per query. Omdat deze server het primaire netwerkverkeer afhandelt, waren de wereldwijde root-hintstructuren al warmgedraaid in het RAM-geheugen, waardoor de Ryzen-processor de recursieve paden vrijwel direct berekende. Bovendien maakt Windows gebruik van TLS Session Resumption, waardoor de versleutelings-overhead van de HTTPS-tunnel met NPM tot nul wordt gereduceerd.

  • dns2.example.com (Secundair / 2017 Lenovo CPU): Noteerde een solide gemiddelde van 11 to 13 milliseconden. Het kleine verschil van ~8ms is puur de tijd die de Windows-client nodig heeft om een frisse, aparte TLS-handshake met NPM op te starten voor het tweede subdomein. Zodra de socket open is, verloopt de verwerking onmiddellijk.

  • Betrouwbaarheid: De test behaalde een succespercentage van 100% met nul pakketverlies of time-outs, wat bewijst dat de Technitium Reverse Proxy Network ACL and NPM zijn perfect op elkaar zijn afgestemd.


πŸ“œ Het PowerShell Benchmark-Script

Gebruik het onderstaande PowerShell-script binnen je Windows-beheeromgeving om de responstijden van je eigen DoH-infrastructuur nauwkeurig door te meten:

# --- REAL SPEEDTEST DNS DOH (HTTPS) WITH LOCAL CACHE FLUSH (100 DOMAINS) ---
\$DNSServers = @("dns2.example.com", "dns1.example.com") # Primaire snelle host wordt eerst getest 
\(TestRuns = 1\)ThresholdMs = 75 # Grenswaarde voor rauwe recursieve uitschieters

# Uitgebreide lijst van exact 100 topdomeinen (NL, DE, FR, US, UK)
\$DomainList = @( 
    # --- Nederland (.nl) - 20 domeinen --- 
    "tweakers.net", "nu.nl", "nos.nl", "buienradar.nl", "bol.com", "rijksoverheid.nl", "rabobank.nl", "ing.nl", "kpn.com", "ziggo.nl", "coolblue.nl", "marktplaats.nl", "belastingdienst.nl", "nlnetlabs.nl", "surf.nl", "tudelft.nl", "uva.nl", "volkskrant.nl", "telegraaf.nl", "albertheijn.nl", 
    # --- Duitsland (.de) - 20 domeinen --- 
    "amazon.de", "spiegel.de", "bild.de", "tagesschau.de", "heise.de", "welt.de", "zeit.de", "focus.de", "golem.de", "computerbase.de", "ebay.de", "bahn.de", "otto.de", "zalando.de", "check24.de", "adac.de", "telekom.com", "bundesregierung.de", "dfb.de", "kit.edu", 
    # --- Frankrijk (.fr) - 20 domeinen --- 
    "lemonde.fr", "lefigaro.fr", "leparisien.fr", "lesechos.fr", "liberation.fr", "allocine.fr", "cdiscount.com", "fnac.com", "vinted.fr", "carrefour.fr", "sncf-connect.com", "impots.gouv.fr", "ameli.fr", "gouvernement.fr", "edf.fr", "orange.fr", "free.fr", "sfr.fr", "sorbonne-universite.fr", "lequipe.fr", 
    # --- Verenigde Staten (.com / .org / .gov) - 20 domeinen --- 
    "cloudflare.com", "ietf.org", "paypal.com", "verisign.com", "google.com", "microsoft.com", "wikipedia.org", "github.com", "amazon.com", "apple.com", "meta.com", "netflix.com", "nasa.gov", "usa.gov", "whitehouse.gov", "nytimes.com", "cnn.com", "mit.edu", "harvard.edu", "stanford.edu", 
    # --- Verenigd Koninkrijk (.uk) - 20 domeinen --- 
    "gov.uk", "bbc.co.uk", "nhs.uk", "ox.ac.uk", "cam.ac.uk", "coop.co.uk", "theguardian.com", "telegraph.co.uk", "hmv.com", "ba.com", "sky.com", "bt.com", "ee.co.uk", "vodafone.co.uk", "tesco.com", "sainsburys.co.uk", "asda.com", "argos.co.uk", "tfl.gov.uk", "manutd.com" 
)

# Toestaan van interne homelab certificaten (DoH dwingt HTTPS af)
[System.Net.ServicePointManager]::ServerCertificateValidationCallback = {\(true}\)DesktopPath = [Environment]::GetFolderPath([Environment+SpecialFolder]::Desktop) 
CSVPath = DesktopPath + "\dns_100_domains_speed_report.csv"

Clear-Host 
Write-Host "Starting ULTIMATE 100-Domain DoH Speed Test against Cluster..." -ForegroundColor Cyan 
Write-Host "Testing Netherlands, Germany, France, US, and UK via NPM.`n" -ForegroundColor Yellow

$Results = @()

foreach ($Server in $DNSServers) { 
    Write-Host "Server: $Server" -ForegroundColor Magenta 
    for ($Run = 1; $Run -le $TestRuns; $Run++) { 
        $Count = 1 
        foreach ($Domain in $DomainList) { 
            # Genereer willekeurige prefix om caching in Technitium volledig te omzeilen 
            $RandomNumber = Get-Random -Min 100000 -Max 999999 
            $UniqueDomain = "${RandomNumber}.${Domain}"

            # Lokale DNS cache flashen voor een zuivere meting
            Clear-DnsClientCache

            # DoH query meten via Resolve-DnsName
            $Stopwatch = [System.Diagnostics.Stopwatch]::StartNew()
            try {
                $Response = Resolve-DnsName -Name $UniqueDomain -Server $Server -ErrorAction Stop
                $Stopwatch.Stop()
                $Duration = $Stopwatch.ElapsedMilliseconds
                $Status = "Success"
            } catch {
                $Stopwatch.Stop()
                $Duration = $Stopwatch.ElapsedMilliseconds
                $Status = "Failed"
            }

            # Kleurcodering op basis van snelheid threshold
            $Color = "Green"
            if ($Duration -gt $ThresholdMs) { $Color = "Red" }
            if ($Status -eq "Failed") { $Color = "DarkRed" }

            Write-Host "[$Count/100] Domain: $UniqueDomain -> ${Duration}ms ($Status)" -ForegroundColor $Color

            $Results += [PSCustomObject]@{
                Server    = $Server
                Run       = $Run
                Domain    = $Domain
                UniqueUrl = $UniqueDomain
                Duration  = $Duration
                Status    = $Status
            }
            $Count++
        }
    }
}

# Resultaten exporteren naar het bureaublad
$Results | Export-Csv -Path $CSVPath -NoTypeInformation -Delimiter ","
Write-Host "`nTest voltooid! Rapport opgeslagen op: \$CSVPath" -ForegroundColor Green