bind9: Views, DNSSEC, AD, AA, DO, RA, RD

Ich fange diesen Artikel bewusst mit einem Zitat von Stephane Bortzmeyer an, einem der Betreiber der TLD-DNS-Server für die .fr-Zone:

Views are brittle and complicated and should be avoided.

Fühlt Euch also gewarnt. Es gibt (für mich) zwei gute Gründe, Views einzusetzen. Der Erste ist das Bedürfnis, gewisse interne Zonendaten (z.B. die RFC1918-IPs meiner virtuellen Maschinen sowie die Adressen der Point-to-Point-Links, die selbige verbinden, jeweils vor- wie auch rückwärts) auch wirklich nur den Clients zur Verfügung zu stellen, die sie benötigen. Der andere hat mit einer Besonderheit von DNSSEC zu tun und der Tatsache, daß ich nunmal kein ganzes Array von Servern besitze und somit auf ein und dem selben Server gerne einen authoritativen und einen rekursiven Nameserver zur gleichen Zeit betreiben möchte. Holen wir also zu einem Rundumschlag in Sachen Begriffsklärung aus (und erledigen den Buchstabensalat aus der Überschrift):

  • Wenn ein Client (das kann jetzt ein Programm mit einer DNSSEC-fähigen Resolver-Library oder z.B. ein DNSSEC sprechender Nameserver, der Clients bedient, sein) Daten haben möchte, die mit DNSSEC authentifiziert wurden, so setzt er dazu in seiner Anfrage das DNSSEC OK (DO)-Bit.
  • Ist der anfragende Client kein echter Resolver, der in der Lage ist, einen beliebigen Namen aufzulösen, in dem er sich “von oben herab” durch die DNS-Hierarchie hangelt, dann teilt er dem Server, dem er die Anfrage schickt mit, daß doch bitte jener für ihn die Rekursion übernehmen solle - er setzt das Recursion Desired (RD)-Bit.
  • Wenn der Server, den die Anfrage trifft, so konfiguriert wurde, daß er dem Client die Rekursion abnimmt, dann setzt er in seiner Antwort das Recursion Allowed (RA)-Bit.
  • Der Client bekommt die Bestätigung, daß die Antwort kryptographisch verifiziert wurde, in dem in der Antwort das Authenticated Data (AD)-Bit gesetzt wird.
  • Ein Nameserver, der auf eine Anfrage betreffend einer Zone, für die er verantwortlich ist, antwortet, setzt das Authenticated Answer (AA)-Bit.

Und hier haben wir ein Problem: Angenommen, der BIND9 auf _thrassa.incertum.net_sei sowohl authoritativer Server für die Zone incertum.net, aber auch rekursiver Resolver für irgendeine VM auf der Kiste. Wenn ihn jetzt eine Anfrage mit gesetztem DO-Bit nach einem Eintrag aus der Zone incertum.net erreicht, dann müsste er gleichzeitig AA und AD setzten - das geht aber nicht, die beiden schließen sich gegenseitig aus (nur weil der authoritative Server Schlüssel hat, heisst das ja nicht, daß das auch die richtigen sind. Die ganze chain of trust kann nur ein rekursiver Resolver verifizieren).

Und hier kommen Views in’s Spiel. Man legt sich einfach einen View für interne Clients an, bei dem man Rekursion zulässt und in dem man die Zonen definiert, die nur interne Clients sehen sollen (N.B: Wenn man auch nur eine einzige Zone in einem View anlegt, dann muss man das mit allen Zonen so machen!). Die zweite Ansicht ist dann die, die wir nach außen präsentieren. Wenn ein interner Client jetzt eine Anfrage mit gesetztem DO-Bit an den Nameserver schickt, dann verifiziert dieser von oben nach unten die Vertrauensstellung der einzelnen Zonen und kommt dann irgendwann bei sich selber an - der Client erhält so das gewünschte AD- und nicht das AA-Bit.

Wichtig: Aus dem oben gesagten folgt, wenn man BIND9 ein bisschen kennt, dass man auf keinen Fall die IP(s), auf denen der Server die offizielle Zone dem Rest der Welt präsentieren soll, mit in die Liste der Clients aufnimmt, die den rekursiven View zu sehen bekommen soll. Man handelt sich sonst nur einen Haufen Fehlermeldungen der Art lame server resolving <eine unserer Adressen>: <IP unseres Servers> ein.

Die Umsetzung ist dann relativ straightforward und kann bei Debian in der Datei named.conf.local erfolgen - na ja, fast, denn bevor wir loslegen, müssen wir noch eine Zeile aus der named.conf entfernen (wir erinnern uns: Eine Zone in einem View, alle Zonen in einem View!):

// moved to named.conf.local due to view usage
//include "/etc/bind/named.conf.default-zones";

Es handelt sich dabei um diverse Zonen, die wir sowieso nur für den rekursiven View brauchen können. In der named.conf.local steht bei mir dann z.B. folgendes:

acl "mynets" {
  127.0.0.1; 192.168.0.0/16;
};

acl "secondaries" {
  85.214.108.195; 88.198.26.233;
};

view "internal" {
  match-clients { mynets; };
  recursion yes;
  allow-transfer { none; };

  // KVM
  zone "kvm.incertum.net" {
    type master;
    file "/etc/bind/forward-zones/kvm.incertum.net";
  };

  // KVM reverse
  zone "168.192.in-addr.arpa" {
    type master;
    file "/etc/bind/reverse-zones/kvm.incertum.net";
  };

  // included here due to view usage
  include "/etc/bind/named.conf.default-zones";
};

view "external"  {
  match-clients { any; };
  recursion no;
  allow-transfer { secondaries; };

  zone "incertum.net" {
    type master;
    file "/etc/bind/forward-zones/incertum.net.signed";
  };
};

Ich bin gerade ernsthaft am Überlegen, ob ich obigen Auszug kommentieren soll, aber ich glaube, er spricht für sich. Wichtig ist, wie oben erwähnt, daß man keine der IPs, auf denen der Server nach außen hin die offiziellen Zonen präsentieren soll und auch keinen der Secondaries versehentlich in den internen View aufnimmt. Und man sollte ebenfalls wissen, daß das Setup unglaublich viel komplexer wird wenn man z.B. dynamische Updates mit dazunimmt. Also kommt bitte nicht bei mir vorbei, wenn ihr Euch Euren DNS zerschießt.

Ohne jeglichen Zusammenhang: Morgen kommt der Packerlmann und bringt mir The Road To Reality. Gehirn, stell’ Dich schonmal drauf ein, Du wirst ab jetzt wieder benutzt!