Workshop: BIND 9 auf Windows 10

ISC BIND als Ersatz für den Microsoftschen Nameserver ist sicherlich keine schlechte Idee, aber kein Honigschlecken für Feinde der Konsole.

In diesem Workshop wird gezeigt, wie man den ISC BIND-Nameserver auf Windows 10 einrichtet, konfiguriert und als Dienst zum Laufen bringt. Die Konfiguration wird Schritt für Schritt aufgebaut und erweitert, bis am Ende ein loggender, rekursiver caching Slave Nameserver mit IPv4- und IPv6-Unterstützung und RNDC eingerichtet ist. Damit entgeht keine einzige DNS-Anfrage der Windows-Maschine dem wachsamen Adlerauge des Administrators, wenn als einziger Nameserver localhost angegeben wird.

BIND downloaden

Aktuell ist (war) die Version 9.11.3, die genießt Support bis zum Jahr 2021. Eine Neuerung ist unter anderem die Unterstützung von dyndb, eine API von Red Hat für externe Zonendaten.

Nachdem das ZIP entpackt wurde, zuerst die Datei readme.1st lesen. Im selben Ordner befinden sich außerdem die Hilfe-Dateien von BIND. Die werden bei der Installation nicht mitkopiert, also am besten am lokalen Webserver speichern. Die wichtigste Datei ist zweifellos Bv9ARM.pdf, das BIND Administrator Reference Manual, ein über 300 Seiten langes Elaborat. notes.pdf sind die Release-Notes.

BIND installieren

BIND muß in Windows als Administrator installiert werden, da ein Benutzer named mit Minimalrechten (nur als Service) angelegt wird.

Also die Datei BINDinstall.exe als Administrator ausführen

Ein Paßwort eingeben (wird später benötigt, also notieren), Tools only nicht ankreuzen da sonst nur die BIND-Utils (dighost, usw., siehe readme.1st) installiert werden, Start Bind Service After Install nicht ankreuzen und auf Install klicken

Die fehlenden C++ Bibliotheken werden nachinstalliert

Das wars eigentlich schon.

Zum Abschluß noch einen Pfad auf “C:\Program Files\ISC Bind 9\bin” setzen, damit die Bind-Utils (hostdig,…) erreichbar werden.

Nach einem Neustart ist die Installation von BIND abgeschlossen.

BIND konfgurieren

Für einen ersten Start von BIND sind nur 6 Dateien notwendig (7 mit IPv6). Die werden aber bei der Installation in Windows nicht erzeugt und im BIND-Handbuch finden sich keine Hinweise, wie die in Windows 10 aussehen müssen. Auch ein längeres herumgoogeln im Internet bringt nicht wirklich brauchbare Ergebnisse. Deswegen wird alles hier erklärt.

Die wichtigste Datei ist Konfigurationsdatei named.conf, die auch zwingend so heißen muß. Die anderen 5 Dateien sind die Zonendateien für die Root-Zone, localhost, 127.0.0.1 (eigentlich 127.x.x.x), Broadcast und dessen Reverse-IP. Die Dateien können beliebige Namen haben, vollkommen gleichgültig welchen, da die in der Konfigurationsdatei hinterlegt werden. Gängige Namen sind z. B. localhost.rev, db.127, master.localhost, db.local, root.servers, root.hint, named.root, db.root, named.broadcast, db.255, named.local, db.0, named.zero. In diesem Tutorial orientieren wir uns mit der Nomenklatur an Ubuntu.

Mit dem Texteditor irgendwo auf “C:” 6 leere Dateien erzeugen, am besten im Home-Ordner.

named.conf
db.root
db.local
db.127
db.0
db.255

und nach “C:\Programme\ISC Bind 9\etc” verschieben. Das erfordert Administratorrechte! Danach die Dateien befüllen.

named.conf

// Konfigurationsdatei für BIND9 unter Windows 10
// Caching Nameserver
///////////////////////////////////////////////////////////////////
options {
    directory "C:\Program Files\ISC BIND 9\etc";
    version "F.O.";
    pid-file "named.pid";
    recursion yes;
    listen-on { 127.0.0.1; };
    listen-on-v6 { ::1; };
    allow-transfer { any; };
    auth-nxdomain no;            # conform to RFC1035
};
///////////////////////////////////////////////////////////////////
logging {
    channel my_log{
        file "named.log" versions 3 size 250k;
        severity info;
    };
    category default{
        my_log;
    };
};
///////////////////////////////////////////////////////////////////
// Root-Zone, download @ ftp://ftp.internic.net/domain/named.root
zone "." IN {
    type hint;
    file "db.root";
};
///////////////////////////////////////////////////////////////////
zone "localhost" IN {
    type master;
    file "db.local";
    allow-update{none;};
};
///////////////////////////////////////////////////////////////////
zone "127.in-addr.arpa" IN {
    type master;
    file "db.127";
    allow-update{none;};
};
//////////////////////////////////////////////////////////////////
zone "0.in-addr.arpa" IN {
    type master;
    file "db.0";
};
//////////////////////////////////////////////////////////////////
zone "255.in-addr.arpa" IN {
    type master;
    file "db.255";
};
//////////////////////////////////////////////////////////////////

db.root

Die aktuelle Datei mit den Rootservern ist bei internic.net zum Download erhältlich: ftp://rs.internic.net/domain/named.root

; ftp://ftp.internic.net/domain/named.root
;
; This file holds the information on root name servers needed to 
; initialize cache of Internet domain name servers
; (e.g. reference this file in the "cache . <file>"
; configuration file of BIND domain name servers). 
; 
; This file is made available by InterNIC 
; under anonymous FTP as
; file /domain/named.cache 
; on server FTP.INTERNIC.NET
; -OR- RS.INTERNIC.NET
; 
; last update: March 07, 2018 
; related version of root zone: 2018030701
; 
; FORMERLY NS.INTERNIC.NET 
;
. 3600000 NS A.ROOT-SERVERS.NET.
A.ROOT-SERVERS.NET. 3600000 A 198.41.0.4
A.ROOT-SERVERS.NET. 3600000 AAAA 2001:503:ba3e::2:30
; 
; FORMERLY NS1.ISI.EDU 
;
. 3600000 NS B.ROOT-SERVERS.NET.
B.ROOT-SERVERS.NET. 3600000 A 199.9.14.201
B.ROOT-SERVERS.NET. 3600000 AAAA 2001:500:200::b
; 
; FORMERLY C.PSI.NET 
;
. 3600000 NS C.ROOT-SERVERS.NET.
C.ROOT-SERVERS.NET. 3600000 A 192.33.4.12
C.ROOT-SERVERS.NET. 3600000 AAAA 2001:500:2::c
; 
; FORMERLY TERP.UMD.EDU 
;
. 3600000 NS D.ROOT-SERVERS.NET.
D.ROOT-SERVERS.NET. 3600000 A 199.7.91.13
D.ROOT-SERVERS.NET. 3600000 AAAA 2001:500:2d::d
; 
; FORMERLY NS.NASA.GOV
;
. 3600000 NS E.ROOT-SERVERS.NET.
E.ROOT-SERVERS.NET. 3600000 A 192.203.230.10
E.ROOT-SERVERS.NET. 3600000 AAAA 2001:500:a8::e
; 
; FORMERLY NS.ISC.ORG
;
. 3600000 NS F.ROOT-SERVERS.NET.
F.ROOT-SERVERS.NET. 3600000 A 192.5.5.241
F.ROOT-SERVERS.NET. 3600000 AAAA 2001:500:2f::f
; 
; FORMERLY NS.NIC.DDN.MIL
;
. 3600000 NS G.ROOT-SERVERS.NET.
G.ROOT-SERVERS.NET. 3600000 A 192.112.36.4
G.ROOT-SERVERS.NET. 3600000 AAAA 2001:500:12::d0d
; 
; FORMERLY AOS.ARL.ARMY.MIL
;
. 3600000 NS H.ROOT-SERVERS.NET.
H.ROOT-SERVERS.NET. 3600000 A 198.97.190.53
H.ROOT-SERVERS.NET. 3600000 AAAA 2001:500:1::53
; 
; FORMERLY NIC.NORDU.NET
;
. 3600000 NS I.ROOT-SERVERS.NET.
I.ROOT-SERVERS.NET. 3600000 A 192.36.148.17
I.ROOT-SERVERS.NET. 3600000 AAAA 2001:7fe::53
; 
; OPERATED BY VERISIGN, INC.
;
. 3600000 NS J.ROOT-SERVERS.NET.
J.ROOT-SERVERS.NET. 3600000 A 192.58.128.30
J.ROOT-SERVERS.NET. 3600000 AAAA 2001:503:c27::2:30
; 
; OPERATED BY RIPE NCC
;
. 3600000 NS K.ROOT-SERVERS.NET.
K.ROOT-SERVERS.NET. 3600000 A 193.0.14.129
K.ROOT-SERVERS.NET. 3600000 AAAA 2001:7fd::1
; 
; OPERATED BY ICANN
;
. 3600000 NS L.ROOT-SERVERS.NET.
L.ROOT-SERVERS.NET. 3600000 A 199.7.83.42
L.ROOT-SERVERS.NET. 3600000 AAAA 2001:500:9f::42
; 
; OPERATED BY WIDE
;
. 3600000 NS M.ROOT-SERVERS.NET.
M.ROOT-SERVERS.NET. 3600000 A 202.12.27.33
M.ROOT-SERVERS.NET. 3600000 AAAA 2001:dc3::35
; End of file

db.local

;
; BIND data file for local loopback interface
;
$TTL 604800
@    IN     SOA    localhost.     root.localhost. (
                   0              ; serial
                   604800         ; refresh
                   86400          ; retry
                   2419200        ; expire
                   604800         ; minimum
                   )
;
@    IN     NS     localhost.
@    IN     A      127.0.0.1
@    IN     AAAA   ::1

db.127

;
; BIND reverse data file for local loopback interface
;
$TTL 604800
@       IN      SOA    localhost.   root.localhost. (
                       0            ; serial
                       604800       ; refresh
                       86400        ; retry
                       2419200      ; expire
                       604800       ; minimum
                       )
;
@       IN      NS     localhost.
1.0.0   IN      PTR    localhost.

db.0

;
; BIND reverse data file for broadcast zone
;
$TTL 604800
@     IN       SOA     localhost.     root.localhost. (
                       0              ; Serial
                       604800         ; Refresh
                       86400          ; Retry
                       2419200        ; Expire
                       604800         ; Negative Cache TTL
                       )
;
@     IN       NS      localhost.

db.255

; BIND reverse data file for broadcast zone
;
$TTL 604800
@      IN      SOA     localhost.    root.localhost. (
                       0             ; Serial
                       604800        ; Refresh
                       86400         ; Retry
                       2419200       ; Expire
                       604800        ; Negative Cache TTL
                       )
;
@      IN      NS      localhost.

Die Konfigurationsdateien von BIND 9 sind hiermit vollständig für einen ersten Start.

BIND starten

Systemsteuerung  Verwaltung  Dienste

Wer hier einfach auf  Dienst starten klickt, wird mit Fehler 1067 quittiert. In der Ereignisanzeige steht, warum das so ist und sein muß.

Kein Wunder! Der Dienst läuft ja auch als Benutzer named, und der hat auf “C:\Programme” (noch) keine Schreibrechte.

Man kann entweder die Eigenschaften des Dienstes auf Anmelden als lokales Systemkonto ändern

oder besser dem Nutzer named Schreibrechte auf “C:\Programme\ISC Bind 9\etc” geben. Dafür haben wir ihn ja auch zuvor angelegt!

Nachdem der Dienst gestartet ist, zur Überprüfung mit einem kurzen “netstat -a” nachsehen, ob jemand auf Port 53 UDP lauscht.

Wien man hier sieht, läuft auch der DNS-Cache von Windows auf Port 5353 UDP.

Nun wollen wir als letzten Funktionstest die BIND-Version von unserem frisch aufgesetzten Nameserver ermitteln. Dazu befragen wir localhost nach einem TXT-Record der Chaosklasse:

dig @localhost version.bind txt chaos

Richtigerweise wird als BIND-Version hier F.O. angezeigt – das haben wir zuvor in der named.conf eingegeben. Was wohl F.O. bedeutet? Hmmm… 🤔

IPv6

Nachdem nun alles funktioniert, erweitern wir die Konfiguration um die Reverse-Zone für IPv6.

An der named.conf anhängen:

// localhost Reverse-Zone IPv6
zone "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa" IN {
     type master;
     file "db.0.ip6.arpa.rev";
     allow-update { none; };
};

Das neue Zonenfile “C:\Programme\ISC Bind 9\etc\db.0.ip6.arpa.rev” mit dem Texteditor erstellen:

;
; BIND reverse data file for local loopback IPv6 interface
;
$TTL 604800
@    IN     SOA     localhost. hostmaster.localhost. (
                    0            ; serial
                    3H           ; refresh
                    15M          ; retry
                    1W           ; expire
                    1D           ; minimum
                    )
;
@    IN     NS      localhost.
;
$ORIGIN 0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa.
1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0 IN PTR localhost.

Kleine Anmerkung am Rande: Die Zonenfiles müssen mit einem CRLF enden!

ISC BIND neu starten.

Ein Blick auf die Log-Datei “C:\Programme\ISC Bind 9\etc\named.log” beim Neustart kann nie schaden 😉

RNDC konfigurieren

Remote Name Daemon Control. Steuert den Nameserver über die Konsole.

Die Konfiguration von RNDC geschieht mit dem Tool rndc-confgen.exe. Es erzeugt die Datei rndc.conf und die Einträge für die named.conf, die man nur noch hinzufügen muß.

Der Aufruf von rnd-confgen in der Kommandozeile ergibt z. B.:

Also den oberen Block in die Datei “C:\Programme\ISC Bind 9\etc\rndc.conf” kopieren und den unteren Block an named.conf anhängen und BIND neu starten.

Ein kurzes “netstat -a” zeigt, daß jetzt RNDC auf localhost Port 953 TCP lauscht.

Somit ist der Nameserver ab jetzt über die Konsole mit dem Befehl rndc bedienbar.

Beim Neustart wird jetzt der Command Channel mitprotokolliert:

rndc status
rndc zonestatus localhost

DNS Client-Einstellungen ändern

Jetzt steht dem nichts mehr im Weg, daß wir auf der Windows-Maschine unseren eigenen Nameserver nutzen.

DNS-Einstellungen für IPv4:

DNS-Einstellungen für IPv6:

Auf einmal geht alles viel schneller – komisch

DNS-Anfragen protokollieren

Nachdem jetzt unsere Windows-Maschine für DNS-Namensauflösungen sich selbst befrägt, wollen wir wissen, was sich im Hintergrund tut. Zum Beispiel bei einem Skype-Gespräch.

Wir erweitern in der named.conf den Abschnit logging um den channel query.

logging {
    channel my_log {
        file "named.log" versions 3 size 250k;
        severity info;
    };
    category default { my_log; };
    channel query {
        file "query.log" versions 2 size 1m;
        print-time yes;
        severity info;
     };
     category queries { query; };
};

Nach einem Neustart von ISC BIND werden alle DNS-Anfragen in der query.logprotokolliert. Sehr hilfreich beim Konfigurieren und Debuggen diverser Anwendungen.

Das geschieht, wenn man Skype öffnet:

Rekursion

Die ganze Konfiguration hat aber noch einen Pferdefuß: die Zonen des lokalen Nameservers. Unser Nameserver ist rekursiv, er hantelt sich also so lange durch, bis er die authoritativen Nameserver gefunden hat, um sie zu befragen und die Namensauflösung durchzuführen. Wenn es im lokalen Netz bereits einen Nameserver gibt und dieser lokale Zonen verwaltet, wird unser Nameserver die Zonen nicht auflösen können weil er schlicht und ergreifend davon nichts weiß. Wenn er auf eine ihm unbekannte Zone trifft, befrägt er zuerst die Root-Server (aus der Datei db.root). Die sagen ihm, welche Nameserver für welche Top-Level-Domains (z. B. .com.net.org, usw.) zuständig sind, diese wiederum verweisen auf Verweise und so weiter, bis letztendlich die zuständigen (authoritativen) Nameserver gefunden wurden.

Private Zonen

Gibt es private Zonen (z. B. .local , .lan oder auch nur 192.168.0.0/24), kann unser Nameserver dies nicht wissen, weil es in den Root-Servern logischerweise nicht enthalten ist und nicht sein kann. Damit es funktioniert, muß man den Nameserver versklaven (einen Slave DNS einrichten für die privaten Zonen).

Slave DNS einrichten

Ein Sklaven-DNS erhält die Zonen vom Master-DNS. Der Master muß dem Sklaven gestatten seine Zonen auslesen zu dürfen (einen Transfer machen) und er muß den Sklaven bei Änderungen benachrichtigen (ein Notify senden). Der empfangende Sklave muß den Master akzeptieren.

Wie man das dem DNS sagt, folgt jetzt.

Angenommen, der Master ist 192.168.0.1 und ist für die Zone .lan authoritativ und der Sklave (unser gerade installierter Nameserver auf localhost) ist 192.168.0.111, dann sind folgende Eingriffe in den Konfigurationsdateien zu machen:

named.conf Master-DNS

IP = 192.168.0.1

notify yes;
allow-transfer { 127.0.0.1; 192.168.0.111; };
allow-notify { 192.168.0.111; };
also-notify { 192.168.0.111; }

named.conf Slave-DNS

IP = 192.168.0.111

// Slave Zones
zone "lan" {
    type slave;
    masters { 192.168.0.1; };
    file "slave.lan.hosts";
};
zone "0.168.192.in-addr.arpa" {
    type slave;
    masters { 192.168.0.1; };
    file "slave.192.168.0.rev";
};
zone "0.0.8.e.f.ip6.arpa" {
    type slave;
    masters { 192.168.0.1; };
    file "slave.0.0.8.e.f.ip6.arpa.rev";
};

Nach einem Restart der Dienste auf beiden Nameservern ist der Sklave bereit, vom Master die Zonen zu empfangen.

Jetzt wollen wir natürlich wissen, ob unser Sklave die Zonen richtig empfängt. Wir erweitern in der named.conf den Abschnitt logging wie folgt:

logging {
    channel my_log{
        file "named.log" versions 3 size 250k;
        severity info;
    };
    category default { my_log; };

    channel query {
        file "query.log" versions 2 size 1m;
        print-time yes;
        severity info;
    };
    category queries { query; };

    channel xfer-log {
        file "xfer.log";
        print-category yes;
        print-severity yes;
        print-time yes;
        severity info;
    };
    category xfer-in { xfer-log; };
    category xfer-out { xfer-log; };
    category notify { xfer-log; };
};

Nach einem Restart von BIND können wir den Zonentransfer vom Master zum Sklaven in der xfer.log  beobachten. Wir laden also vom Master die Zone lan zu unserem Sklaven erneut:

rndc lan retransfer

Zonen auslesen

Weil wir in der named.conf den Transfer für alle gestattet haben,

allow-transfer { any; };

können wir die komplette Zonendatei auslesen:

dig @localhost lan AXFR

Fertig

War ja ganz leicht!