Windows DNS-Dienst mit PowerShell Richtlinien steuern

Eine eher unbekannte Funktion wurde beginnend mit Windows Server 2016 für den DNS-Dienst eingeführt.

Es gibt die Möglichkeit, über Richtlinien (Policies) DNS-Abfragen zu steuern. Diese Funktion kann genutzt werden, um gezielt Abfragen zu erlauben oder zu verbieten.

Die Konfiguration dieser Funktion erfolgt ausschließlich über die PowerShell, weshalb sie vielen Administratoren unbekannt ist.

Um alle vorhandenen PowerShell Befehle des DNS-Dienstes anzeigen zu lassen, kann ich wie immer den Befehl:

Get-Command -Module DNSServer

nutzen.

Um nur die PowerShell Befehle für die Richtlinien ausgeben zu lassen, kann ich die Ausgabe weiter filtern:

Get-Command *QueryResolutionPolicy -Module DnsServer

Wir haben die typischen Auswahl an PowerShell-Befehlen:
Mit Get-DnsServerQueryResolutionPolicy werden die schon vorhandenen Richtlinien angezeigt
Mit Set-DnsServerQueryResolutionPolicy werden schon vorhandene Richtlinien geändert
Mit Remove-DnsServerQueryResolutionPolicy wird eine bestehende Richtlinie entfernt
Mit Add-DnsServerQueryResolutionPolicy wird eine neue Richtlinie hinzugefügt

 

Ein Kunde von uns hatte folgendes Problem:

In einem Management Active Directory sollen die DNS-Server nur AD-integrierte und sekundäre Zonen auflösen. Es ist kein DNS-forwarder für ihm nicht bekannte Zonen eingerichtet und alle DNS-Anfragen nach extern werden auf der Firewall geblockt.

Nach jedem Update haben sich aber wieder die Root-Nameserver eingetragen. D.h. bei Anfragen für unbekannte DNS-Zonen hat der Server versucht, die Root-Nameserver zu erreichen. Erst nach ein paar Sekunden kam es zu einem Timeout. Dies hatte aber das Monitoring-Tool aus dem Tritt gebracht.

Die Idee ist, per Richtlinien nur die internen Zonen zu erlauben und allen anderen Anfragen sofort ein "Kenne ich nicht" zu senden

Die internen Zonen sind schnell eingelesen (TrustAnchor = Schlüssel von signierten Zonen werden herausgefiltert)
$allzones = (Get-DnsServerZone | where {$_.zonename -notlike "TrustAnchors"} | sort zonename).zonename

Füe den Befehl Add-DnsServerQueryResolutionPolicy benötigen wir einen Namen, eine Aktion die durchgeführt werden soll und den erklärungsbedürftigen Paramater Fqdn

Bei den Aktionen gibt es 3 Möglichkeiten
ALLOW - erlaubt eine Antwort auf die DNS Anfrage
DENY - Antworte mit SERV_FAIL. Die Gegenseite weiss sofort, dass es keine Auflösung gibt (und genau das benötigen wir)
IGNORE - Sende keine Antwort. Die Gegenseite wartet, bis er durch Timeout abbricht

Der Parameter Fqdn besteht aus einem Operator und einer Liste von Werten, für die der Operator gelten soll.
Als Operator ist EQ oder NE erlaubt. Für alle Werte nach dem Operator EQ wird die definierte Aktion ausgeführt, für alle Werte nach dem Operator NE wird die definierte Aktion nicht ausgeführt. Die beiden Operatoren dürfen nicht zusammen in einer Policy benutzt werden.

D.h.
"EQ,*.powershell-user.de,*.itm8.com" bedeutet: Führe die Aktion für die Abfrage der Domains powershell-user.de und itm8.com aus, und für alle anderen nicht
"NE,*.powershell-user.de,*.itm8.com" bedeutet: Führe die Aktion aus, außer es ist eine Abfrage für die Domains powershell-user.de oder itm8.com

Für unser Problem gibt es folgende Lösung: Führe die Aktion DENY aus, außer es ist eine unserer internen Zonen

Zuerst erstellen wir unsere Whitelist für den Paramater Fqdn. For jeden Zonennamen stellen wir ein *., damit alle Anfragen der Zone erwischt werden
$fqdn = "NE"
ForEach ($zone in $allzones) {$fqdn = $fqdn + ",*." + $zone}

Dann erstellen wir die Policy
Add-DnsServerQueryResolutionPolicy -Name "OnlyInternalDomains" -Action DENY -Fqdn $fqdn

Et voila. Interne Zonen lösen weiterhin auf, alles andere wird sofort mit "SERV_FAIL" beantwortet

Vorher: Warten auf den Timeout

Nachher: Sofortige Antwort "Query refused"

Und hier das ganze Script

# nur AD integrierte und secondary DNS-Zonen auflösen
# 20240616 BBi CBC/itm8

# Alle Zonen auslesen vom lokalen DNS Server, außer root-DNS-Server
$Allzones = (Get-DnsServerZone | where {$_.zonename -notlike "TrustAnchors"} | sort zonename).zonename

# prüfen, ob schon DNS Filter da sind - wenn ja, dann löschen
if (Get-DnsServerQueryResolutionPolicy)
  {
  Get-DnsServerQueryResolutionPolicy |Remove-DnsServerQueryResolutionPolicy"
  }

# Whitelist Filter bauen
$fqdn = "NE"
ForEach ($zone in $allzones)
  {
  $fqdn = $fqdn + ",*." + $zone
  }

# DNS-Filter anlegen
Add-DnsServerQueryResolutionPolicy -Name "OnlyInternalDomains" -Action DENY -Fqdn $fqdn

 

Es gibt viele weitere mögliche Richtlinien und Filterungen.

Diese sind bei Microsoft hier zu finden (zumindest solange, bis ein Produktmanager mal wieder beschließt, den DNS-Namen zu ändern - die toten Links auf technet.microsoft.com und docs.microsoft.com sind endlos)

Was denken Sie?