DNS: Unterschied zwischen den Versionen

Aus Freifunk Franken
Wechseln zu:Navigation, Suche
(Empfehlung auf Anycast geändert)
 
(61 dazwischenliegende Versionen von 6 Benutzern werden nicht angezeigt)
Zeile 3: Zeile 3:
== Konzept ==
== Konzept ==


Für die interne Nutzung im Freifunknetz besitzt F3 Netze e.V. die Domain fff.community
Für die interne Nutzung im Freifunknetz besitzt F3 Netze e.V. die Domain fff.community. Im Gegensatz zu anderen Communites verwenden wir keine eigene Toplevel-Domain, um Kollisionen vorzubeugen und Probleme mit DNSSEC zu vermeiden.
Wir haben keine eigene Toplevel-Domain genutzt um Kollisionen vorzubeugen.


Eine Gruppe von verschiedenen Gateway Betreibern ist autoritativ für die Zone zuständig und synchronisiert untereinander das Zonefile mittels untenstehendem Script.
Die Zone wird in einem Git [https://git.freifunk-franken.de/freifunk-franken/dns] verwaltet und über Skripte [https://git.freifunk-franken.de/freifunk-franken/dns-scripts] auf die für diese Zone autoritativen Nameserver einiger Freifunker synchronisiert.


Wenn jemand eine Domain für seinen Service haben möchte, sollte eine Mail an die Mailingliste genügen.
Wenn jemand eine Domain für seinen Service haben möchte, kann dies mit einen Pull Request angefragt werden: [https://git.freifunk-franken.de/freifunk-franken/dns]</br>
Wenn Subdomains delegiert werden sollen, müssen mindestens 2 Gateways von verschiedenen Betreibern autoritativ sein und das Zone-File entsprechend austauschen.
Die Delegation von Subdomains ist ebenfalls möglich.


== Funktionsfähigkeit auf allen GWs ==
Da es sich bei der Namensauflösung für unsere Adressbereiche um Bereiche des privaten Adressraums handelt, sollten diese IP-Adressen nicht bei eigenen global auflösbaren Domains gesetzt werden. Da einige DNS Server gegen rebind Attacken aus dem globalen DNS geschützt sind, kann es vorkommen, dass die eigene globale Domain nicht auf die fd43:[..] oder 10.[..] IPs aufgelöst werden kann.
Sollte dennoch gern eine globale Domain verwendet werden, dann bitte den jeweiligen Eintrag als CNAME auf einen [..].fff.community hostname setzen und die IP im Git [https://git.freifunk-franken.de/freifunk-franken/dns] setzen.
 
=== Zone extern ===
 
Die Zone extern.fff.community wird automatisch angelegt. Diese enthällt keine Adressen des privaten IP-Bereichs und ist von überall erreichbar. Deswegen können im Zonefile bei einem Hostnamen alle IP-Adressen angegeben werden und für benötigtes Peering kann der gleiche Hostname aus dieser extern-Domain genutzt werden. Das funktioniert auch für delegierte Subdomains (z.B. gw01.herpf.fff.community -> gw01.herpf.extern.fff.community)
 
== Funktionsfähigkeit auf allen Gateways ==


Um sicher zu stellen, dass das DNS im ganzen Netz funktioniert, müssen alle Gateways korrekt konfiguriert sein.
Um sicher zu stellen, dass das DNS im ganzen Netz funktioniert, müssen alle Gateways korrekt konfiguriert sein.
Es gibt 3 Möglichkeiten um dies zu erreichen:
Dabei sollte man immer beachten, dass der DNS nicht aus dem Internet sondern nur aus dem Freifunknetz erreichbar ist.
* Kein eigener DNS-Server
Es gibt mehrere Möglichkeiten um dies zu erreichen:
*:Wenn kein eigener DNS-Server betrieben wird, bitte nicht auf einen öffentlichen verweisen, sondern auf einen unserer Server. Somit braucht man sich um die Konfiguration keine Gedanken machen.  
 
**Aktuell wären das:
===  Andere DNS Server nutzen ===
*** 10.83.252.11 o. fd43:5602:29bd:ffff:a:a:a:a  (ChristianDr)
Es muss nicht zwingend ein eigener DNS-Server betrieben werden. Es sollte aber möglichst nicht einer der großen bekannten öffentlichen (z.B. 1.1.1.1 oder 2606:4700:4700::1111) verwendet werden, sondern besser einer unserer Server. Somit braucht man sich um die Konfiguration keine Gedanken machen. Am besten verwendet man primär die [[DNS#Anycast | Anycastadresse]] und dann [[DNS#Serveradressen | Serveradressen]] nach Wahl.
*** 10.50.40.10 (Mayosemmel)
*** 10.50.252.0 o. fd43:5602:29bd:ffff::252 (RedDog)
*** 10.83.252.62 o. fd43:5602:29bd:ffff::62 (Adrian)
*** 10.83.252.0 o. fd43:5602:29bd:ffff::42 ([[User:fblaese|fblaese]])
* Eigener DNS-Server mit peering der Zonen
*:Die Anzahl der DNS-Server sollte aber beschränkt bleiben. 3 sind eine gute Anzahl.
*:Hierzu sind die [[#Synchronisationsscript|untenstehenden Scripts]] und das Zutun der bereits am peering angeschlossenen Server Betreiber notwendig
* Eigener DNS-Server mit Static-Stub
*:siehe hierzu [[#StaticStub]]


==== Anycast ====


<span style="color:#ff0000">'''Hinweis:'''</span> Wenn ein eigener DNS-Server betrieben werden soll, sollte man unbedingt in Betracht ziehen auch die deutschlandweiten Freifunk-Zonen zu übernehmen. Wie das geht, steht hier: https://wiki.freifunk.net/DNS
Unter der Anycast Adresse antwortet immer der am besten zu erreichende Server:


Funktioniert analog zu unserer Konfiguration als "Static-Stub"
{| class="wikitable"
! IPv4-Adresse
! IPv6-Adresse
! Bemerkung
|-
| - || fd43:5602:29bd:ffff:1:1:1:1 || Anycast DNS
|-
| - || fd43:5602:29bd:ffff:1:1:1:64 || Anycast DNS64
|}


== Voraussetzungen ==
siehe auch [[Anycast-DNS]].


Debian:
==== Serveradressen ====


<code>
{| class="wikitable"
apt-get install bind9 bind9utils dnsutils
! IPv4-Adresse
</code>
! IPv6-Adresse
! Betreiber
! Bemerkung
|-
| <s>10.50.40.10</s> || – || [[Benutzer:Mayosemmel | Mayosemmel]] || z.Z. offline
|-
| 10.50.250.1 || fd43:5602:29bd:62::1 || [[Benutzer:Blackyfff | Blackyfff]] ||
|-
| 10.50.252.0 || fd43:5602:29bd:ffff::252 || [[Benutzer:RedDog | RedDog]] ||
|-
| 10.83.252.0 || fd43:5602:29bd:ffff::42 || [[Benutzer:fblaese | fblaese]] ||
|-
| 10.83.252.11 || fd43:5602:29bd:ffff:a:a:a:a || [[Benutzer:ChristianD | ChristianD]] ||
|-
| 10.83.252.62 || fd43:5602:29bd:ffff::62 || [[Benutzer:Adrian Schmutzler | Adrian Schmutzler]] ||
|-
| – || fd43:5602:29bd:ffff::37 || [[Benutzer:CHRiSNEW | CHRiSNEW]] ||
|}


== Static-Stub Konfiguration ==
==== DoH/DoT ====
<div id="StaticStub"></div>
Im Freifunk Franken Netz werden auch DoT/DoH DNS Server betrieben. Aktuell gibt es folgende Server:
Ein so genannter Static-Stub sorgt dafür, dass Bind für definierte Zonen immer zuerst die festgelegten DNS-Server anfragt.
Voraussetzung ist allerdings, dass keine Forwarder eingetragen sind.


Wir haben zur Zeit eine Forward und eine Reverse Lookup Zone. Diese sollten statisch eingetragen werden. Dies geschieht in der ''/etc/bind/named.conf.local''
{| class="wikitable"
! IPv4-Adresse
! IPv6-Adresse
! Service
! Domain für Zertifikat
|-
| 10.50.250.1 || fd43:5602:29bd:62::1 || DoT || dns.herpf.fff.community
|-
| - || fd43:5602:29bd:62::3 || DoT DNS64 || dns64.herpf.fff.community
|}


<pre>
=== eigener DNS Server als Cache mit forwarding ===
zone "50.10.in-addr.arpa" {
    type static-stub;
    server-addresses { 10.50.40.10; 10.83.252.11; 10.50.252.0; 10.83.252.62; };
};


zone "83.10.in-addr.arpa" {
Es kann auch ein eigener DNS Server betrieben werden und auf einen Freifunk DNS Server geforwardet werden.
    type static-stub;
    server-addresses { 10.50.40.10; 10.83.252.11; 10.50.252.0; 10.83.252.62; };
};


zone "fff.community" {
siehe hier: <br>
    type static-stub;
[[DNS#unbound als Cache mit forwarding | unbound als Cache mit forwarding]] <br>
    server-addresses { 10.50.40.10; 10.83.252.11; 10.50.252.0; 10.83.252.62; };
[[DNS#unbound als Cache mit forwarding auf DoT | unbound als Cache mit forwarding auf DoT]]
};
</pre>


In der /etc/bind/named.conf.options müssen eventuell vorhandene Forwarder entfernt werden. Untenstehend ein Beispiel:
=== eigener rekursiver Resolver mit Static-Stub ===
Wenn der Server die angefragten Domains nicht vorkonfiguriert weiterleitet, sondern den Namen selbst über die DNS Root Server auflöst, spricht man von einem rekursiven Resolver. Da aber unsere IP-Adressen nicht global aufgelöst werden können muss man die verantwortlichen Server selbst eintragen. Aktuell sind es 3 Reversezonen die eingetragen werden müssen. Optional kann man auch die Domain selbst eintragen, das beschleunigt die Namensauflösung ein bisschen.


<s><pre>
Hierbei ist zu beachten, dass die rekursiven Abfragen (IPv4 und IPv6) immer aus dem FFF-Netz heraus kommen sollten. Das ist für die Teilnehmer besser, da so die Antworten auf das FFF-Netz angepasst sind, was zu meißt kürzeren Routen zu externen Adressen führt. Da man dies in bind9 nicht direkt konfigurieren kann, sollte dies sichergestellt (metric, o.ä.) werden. Daher bietet sich hier eher unbound an. Ist es nicht möglich die Abfragen von FFF-internen Adressen zu führen, können die externen IPs auch entweder via babel announced werden oder (sofern die IPs statisch sind) auch in der Datei external.dnsserverips im Git [https://git.freifunk-franken.de/freifunk-franken/dns] eingetragen werden. Ist auch das nicht möglich, muss die fff.community Zone geforwardet werden (kein Static-Stub).
forwarders {
              8.8.8.8;


        };
<span style="color:#ff0000">'''Hinweis:'''</span> Wenn ein eigener DNS-Server betrieben werden soll, sollte man unbedingt in Betracht ziehen auch die deutschlandweiten Freifunk-Zonen zu übernehmen. Wie das geht, steht hier: https://wiki.freifunk.net/DNS
</pre></s>


Ebenfalls in der named.conf.options muss dnssec deaktiviert werden:
siehe hier: <br>
[[DNS#bind9 als rekursiver Resolver | bind9 als rekursiver Resolver]] <br>
[[DNS#unbound als rekursiver Resolver | unbound als rekursiver Resolver]]


<pre>
=== eigener rekursiver Resolver als autoritativer DNS ===
dnssec-validation no;
Die Grundfunktionalität ist wie beim Static-Stub, nur werden unsere eigenen Zonen hier auf dem Server selbst gespeichert.
</pre>


Weiterhin sollte das ICVPN-DNS aufgenommen werden. Wie das passiert ist [https://wiki.freifunk.net/DNS hier] erklärt.
siehe hier: <br>
[[DNS#bind9 als autoritativer DNS mit DNS64 und Split-View | bind9 als autoritativer DNS mit DNS64 und Split-View]] <br>


=== Beispielhafte Installation ===
== Beispielhafte Installation ==
Die Installation könnte dann etwa so aussehen:
Die Installation könnte dann etwa so aussehen:
<pre>
<pre>
Zeile 129: Zeile 150:
* /etc/init.d/isc-dhcp-server restart
* /etc/init.d/isc-dhcp-server restart


== Synchronisationsscript für DNS-Zones ==
<div id="Synchronisationsscript"></div>
Dieses script ist nur zu verwenden, wenn man ein Peering mit allen Serverbetreibern ausgehandelt hat. Bei "static-stub" oder "kein DNS" nicht nötig.


Dies ist notwendig um die Dezentralität zu wahren. Wobei man dazu sagen muss, dass unsere DNS Lösung nicht 100% dezentral ist. Daher sollte man unseren DNS als "Service innerhalb des Freifunknetzes Franken" ansehen.
== Konfigurationsbeispiele ==
 
In den aufgeführten Beispielen müssen die <XXXXX> jeweils durch selbst gewählte [[DNS#Andere DNS Server nutzen | DNS Server]] und/oder eine der [[DNS#Anycast | Anycast Adressen]] ersetzt werden. Vorzugsweise IPv6 vorrangig und IPv4 als sekundäre.
 
=== unbound als Cache mit forwarding ===
 
Konfigurationsdatei: /etc/unbound/unbound.conf
 
<pre>
server:
  access-control: 10.0.0.0/8 allow
  access-control: 127.0.0.0/8 allow
  access-control: 192.168.0.0/16 allow
  access-control: fc00::/7 allow
  cache-max-ttl: 14400
  cache-min-ttl: 1200
  hide-identity: yes
  hide-version: yes
  interface: 0.0.0.0
  interface: ::0
  rrset-roundrobin: yes
   
   
Im Gegensatz zu static-stub muss Folgendes in der named.conf.local eingetragen werden (Pfade ggf. anpassen):
# Enable or disable whether TCP queries are answered or issued.
do-tcp: yes
 
# Enable  or disable whether the upstream queries use TCP only for
# transport.  Useful in tunneling scenarios.
#tcp-upstream: yes
 
# If enabled id.server and hostname.bind queries are refused.
hide-identity: yes
 
# If enabled version.server and version.bind queries are refused.
hide-version: yes
 
# If yes, Unbound doesn't insert authority/additional sections
# into response messages when those sections are not required.
minimal-responses: yes
 
# If yes, message cache elements are prefetched before they expire
# to keep the cache up to date.
prefetch: yes
 
# Send minimum amount of information to  upstream servers to
# enhance privacy.
qname-minimisation: yes
 
# Enabled or disable whether the upstream queries use SSL only for
# transport.
# ACHTUNG! Nur einschalten wenn als Forwarder DoT Server verwendet werden
# ansonsten auskommentieren!
#ssl-upstream: yes
 
# Use 0x20-encoded random bits in the query to foil spoof
# attempts.
use-caps-for-id: no
 
forward-zone:
  name: "."
  forward-addr: <XXXXX>
  forward-addr: <XXXXX>
  [optional noch mehr]
</pre>
 
=== unbound als Cache mit forwarding auf DoT ===
 
folgende Parameter müssen zur [[DNS#unbound als Cache mit forwarding | Konfiguration ohne DoT]] geändert werden:
<pre>
tcp-upstream: yes
ssl-upstream: yes
 
forward-zone:
    name: "."
    forward-addr: <XXXXX-DNS64>@853#<XXXXX-DNS64-Servername>
</pre>
 
=== unbound als Cache bei mehreren Hoods auf einem Gateway ===
 
Bei mehreren Hoods arbeitet DNS je nach Hood auf verschiedenen IP-Adressen. Will man nun den DNS-Cache
analog zur Konfiguration mit Community DNS-Servern einheitlich auf den Transfer-Adressen nutzen, muss
die Antwort-IP-Adresse an die jeweilige Quell-IP-Adresse angepasst werden. Dafür ergänze folgenden
Parameter in der Konfigurationsdatei: /etc/unbound/unbound.conf


<pre>
<pre>
zone "fff.community" {
# Listen on all addresses on all (current and future) interfaces,
    type master;
# detect the source interface on UDP queries and copy them to
    file "/etc/bind/db.fff.community";
# replies. Experimental feature, default value is no.
    allow-transfer {10.50.252.0/24; 10.83.252.0/24; fd43:5602:29bd::/48; 2a0b:f4c0::/32;};
interface-automatic: yes
</pre>
 
Als alternative Methode können auch für jedes Interface, also jede Hood, die IPv4 und IPv6 Adressen
im jeweils für die Hood reservierten Adressband konfiguriert werden. Dies darf dann nur nicht vergessen werden, wenn später im Betrieb neue Interfaces hinzukommen.
 
=== bind9 als rekursiver Resolver ===
 
named.conf oder named.conf.options und named.conf.local; je nach Betriebssystem
 
<pre>
acl icvpnlocal {
10.0.0.0/8;
172.16.0.0/12;
fc00::/7;
};
};


zone "50.10.in-addr.arpa." {
options {
    type master;
directory "/tmp";
    file "/etc/bind/db.50.10";
 
auth-nxdomain no;
listen-on port 53 { any; };
listen-on-v6 port 53 { any; };
recursion yes;
allow-query-cache { icvpnlocal; localhost; };
allow-recursion { icvpnlocal; localhost; };
dnssec-validation no;
zone "." {
type hint;
file "/etc/bind/db.root";
};
zone "50.10.in-addr.arpa" {
type static-stub;
server-addresses { <XXXXX>; <XXXXX>; };
};
zone "83.10.in-addr.arpa" {
type static-stub;
server-addresses { <XXXXX>; <XXXXX>; };
};
zone "d.b.9.2.2.0.6.5.3.4.d.f.ip6.arpa" {
type static-stub;
server-addresses { <XXXXX>; <XXXXX>; };
};
zone "fff.community" {
type static-stub;
server-addresses { <XXXXX>; <XXXXX>; };
};
include "/etc/bind/icvpn-zones.conf";
 
// be authoritative for the localhost forward and reverse zones, and for
// broadcast zones as per RFC 1912
zone "localhost" {
type master;
file "/etc/bind/db.local";
};
zone "127.in-addr.arpa" {
type master;
file "/etc/bind/db.127";
};
zone "0.in-addr.arpa" {
type master;
file "/etc/bind/db.0";
};
zone "255.in-addr.arpa" {
type master;
file "/etc/bind/db.255";
};
};
};
</pre>
=== unbound als rekursiver Resolver ===
zu beachten ist, dass man die Anfragen (IPv4 und IPv6) immer aus dem FFF-Netz heraus stellt.
Ansonsten bekommt man bei Subdomains von fff.community nicht die internen IP-Adressen ausgeliefert.
folgende Parameter müssen zur [[DNS#unbound als Cache mit forwarding | forwarding Konfiguration]] hinzugefügt/entfernt werden:
<pre>
  # file to read root hints from.
  # get one from https://www.internic.net/domain/named.cache
  root-hints: "/var/lib/unbound/root.hints"
  auto-trust-anchor-file: /var/lib/unbound/root.key
  do-ip4: yes
  do-ip6: yes
  prefer-ip6: yes
  outgoing-interface: <public Freifunk IPv6>
  outgoing-interface: <lokale 10er Netz IPv4>
stub-zone:
  name: 50.10.in-addr.arpa
  stub-addr: <XXXXX>
  stub-addr: <XXXXX>
stub-zone:
  name: 83.10.in-addr.arpa
  stub-addr: <XXXXX>
  stub-addr: <XXXXX>


zone "83.10.in-addr.arpa." {
stub-zone:
    type master;
  name: d.b.9.2.2.0.6.5.3.4.d.f.ip6.arpa
    file "/etc/bind/db.83.10";
  stub-addr: <XXXXX>
};
  stub-addr: <XXXXX>
 
stub-zone:
  name: fff.community
  stub-addr: <XXXXX>
  stub-addr: <XXXXX>
 
</pre>
<S>
<pre>
forward-zone:
  name: "."
  forward-addr: <XXXXX>
  forward-addr: <XXXXX>
  [optional noch mehr]
</pre>
</pre>
</S>


==== randomisierte Upstream IPv6 ====
Um DNS spoofing zu erschweren bietet es sich an für den Upstream einen IPv6 Netzwerkblock anstelle einer einzelnen Adresse zu verwenden. Dafür muss man sich ein eigens dafür genutztes IPv6/64er Netz klicken, routing einrichten und im ifup an das lo interface hängen. Dann benutzt unbound für jede Abfrage (welche via IPv6 gemacht werden kann) eine zufällige Adresse aus diesem Netzblock.


Das Skript zum Erstellen/Updaten des Zone files (als root ausführen):
ifup
<pre>
ip -6 addr add <public IPv6 Präfix>/64 dev lo
ip -6 ro add local <public IPv6 Präfix>/64 dev lo
</pre>


unbound config
<pre>
<pre>
#!/bin/bash
outgoing-interface: <public IPv6 Präfix>/64
outgoing-interface: <lokale 10er Netz IPv4>
</pre>


#Server die abgefragt werden sollen (Alle DNS Peers)
=== bind9 als autoritativer DNS mit DNS64 und Split-View ===
DnsPeers=( 10.50.252.15 10.50.252.39 10.50.252.27 )
#Name der Zone die verteilt werden soll
DomainZone="fff.community"
#Position und Name des Zone Files
OwnZoneFile="/etc/bind/db.fff.community"
#Temporäres Verzeichnis - muss pro Zone exclusiv sein!
TempDir="/tmp/fff-dns"
#Backup Verzeichnis
BackupDir="/home/freifunk/DNS-Backup"
#Wie viele Backups sollen aufgehoben werden? Nur Integer Werte!
BackupsToStore=20


echo $(date) "Script started"
Bei dieser Konfiguration ist der Server autoritativ für die fff.community Domain und beantwortet Anfragen für diese und unsere Reversezonen direkt. Da der Server autoritativ ist muss er auch Anfragen aus dem Internet beantworten. Diese Anfragen landen dann im external-view und es werden dort hin nur Antworten für unsere Zone gegeben und auch nur öffentlich erreichbare IPs herausgegeben.
function dnsreload
{
        /etc/init.d/bind9 reload
}
function backup
{
datetime=$(date +"%Y-%m-%d_%H-%M-%S")
mkdir -p $1/$datetime
cp $OwnZoneFile $1/$datetime/.
BackupFiles=( $(ls -t $1) )
if [ -n ${BackupFiles[0]} ]  && [ ${#BackupFiles[@]} -gt 20 ]
then
rm -rf $1/${BackupFiles[$BackupsToStore]}
fi
}


function exit_script
Autoritative Server sollten nur in Absprache erstellt und auch als solche in der Zonendatei im Git [https://git.freifunk-franken.de/freifunk-franken/dns] eingetragen werden.
{
rm -rf $TempDir
echo $(date) "Script ended"
exit $1
}


mkdir -p $TempDir
Die nötigen Scripte und Konfigrationsbeispiele für den autoritativen Teil befinden sich im Git [https://git.freifunk-franken.de/freifunk-franken/dns-scripts]
cd $TempDir
OwnSerial=$(grep SOA $OwnZoneFile |awk 'NR==1{print $7}')
HighestSerialSoFar=0
for peer in "${DnsPeers[@]}"
do
echo $(date) "process DNS-Peer"
#Zone File von Peering DNS Servern herunterladen
dig @$peer $DomainZone axfr |grep -v ";"> $peer
#Seriennummer des Zone Files einlesen
PeerSerial=$(grep SOA $peer |awk 'NR==1{print $7}')
#Falls keine Seriennummer vorhanden, ist das File invalid oder die Verbindung zum Peer ist nicht in Ordnung
if [ -z $PeerSerial ]
then
rm -f $peer
continue
PeerSerial=1
fi
#Falls eigenes Zone File keine Seriennummer enthält und somit invalid ist, automatisch erstbestes valides nutzen
if [ -z $OwnSerial ]
then
named-checkzone  $DomainZone $peer
if [ $? -eq 0 ]
then
named-compilezone -o $OwnZoneFile $DomainZone $peer
fi
exit 0
fi
#Nur die Zone-Files mit dem höchsten Serial behalten - wenn dieser höher ist als der bereits vorhandene
if [ $OwnSerial -ge $PeerSerial ]
then
rm -f $peer
continue
elif [ ${HighestSerialSoFar[0]} -gt $PeerSerial ]
then
rm -f $peer
continue
else
HighestSerialSoFar=( $PeerSerial $peer )
fi
done


#Anzahl der verbliebenen Zone Files ermitteln
Für DNS64 benötigt man noch einen weiteren view
PeerZoneFileCount=$(ls -l|wc -l)
#Im Falle von einem Update vorher ein Backup machen
if [ $PeerZoneFileCount -gt 1 ]
then
backup $BackupDir $BackupsToStore
else
exit_script 0
fi


#Falls nur ein Zone File verblieben ist, direkt einspielen und neustarten
named.conf
if [ $PeerZoneFileCount -eq 2 ]
<pre>
then
[..]
echo $(date) "Check Zonefile1"
view "icvpn-internal-dns64-view" {
named-checkzone  $DomainZone ${HighestSerialSoFar[1]}
match-destinations {
        if [ $? -eq 0 ]
<separate IPv6 für dns64>;
        then
<anycast-dns64>;
echo $(date) "Copy Zonefile1"
};
named-compilezone -o $OwnZoneFile $DomainZone ${HighestSerialSoFar[1]}
dns64 64:ff9b::/96 {
        fi
break-dnssec yes;
dnsreload
mapped { !10/8; !192.168/16; !172.16/12; any; };
exit_script 0
exclude { 64:FF9B::/96; };
#Im Fall von mehreren Zone Files, prüfen ob alle identisch sind. Falls nicht Abbruch. Ansonsten einspielen und neustart
};
else
md5=$(md5sum ${HighestSerialSoFar[1]} |awk '{print $1}')
include "/etc/bind/icvpn-internal-dns64-view.conf";
for ZoneFile in *
do
loopmd5=$(md5sum $ZoneFile |awk '{print $1}')
if [ $md5 != $loopmd5 ]
then
echo $(date) $md5 $loopmd5
exit_script 1
fi
done
echo $(date) "Check Zonefile2"
named-checkzone  $DomainZone ${HighestSerialSoFar[1]}
        if [ $? -eq 0 ]
        then
echo $(date) "Copy Zonefile2"
named-compilezone -o $OwnZoneFile $DomainZone ${HighestSerialSoFar[1]}
fi
        dnsreload
        exit_script 0
fi


[..]


zone "." {
type hint;
file "/etc/bind/db.root";
};
};
[..]
</pre>
</pre>


== Script um die Reverse-DNS Zone zu erstellen ==
Der letzte Eintrag (zone ".") sorgt dafür, dass bind9 alle anderen Anfragen rekursiv auflöst. Das bitte nur bei den internen views setzen.


Das Skript muss jeweils einmal für 10.50.0.0/16 und 10.83.0.0/16 angelegt und entsprechend angepasst werden.
Alternativ kann die "." Zone auch an unbound geforwarded werden. Dann kann im unbound dnssec aktiviert werden und funktioniert dann wenigstens fürs Internet.
<pre>
zone "." {
type forward;
forward only;
forwarders {
::1 port <unbound port>;
};
};
</pre>


um doppeltes Cachen zu unterbinden muss man in den bind9 optionen dann noch folgendes setzen:
<pre>
<pre>
#!/bin/bash
max-cache-size 0;
</pre>
 
==== bekannte Probleme ====
 
Kommen folgende 4 Dinge zusammen:<br>
1. bind ist autoritativ für eine Zone<br>
2. diese Zone delegiert Subdomains an andere Server (NS) für welche bind nicht autoritativ ist<br>
3. bind ist neben der Aufgabe als autoritativer Server auch Resolver<br>
4. für die Aufgabe als Resolver ist in bind ein Forwarder eingetragen (ist bind selbst rekursiver Resolver tritt das Problem nicht auf)


#Name der Zone
Wird nun ein Hostname der delegierten Subdomain angefragt, kommt es zu einer Schleife zwischen bind und dem Forwarder mit folgender Fehlermeldung:
DomainZone="50.10.in-addr.arpa."
<pre>
#Positionen und Namen der Forward Lookup Zone Files
DNS format error from <FORWARDER> resolving <HOSTNAME> for <CLIENT>: Name <OWN AUTH DOMAIN> (NS) not subdomain of zone <DELEGATED SUBDOMAIN> -- invalid response
ForwardZoneFiles=("/etc/bind/db.fff.community")
</pre>
ReverseZoneFile="/etc/bind/db.50.10"
#Temporäres Verzeichnis - muss pro Zone exclusiv sein!
TempDir="/tmp/50.10.in-addr.arpa"
#TTL
TTL=3600
#refresh
refresh=2000
#retry
retry=6400
#expire
expire=2419200
#minimum
minimum=86400
#contact-mail
contact=franken.freifunk.net.
#responsible DNS Server by name(for reverseDNS your own)
responsible=fff-gw-m1.gw.fff.community.
#################################################################
function dnsreload
{
/etc/init.d/bind9 reload
}
function validate_ip()
{
    local  ip=$1
    local  stat=1


    if [[ $ip =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then
Um das Problem zu beheben müssen im Forwarder für die von bind delegierten Subdomains die jeweils dafür verantwortlichen Nameserver explizit für die Subdomain als Forwardingserver eingetragen werden.
        OIFS=$IFS
        IFS='.'
        ip=($ip)
        IFS=$OIFS
        [[ ${ip[0]} -le 255 && ${ip[1]} -le 255 \
            && ${ip[2]} -le 255 && ${ip[3]} -le 255 ]]
        stat=$?
    fi
    return $stat
}


== Testen ==


mkdir -p $TempDir
Testen können wir, indem wir vom DNS Server des Gateways (localhost/127.0.0.1) eine DNS-Auflösung abfragen.
Serials=()
for ForwardZoneFile in "${ForwardZoneFiles[@]}"
do
ZoneName=$(cat $ForwardZoneFile|grep SOA| awk '{ print $1 }'|head -n 1)
named-compilezone -o "$TempDir/$ZoneName" $ZoneName $ForwardZoneFile >/dev/null 2>&1
serial=$(cat "$TempDir/$ZoneName"|grep SOA| awk '{ print $7 }'|head -n 1)
Serials+=( "$serial" )
done


Serials=( $( for i in ${Serials[@]}; do echo "$i"; done | sort -rn ) )
Ein DNS Resolve für freifunk-franken.de ...
serial=${Serials[0]}
<code>
dig @127.0.0.1 freifunk-franken.de
</code>
...sollte von uns selber (Server localhost; 127.0.0.1) beantwortet werden:
<pre>
;; global options: +cmd


echo "$DomainZone $TTL IN SOA $responsible $contact $serial $refresh $retry $expire $minimum"> "$TempDir/$DomainZone"
;; Got answer:
echo "$DomainZone $TTL IN NS $responsible" >> "$TempDir/$DomainZone"
for ForwardZoneFile in $(ls $TempDir)
do
Hosts=($(cat "$TempDir/$ForwardZoneFile"|grep -v SOA|awk '{ print $1 }'))
IPs=$(cat "$TempDir/$ForwardZoneFile"|grep -v SOA|awk '{ print $5 }')
i=0
for IP in $IPs
do
if validate_ip $IP
then
echo $(echo $IP|awk 'BEGIN { FS = "." } ; { print $4 "." $3 "." $2 "." $1 }')".in-addr.arpa." $TTL IN PTR ${Hosts[$i]} >> "$TempDir/$DomainZone"
fi
i=$((i+1))
done
done


if [ -f $ReverseZoneFile ]; then
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 5819
        oldSerial=$(grep SOA $ReverseZoneFile |awk 'NR==1{print $7}')
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 13, ADDITIONAL: 1  
else
;; OPT PSEUDOSECTION:
        oldSerial=0
; EDNS: version: 0, flags:; udp: 4096
fi


if [ $serial -gt $oldSerial ]
;; QUESTION SECTION:
then
;freifunk-franken.de. IN A
named-compilezone -o $ReverseZoneFile $DomainZone "$TempDir/$DomainZone" >/dev/null 2>&1
;; ANSWER SECTION:
dnsreload
freifunk-franken.de. 3599 IN A 31.172.113.113
fi
.
rm -r $TempDir
.
.
;; Query time: 117 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: Tue Sep 08 14:16:32 EEST 2015
;; MSG SIZE  rcvd: 275
</pre>


Welche DNS Server ein angeschlossener Client angeboten bekommt, kann laufzeitaktuell mit folgenden Befehlen  abgefragt werden:
<pre>
nmcli device show <Netzwerkschnittstelle> | grep "IP4.DNS"
nmcli device show <Netzwerkschnittstelle> | grep "IP6.DNS"
</pre>
</pre>
== Script um die Reverse DNS Zone zu erstellen ==
Viel Magie, liegt jetzt im Git: [https://git.freifunk-franken.de/freifunk-franken/dns-scripts]
== Monitoring ==
Ein quick&dirty Monitor ist hier: [https://dns.herpf.fff.community/ffdns/monitor.html]

Aktuelle Version vom 3. April 2023, 02:46 Uhr

Konzept

Für die interne Nutzung im Freifunknetz besitzt F3 Netze e.V. die Domain fff.community. Im Gegensatz zu anderen Communites verwenden wir keine eigene Toplevel-Domain, um Kollisionen vorzubeugen und Probleme mit DNSSEC zu vermeiden.

Die Zone wird in einem Git [1] verwaltet und über Skripte [2] auf die für diese Zone autoritativen Nameserver einiger Freifunker synchronisiert.

Wenn jemand eine Domain für seinen Service haben möchte, kann dies mit einen Pull Request angefragt werden: [3]
Die Delegation von Subdomains ist ebenfalls möglich.

Da es sich bei der Namensauflösung für unsere Adressbereiche um Bereiche des privaten Adressraums handelt, sollten diese IP-Adressen nicht bei eigenen global auflösbaren Domains gesetzt werden. Da einige DNS Server gegen rebind Attacken aus dem globalen DNS geschützt sind, kann es vorkommen, dass die eigene globale Domain nicht auf die fd43:[..] oder 10.[..] IPs aufgelöst werden kann. Sollte dennoch gern eine globale Domain verwendet werden, dann bitte den jeweiligen Eintrag als CNAME auf einen [..].fff.community hostname setzen und die IP im Git [4] setzen.

Zone extern

Die Zone extern.fff.community wird automatisch angelegt. Diese enthällt keine Adressen des privaten IP-Bereichs und ist von überall erreichbar. Deswegen können im Zonefile bei einem Hostnamen alle IP-Adressen angegeben werden und für benötigtes Peering kann der gleiche Hostname aus dieser extern-Domain genutzt werden. Das funktioniert auch für delegierte Subdomains (z.B. gw01.herpf.fff.community -> gw01.herpf.extern.fff.community)

Funktionsfähigkeit auf allen Gateways

Um sicher zu stellen, dass das DNS im ganzen Netz funktioniert, müssen alle Gateways korrekt konfiguriert sein. Dabei sollte man immer beachten, dass der DNS nicht aus dem Internet sondern nur aus dem Freifunknetz erreichbar ist. Es gibt mehrere Möglichkeiten um dies zu erreichen:

Andere DNS Server nutzen

Es muss nicht zwingend ein eigener DNS-Server betrieben werden. Es sollte aber möglichst nicht einer der großen bekannten öffentlichen (z.B. 1.1.1.1 oder 2606:4700:4700::1111) verwendet werden, sondern besser einer unserer Server. Somit braucht man sich um die Konfiguration keine Gedanken machen. Am besten verwendet man primär die Anycastadresse und dann Serveradressen nach Wahl.

Anycast

Unter der Anycast Adresse antwortet immer der am besten zu erreichende Server:

IPv4-Adresse IPv6-Adresse Bemerkung
- fd43:5602:29bd:ffff:1:1:1:1 Anycast DNS
- fd43:5602:29bd:ffff:1:1:1:64 Anycast DNS64

siehe auch Anycast-DNS.

Serveradressen

IPv4-Adresse IPv6-Adresse Betreiber Bemerkung
10.50.40.10 Mayosemmel z.Z. offline
10.50.250.1 fd43:5602:29bd:62::1 Blackyfff
10.50.252.0 fd43:5602:29bd:ffff::252 RedDog
10.83.252.0 fd43:5602:29bd:ffff::42 fblaese
10.83.252.11 fd43:5602:29bd:ffff:a:a:a:a ChristianD
10.83.252.62 fd43:5602:29bd:ffff::62 Adrian Schmutzler
fd43:5602:29bd:ffff::37 CHRiSNEW

DoH/DoT

Im Freifunk Franken Netz werden auch DoT/DoH DNS Server betrieben. Aktuell gibt es folgende Server:

IPv4-Adresse IPv6-Adresse Service Domain für Zertifikat
10.50.250.1 fd43:5602:29bd:62::1 DoT dns.herpf.fff.community
- fd43:5602:29bd:62::3 DoT DNS64 dns64.herpf.fff.community

eigener DNS Server als Cache mit forwarding

Es kann auch ein eigener DNS Server betrieben werden und auf einen Freifunk DNS Server geforwardet werden.

siehe hier:
unbound als Cache mit forwarding
unbound als Cache mit forwarding auf DoT

eigener rekursiver Resolver mit Static-Stub

Wenn der Server die angefragten Domains nicht vorkonfiguriert weiterleitet, sondern den Namen selbst über die DNS Root Server auflöst, spricht man von einem rekursiven Resolver. Da aber unsere IP-Adressen nicht global aufgelöst werden können muss man die verantwortlichen Server selbst eintragen. Aktuell sind es 3 Reversezonen die eingetragen werden müssen. Optional kann man auch die Domain selbst eintragen, das beschleunigt die Namensauflösung ein bisschen.

Hierbei ist zu beachten, dass die rekursiven Abfragen (IPv4 und IPv6) immer aus dem FFF-Netz heraus kommen sollten. Das ist für die Teilnehmer besser, da so die Antworten auf das FFF-Netz angepasst sind, was zu meißt kürzeren Routen zu externen Adressen führt. Da man dies in bind9 nicht direkt konfigurieren kann, sollte dies sichergestellt (metric, o.ä.) werden. Daher bietet sich hier eher unbound an. Ist es nicht möglich die Abfragen von FFF-internen Adressen zu führen, können die externen IPs auch entweder via babel announced werden oder (sofern die IPs statisch sind) auch in der Datei external.dnsserverips im Git [5] eingetragen werden. Ist auch das nicht möglich, muss die fff.community Zone geforwardet werden (kein Static-Stub).

Hinweis: Wenn ein eigener DNS-Server betrieben werden soll, sollte man unbedingt in Betracht ziehen auch die deutschlandweiten Freifunk-Zonen zu übernehmen. Wie das geht, steht hier: https://wiki.freifunk.net/DNS

siehe hier:
bind9 als rekursiver Resolver
unbound als rekursiver Resolver

eigener rekursiver Resolver als autoritativer DNS

Die Grundfunktionalität ist wie beim Static-Stub, nur werden unsere eigenen Zonen hier auf dem Server selbst gespeichert.

siehe hier:
bind9 als autoritativer DNS mit DNS64 und Split-View

Beispielhafte Installation

Die Installation könnte dann etwa so aussehen:

cd /etc/bind

cat <<EOF >> named.conf.local
zone "50.10.in-addr.arpa" {
    type static-stub;
    server-addresses { 10.50.40.10; 10.83.252.11; 10.50.252.0; 10.83.252.62; };
};

zone "fff.community" {
    type static-stub;
    server-addresses { 10.50.40.10; 10.83.252.11; 10.50.252.0; 10.83.252.62; };
};
EOF

aptitude install python-yaml
git clone https://github.com/freifunk/icvpn-scripts.git
git clone https://github.com/freifunk/icvpn-meta.git
echo 'include "/etc/bind/named.conf.icvpn";' >> named.conf

cat <<EOF > update-icvpn.sh
#!/bin/bash
cd /etc/bind/icvpn-meta
git pull
cd ..
icvpn-scripts/mkdns -x franken -f bind -s icvpn-meta > named.conf.icvpn
/usr/sbin/rndc reload
EOF
chmod +x update-icvpn.sh

# falls das sich wg. fehlendem yaml beschwert wird python3 für das script verwendet - dann python3-yaml nachinstallieren!
./update-icvpn.sh

echo "10 2    * * *   root    /etc/bind/update-icvpn.sh" >> /etc/crontab

Der DHCP sollte natürlich auch angepasst werden:

In der dhcpd config:

  • option domain-name "fff.community";
  • Bitte auch keine Freifunk Fremden DNS Server verteilen, wenn kein eigener DNS betrieben werden soll, lieber einige vorhandene Freifunk DNS Server announcen.

Danach:

  • /etc/init.d/isc-dhcp-server restart


Konfigurationsbeispiele

In den aufgeführten Beispielen müssen die <XXXXX> jeweils durch selbst gewählte DNS Server und/oder eine der Anycast Adressen ersetzt werden. Vorzugsweise IPv6 vorrangig und IPv4 als sekundäre.

unbound als Cache mit forwarding

Konfigurationsdatei: /etc/unbound/unbound.conf

server:
  access-control: 10.0.0.0/8 allow
  access-control: 127.0.0.0/8 allow
  access-control: 192.168.0.0/16 allow
  access-control: fc00::/7 allow
  cache-max-ttl: 14400
  cache-min-ttl: 1200
  hide-identity: yes
  hide-version: yes
  interface: 0.0.0.0
  interface: ::0
  rrset-roundrobin: yes
 
# Enable or disable whether TCP queries are answered or issued.
do-tcp: yes

# Enable  or disable whether the upstream queries use TCP only for
# transport.  Useful in tunneling scenarios.
#tcp-upstream: yes

# If enabled id.server and hostname.bind queries are refused.
hide-identity: yes

# If enabled version.server and version.bind queries are refused.
hide-version: yes

# If yes, Unbound doesn't insert authority/additional sections
# into response messages when those sections are not required.
minimal-responses: yes

# If yes, message cache elements are prefetched before they expire
# to keep the cache up to date.
prefetch: yes

# Send minimum amount of information to  upstream servers to
# enhance privacy.
qname-minimisation: yes

# Enabled or disable whether the upstream queries use SSL only for
# transport.
# ACHTUNG! Nur einschalten wenn als Forwarder DoT Server verwendet werden
# ansonsten auskommentieren!
#ssl-upstream: yes

# Use 0x20-encoded random bits in the query to foil spoof
# attempts.
use-caps-for-id: no

forward-zone:
   name: "."
   forward-addr: <XXXXX>
   forward-addr: <XXXXX>
   [optional noch mehr]

unbound als Cache mit forwarding auf DoT

folgende Parameter müssen zur Konfiguration ohne DoT geändert werden:

tcp-upstream: yes
ssl-upstream: yes

forward-zone:
    name: "."
    forward-addr: <XXXXX-DNS64>@853#<XXXXX-DNS64-Servername>

unbound als Cache bei mehreren Hoods auf einem Gateway

Bei mehreren Hoods arbeitet DNS je nach Hood auf verschiedenen IP-Adressen. Will man nun den DNS-Cache analog zur Konfiguration mit Community DNS-Servern einheitlich auf den Transfer-Adressen nutzen, muss die Antwort-IP-Adresse an die jeweilige Quell-IP-Adresse angepasst werden. Dafür ergänze folgenden Parameter in der Konfigurationsdatei: /etc/unbound/unbound.conf

# Listen on all addresses on all (current and future) interfaces,
# detect the source interface on UDP queries and copy them to
# replies. Experimental feature, default value is no.
interface-automatic: yes

Als alternative Methode können auch für jedes Interface, also jede Hood, die IPv4 und IPv6 Adressen im jeweils für die Hood reservierten Adressband konfiguriert werden. Dies darf dann nur nicht vergessen werden, wenn später im Betrieb neue Interfaces hinzukommen.

bind9 als rekursiver Resolver

named.conf oder named.conf.options und named.conf.local; je nach Betriebssystem

acl icvpnlocal {
	10.0.0.0/8;
	172.16.0.0/12;
	fc00::/7;
};

options {
	directory "/tmp";

	auth-nxdomain no;
	listen-on port 53 { any; };
	listen-on-v6 port 53 { any; };
	recursion yes;
	allow-query-cache { icvpnlocal; localhost; };
	allow-recursion { icvpnlocal; localhost; };
	dnssec-validation no;
	
	zone "." {
		type hint;
		file "/etc/bind/db.root";
	};
	
	zone "50.10.in-addr.arpa" {
		type static-stub;
		server-addresses { <XXXXX>; <XXXXX>; };
	};
	
	zone "83.10.in-addr.arpa" {
		type static-stub;
		server-addresses { <XXXXX>; <XXXXX>; };
	};
	
	zone "d.b.9.2.2.0.6.5.3.4.d.f.ip6.arpa" {
		type static-stub;
		server-addresses { <XXXXX>; <XXXXX>; };
	};
	
	zone "fff.community" {
		type static-stub;
		server-addresses { <XXXXX>; <XXXXX>; };
	};
	
	include "/etc/bind/icvpn-zones.conf";

	// be authoritative for the localhost forward and reverse zones, and for
	// broadcast zones as per RFC 1912
	
	zone "localhost" {
		type master;
		file "/etc/bind/db.local";
	};
	
	zone "127.in-addr.arpa" {
		type master;
		file "/etc/bind/db.127";
	};
	
	zone "0.in-addr.arpa" {
		type master;
		file "/etc/bind/db.0";
	};
	
	zone "255.in-addr.arpa" {
		type master;
		file "/etc/bind/db.255";
	};
};

unbound als rekursiver Resolver

zu beachten ist, dass man die Anfragen (IPv4 und IPv6) immer aus dem FFF-Netz heraus stellt. Ansonsten bekommt man bei Subdomains von fff.community nicht die internen IP-Adressen ausgeliefert. folgende Parameter müssen zur forwarding Konfiguration hinzugefügt/entfernt werden:

  # file to read root hints from.
  # get one from https://www.internic.net/domain/named.cache
  root-hints: "/var/lib/unbound/root.hints"
  auto-trust-anchor-file: /var/lib/unbound/root.key
  do-ip4: yes
  do-ip6: yes
  prefer-ip6: yes
  outgoing-interface: <public Freifunk IPv6>
  outgoing-interface: <lokale 10er Netz IPv4>

stub-zone:
  name: 50.10.in-addr.arpa
  stub-addr: <XXXXX>
  stub-addr: <XXXXX>

stub-zone:
  name: 83.10.in-addr.arpa
  stub-addr: <XXXXX>
  stub-addr: <XXXXX>

stub-zone:
  name: d.b.9.2.2.0.6.5.3.4.d.f.ip6.arpa
  stub-addr: <XXXXX>
  stub-addr: <XXXXX>

stub-zone:
  name: fff.community
  stub-addr: <XXXXX>
  stub-addr: <XXXXX>

forward-zone:
   name: "."
   forward-addr: <XXXXX>
   forward-addr: <XXXXX>
   [optional noch mehr]

randomisierte Upstream IPv6

Um DNS spoofing zu erschweren bietet es sich an für den Upstream einen IPv6 Netzwerkblock anstelle einer einzelnen Adresse zu verwenden. Dafür muss man sich ein eigens dafür genutztes IPv6/64er Netz klicken, routing einrichten und im ifup an das lo interface hängen. Dann benutzt unbound für jede Abfrage (welche via IPv6 gemacht werden kann) eine zufällige Adresse aus diesem Netzblock.

ifup

ip -6 addr add <public IPv6 Präfix>/64 dev lo
ip -6 ro add local <public IPv6 Präfix>/64 dev lo

unbound config

	outgoing-interface: <public IPv6 Präfix>/64
	outgoing-interface: <lokale 10er Netz IPv4>

bind9 als autoritativer DNS mit DNS64 und Split-View

Bei dieser Konfiguration ist der Server autoritativ für die fff.community Domain und beantwortet Anfragen für diese und unsere Reversezonen direkt. Da der Server autoritativ ist muss er auch Anfragen aus dem Internet beantworten. Diese Anfragen landen dann im external-view und es werden dort hin nur Antworten für unsere Zone gegeben und auch nur öffentlich erreichbare IPs herausgegeben.

Autoritative Server sollten nur in Absprache erstellt und auch als solche in der Zonendatei im Git [6] eingetragen werden.

Die nötigen Scripte und Konfigrationsbeispiele für den autoritativen Teil befinden sich im Git [7]

Für DNS64 benötigt man noch einen weiteren view

named.conf

[..]
view "icvpn-internal-dns64-view" {
	match-destinations {
		<separate IPv6 für dns64>;
		<anycast-dns64>;
	};
	dns64 64:ff9b::/96 {
		break-dnssec yes;
		mapped { !10/8; !192.168/16; !172.16/12; any; };
		exclude { 64:FF9B::/96; }; 
	};
	
	include "/etc/bind/icvpn-internal-dns64-view.conf";

	[..]

	zone "." {
		type hint;
		file "/etc/bind/db.root";
	};
};
[..]

Der letzte Eintrag (zone ".") sorgt dafür, dass bind9 alle anderen Anfragen rekursiv auflöst. Das bitte nur bei den internen views setzen.

Alternativ kann die "." Zone auch an unbound geforwarded werden. Dann kann im unbound dnssec aktiviert werden und funktioniert dann wenigstens fürs Internet.

zone "." {
	type forward;
	forward only;
	forwarders {
		::1 port <unbound port>;
	};
};

um doppeltes Cachen zu unterbinden muss man in den bind9 optionen dann noch folgendes setzen:

	max-cache-size 0;

bekannte Probleme

Kommen folgende 4 Dinge zusammen:
1. bind ist autoritativ für eine Zone
2. diese Zone delegiert Subdomains an andere Server (NS) für welche bind nicht autoritativ ist
3. bind ist neben der Aufgabe als autoritativer Server auch Resolver
4. für die Aufgabe als Resolver ist in bind ein Forwarder eingetragen (ist bind selbst rekursiver Resolver tritt das Problem nicht auf)

Wird nun ein Hostname der delegierten Subdomain angefragt, kommt es zu einer Schleife zwischen bind und dem Forwarder mit folgender Fehlermeldung:

DNS format error from <FORWARDER> resolving <HOSTNAME> for <CLIENT>: Name <OWN AUTH DOMAIN> (NS) not subdomain of zone <DELEGATED SUBDOMAIN> -- invalid response

Um das Problem zu beheben müssen im Forwarder für die von bind delegierten Subdomains die jeweils dafür verantwortlichen Nameserver explizit für die Subdomain als Forwardingserver eingetragen werden.

Testen

Testen können wir, indem wir vom DNS Server des Gateways (localhost/127.0.0.1) eine DNS-Auflösung abfragen.

Ein DNS Resolve für freifunk-franken.de ... dig @127.0.0.1 freifunk-franken.de

...sollte von uns selber (Server localhost; 127.0.0.1) beantwortet werden:

;; global options: +cmd

;; Got answer:

;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 5819
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 13, ADDITIONAL: 1 
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096

;; QUESTION SECTION:
;freifunk-franken.de. IN A
;; ANSWER SECTION:
freifunk-franken.de. 3599 IN A 31.172.113.113	
.
. 
.
;; Query time: 117 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: Tue Sep 08 14:16:32 EEST 2015
;; MSG SIZE  rcvd: 275

Welche DNS Server ein angeschlossener Client angeboten bekommt, kann laufzeitaktuell mit folgenden Befehlen abgefragt werden:

nmcli device show <Netzwerkschnittstelle> | grep "IP4.DNS"
nmcli device show <Netzwerkschnittstelle> | grep "IP6.DNS"

Script um die Reverse DNS Zone zu erstellen

Viel Magie, liegt jetzt im Git: [8]

Monitoring

Ein quick&dirty Monitor ist hier: [9]