

	\documentclass[a4paper,11pt]{article}
	\usepackage{ngerman}
	\usepackage[latin1]{inputenc}
	\setlength\parskip{\medskipamount}
	\setlength\parindent{0pt}
	\begin{document}

	
 % dns
 % Copyright Steffen Dettmer
 % Lizenz: GFDL
 % 
 % $Name: $
 % $Revision: 1.4.2.19 $
 % $Source: /cvsroot/selflinux/tutorial/advanced/netzwerk_advanced/dns/dns,v $
 % SelfLinux-0.7.2
 %
 % Diese Datei ist Teil von SelfLinux http://www.selflinux.de
 %
 %%% $Id: dns,v 1.4.2.19 2002/12/07 17:33:15 jgraber Exp $

	\title{Domain Name System}


	
	    \author{Steffen Dettmer}
	    %\url{mailto:steffen@dett.de}
    

	\maketitle

	
	
	%\ref{../index.tex}
	
		%\ref{andere_dienste1.tex}
		Internet
	\ref{dns}

    \par{Layout}
    Peter Schneewind
	    %\url{mailto:peter@schneewind.net}
    
    	\par{Lizenz}
	GFDL
 
	\tableofcontents{}

        
	\section{Einführung} \label{d55e60}
        
  

  
  \par
  
Da sich ein Mensch IP-Nummern schlecht merken kann, benutzt man
lieber Namen. Nun braucht man einen Dienst, der diese irgendwie
in IP-Adressen übersetzen kann.
  

  
  \par
  
Zunächst führte man (auf jedem Host) die Datei
{\bf /etc/hosts} ein, in der,
durch Whitespace getrennt, eine IP-Adresse, ein Name und beliebig
viele Aliasnamen stehen. Der Name ist der ''erste, wirkliche, echte
Systemname'', die Aliasnamen sind zusätzliche. In der Praxis kann
das natürlich auch umgekehrt sein, denn manche Administratoren
verwechseln die Namen und geben dem System mit dem Kommando
{\bf hostname} einen
Namen, der eigentlich ''nur'' ein Alias ist. Dies kann unter
Umständen zu Problemen führen.
  

  
  \par
  
Eine {\bf /etc/hosts} kann zum Beispiel so aussehen:
  

 \begin{tabular}{|l|}
                  \hline
                  \begin{tt} 
        /etc/hosts\end{tt} \\ 
                  \hline
                  \begin{minipage}{130mm} 
                  \begin{scriptsize} 
                  \begin{verbatim} 
        
127.0.0.1    localhost
192.168.1.1  ns1.selflinux.de
192.168.1.2  ns2.selflinux.de
192.168.1.3  rebecca.selflinux.de www.selflinux.de
  \end{verbatim} 
                  \end{scriptsize} 
                  \end{minipage} \\
                  \hline
                  \end{tabular}

  
  \par
  
Neben dem {\bf localhost} Eintrag, der stets eingetragen sein sollte,
sind hier noch zwei Namesserver und ein Webserver eingetragen.
Der Webserver heißt eigentlich {\bf rebecca}, {\bf www} ist ein Zweit-
oder Aliasname.
  

  
  \par
  
Damit Namen auf allen Maschinen bekannt sind, müssen die Einträge
in allen {\bf /etc/hosts} auf allen
Maschinen stehen.
In den Anfängen des ARPA-Net wurde diese Datei als
{\bf hosts.txt}
dann auf alle Maschinen verteilt. Diese wurde schnell groß und
unübersichtlich. Um Konflikte zu vermeiden, kam man auf die
Idee, jeder Organisation einen Namen zu geben, der durch einen
Punkt dahinter geschrieben wurde. Damit blieben die Namen
eindeutig, auch wenn zwei Organisationen einen Host Namens
{\bf FTP} haben wollten, denn hinter dem Punkt waren sie
unterschiedlich. \linebreak 
Später kam noch eine weitere Unterteilung hinzu, nämlich die
nach Ländern. So gibt es jetzt einen Server www in der
Organisation selflinux in Deutschland, kurz www.selflinux.de. Die
Organisation bezeichnet man allgemeiner als
{\bf Domain}, was im mathematischen Sinne das
''Gemeinsame'' bedeutet.
 
			
 
  \par
  
Da das für tausende von Maschinen nicht mehr wartbar ist, erfand
man eine verteilte Datenbank, die das verwaltet, und nannte es
das {\bf Domain Name System}, kurz
{\bf DNS}.
Verteilte Datenbank bedeutet, daß jeder nur einen Teil
verwaltet. Eine einfache und hier günstige Struktur ist die
Baumstruktur, die angewendet wird. \linebreak 
An der Wurzel stehen die
sogenannten {\bf Top Level Domains},
{\bf TLD}s, z.B.
{\bf de}, {\bf com}, {\bf org}. Diese werden
von Wurzelservern bedient, also dem Teil der Datenbank, der
darüber Informationen hat. Englisch heißen diese
{\bf ROOT-SERVERS}. \linebreak 
Darunter kommen dann die Server, welche die 
TLD-Datenbanken haben, es sind mehere, um ausfallsicher zu sein
und die Last zu verteilen. Diese haben dann Informationen über
die Organisations-Domains, die man zusammen mit der TLD kurz mit
{\bf Domain} bezeichnet, eine Domain wäre z.B.
{\bf selflinux.de}. \linebreak 
Eine Domain hat in der Regel einen Namensserver, der nun endlich
die Namen wie {\bf www} kennt. Das nennt man
{\bf Delegation}.
 

 
  \par
  
Da DNS-Server aus Performancegründen Namen cachen (also
zwischenspeichern), kann es auch sein, daß ein anderer
Namensserver {\bf www.selflinux.de} kennt, aber er hat die
Information ''aus zweiter Hand''. Die Server, die die
Daten wirklich haben, meist eine Datei auf einer Platte, und
deren Antwort verbindlich ist, nennt man
{\bf autoritativ}. Bekommt man von einem
DNS-Server eine Antwort aus dem Cache, so ist sie als
{\bf non-autorativ} gekennzeichnet, d.h, sie
ist vielleicht nicht mehr gültig.
 

 
Ein TLD Server ist für eine TLD (z.B. {\bf de}) autoritativ.
 

 
  \par
  
Die ''Rootdomain'', die Vater/Mutterdomain, nennt man
''.''.
 

 
Ein ROOT-SERVER ist also für ''.'' autoritativ.
 

 
  \par
  
Die ROOT-SERVER delegieren nun die Autorität zu den TLD-Servern.
Der ROOT-SERVER ''weiß'' (und bestimmt), welcher
DNS-Server für z.B. {\bf de} autoritativ ist. Ein
 {\bf de}-Server enthält nun auch nicht die Daten über
 {\bf www} der Domain {\bf selflinux}, sondern er
delegiert die Autorität zu einem anderen DNS-Server, der nun
unter {\bf selflinux.de}; eintragen kann, was er will,
z.B. {\bf www}. 
 
\section{Resolver} \label{d55e215}
        

 
 
 
  \par
  
Ein Programm, z.B. ein WWW-Browser, muß nun natürlich so einen
DNS-Server fragen können.  Damit das nicht jedes Programm von
sich aus implementieren muß, ist das Bestandteil der libc. Dies
nennt man {\bf Resolver}, zu deutsch:
''Auflöser''. Die Funktionen verwenden
Konfigurationsdateien (bzw. bei Win entsprechende
Registryeinträge), um z.B. die IP Adresse des zu verwenden
Namensservers zu ermitteln. Der Resolver sendet eine Anfrage an
einen DNS-Server, und erwartet die (endgültige) Antwort. Der
DNS-Server muß nun hinten beginnend den Namen
auflösen. Soll er z.B. {\bf www.selflinux.de} für den
Klienten auflösen, muß er sich dabei rekursiv durch die
DNS-Struktur hangeln. 
 

 
  \par
  
Er fragt zuerst einen ROOT-SERVER nach den DNS-Servern (falls
noch nicht im Cache), die für {\bf de.} autoritativ sind.
Dann fragt er einen dieser nach den für {\bf selflinux.de.}
autoritativen, und einen von diesen nach
{\bf www.selflinux.de.}. Hat er die Antwort im Cache, oder
hatte ein anderer DNS-Server (der von ''unserem'' als
{\bf Forwarder} benutzt wird, der also die Anfragen
weitergereicht bekommt) die Antwort im Cache, so wird sie dem
Client als {\bf non-authoritative} gekennzeichnet
übermittelt. Diese Information bekommt das Programm
normalerweise allerdings nicht zu sehen.
 

 
Es gibt auch DNS-Server, die diese rekursiven Resolveranfragen
nicht auflösen. Diese können von einem Client nicht als
DNS-Server benutzt werden. Das reduziert die Belastung dieser
DNS-Server, was z.B. bei den ROOT-Servern wichtig ist.
 

 
  \par
  
Häufig wird unter UN*X der BSD-Resolver verwendet. Dieser wird
mit der Datei {\bf /etc/resolv.conf} konfiguriert.
Hier können einige
Optionen gesetzt werden. Eine ist natürlich die zu verwendenden
Namensserver. Diese werden einfach untereinander (jeder in einer
Zeile) aufgezählt (z.B.: ''nameserver 127.0.0.1'' usw.).
Zusätzlich wird hier die DNS-Domain eingetragen (z.B.:
''domain self-linux.de''), und eine Suchliste (z.B.:
''search selflinux.de de com'' - ein benutzerfreundliches
Beispiel).
 

 
Es wird immer der erste Namenserver gefragt, außer
wenn dieser ausfällt. Nach einem großzügigen Timeout wird dann
der zweite verwendet.
 

 
  \par
  
Es gibt eine Erweiterung, der
{\bf Splitted Resolver}. Hier kann man zusätzlich
angeben, für welche Domains der Namesserver verwendet wird (die
Option ''nameserver'' erhält dies als weiteren
Parameter). Diese Erweiterung ist allerdings relativ selten
anzutreffen. Die Suchliste funktioniert wie folgt: \linebreak 
Wird ein Name nicht gefunden,
so wird der erste Teil der Suchliste angehängt (also
selflinux.de). Wird auch der so erweitere Name nicht gefunden, so
wird dem ursprünglichen der zweite Teil angehängt, und eine
dritte Anfrage gestartet usw. Der Client (also das Programm)
bemerkt davon nichts. So kann man sich etwas Schreibarbeit
sparen. Eine Beispieldatei wäre also:
 

 \begin{tabular}{|l|}
                  \hline
                  \begin{tt} 
        /etc/resolv.conf\end{tt} \\ 
                  \hline
                  \begin{minipage}{130mm} 
                  \begin{scriptsize} 
                  \begin{verbatim} 
        
domain selflinux.de
search selflinux.de de com
nameserver 127.0.0.1
nameserver 192.168.1.53
  \end{verbatim} 
                  \end{scriptsize} 
                  \end{minipage} \\
                  \hline
                  \end{tabular}
   
 
Sicherheitshalber sollte man stets mehrere Nameserver angeben.
 
			
 
  \par
  
Verwendet man Windows-Clients, so sind diese Paramter im
entsprechenden Fenster einzustellen. Dabei ist zu beachten, daß
Windows Namen grundsätzlich zuerst über das
Windows-Namensprotokoll aufzulösen versucht, was zu unerwarteten
Effekten führen kann.
 
   
 
  \par
  
In einer weiteren Datei ({\bf /etc/nsswitch.conf})
legt man unter
moderneren UN*X-Varianten fest, in welcher
Reihenfolge welche
Methoden zur Namensauflösung verwendet werden (lokale Dateien,
DNS oder NIS). Die entsprechende Option heißt ''hosts''.
In einer
typischen DNS-Konfiguration (ohne NIS) ist sie meist auf
 

 \begin{tabular}{|l|}
                  \hline
                  \begin{tt} 
        /etc/nsswitch.conf\end{tt} \\ 
                  \hline
                  \begin{minipage}{130mm} 
                  \begin{scriptsize} 
                  \begin{verbatim} 
        
hosts:  files dns
  \end{verbatim} 
                  \end{scriptsize} 
                  \end{minipage} \\
                  \hline
                  \end{tabular}

 
  \par
  
gesetzt (erst lokale Datei: {\bf /etc/hosts}, dann
DNS verwenden).
 

\section{Bind} \label{d55e307}
        
 

 
  \par
  
Im folgenden wird {\bf bind} in einer 8er-Version
vorrausgesetzt. {\bf bind} ist der Nameserver-Deamon, 
der vom Internet Software Consortium gepflegt und
entwickelt wird. Es sind zwar noch hier und da Versionen 4.x
im Einsatz, diese sterben jedoch aus. Neue Server sollten immer 
eine aktuelle Version erhalten, und auch bestehende sollten 
hin und wieder geupdatet werden, insbesondere, wenn 
Sicherheitslücken bekannt geworden sind!
 

\section{Zonen} \label{d55e322}
        
 

 
  \par
  
Nun gibt es einen weiteren wichtigen Begriff:
{\bf Zone}. Ein Zone wird gerne mit einer Domain
verwechselt, da muß man aufpassen, die Unterschiede sind wichtig.
 

 
In Kurzform: Eine Zone ist das, für das ein DNS-Server
authoritativ ist, also etwas {\bf Delegiertes}.
 

 
  \par
  
Ein DNS-Server ist immer für eine oder mehrere Zones autoritativ
(nämlich die, die zu ihm delegiert wurden). Umgekehrt gibt es zu
jeder Zone einen DNS-Server, der für diese authorativ ist. Nun
gibt es aber sehr große Zones, z.B. die der Universität Berkeley
{\bf berkeley.edu}. Die DNS-Admins von Berkeley delegieren
also weiter. \linebreak Zum Beispiel könnte man die großen Zweige
{\bf cs} und {\bf math} delegieren. Die bekommen
einen eigenen Server und der Admin von {\bf cs} muß nicht
immer die Admins von Berkeley auffordern, einen Namen
einzutragen, das kann er selbst machen. Damit sind
{\bf cs} und {\bf math} Zonen der Domain Berkeley.
Diese bezeichnet man auch als {\bf Subdomains},
da sie unter Berkeley liegen.
 

 
  \par
  
Wir haben nun eine Domain, die aus mehreren Zonen besteht, und
jede Zone gehört zu genau einer Domain (nämlich Berkeley).
Berkeley selbst ist auch eine Zone, aber diese enthält nur wenige
Informationen, nämlich die Adressen der DNS-Server, die für
{\bf cs} und {\bf math} authoritativ sind, und
vielleicht noch ein paar Namen aus kleinen Subdomains wie z.B.
{\bf art}. Diese Subdomain liegt nun - im Gegensatz zu
{\bf cs} - in der Zone Berkeley! Das heißt also,
{\bf cs} hat einen eigenen Namensserver, ist also eine Zone,
{\bf art} jedoch nicht. Hier liegt also der Unterschied,
denn beides sind Subdomains, aber nur {\bf cs} ist eine
Subzone.
 

\section{DNS-Datenbank und deren Einträge} \label{d55e393}
        
 

 
  \par
  
Eine DNS-Datenbank besteht aus zwei wichtigen Typen von
Einträgen: Zuordnung von Namen zu Adressen (Addressrecords
''A''), und Einträgen, die einer Adresse einen Namen
zuordnen, also Zeigern auf einen Namen (Reverserecords
''PTR''). Daneben gibt es aber noch weitere. Diese
Einträge liegen in einer Zone, die von einem Namensserver
authoritativ verwaltet werden. Diese Einträge selbst nennt man
{\bf Resource Record}, kurz {\bf RR}.
 

 
  \par
  
Neben Namen und IP-Adressen gibt es einen RR (also
''Typ'') für die Eigenschaften einer Zone. Es gibt 
RRs, die Textinformationen beinhalten, die geographische 
Position festlegen und weitere.
 

 
Die DNS-Datenbank ist also eine verteilte Datenbank, die in Zonen
unterteilt ist. Diese Zonen werden von DNS-Servern bedient. Eine
Zone besteht aus Einträgen, die man Resource Records nennt.
 

\section{Meister und Sklaven} \label{d55e414}
        

 
 
 
  \par
  
Da man für große Zones mehere DNS-Server benötigt, können diese
Datenbanken übertragen werden. Auf einer Maschine werden die
Dateien gepflegt, und dann auf die anderen kopiert. Diese eine
Maschine nennt man ''Master'' oder
{\bf Primary}, die anderen ''Slave'' oder
{\bf Secondary}. Die letzteren sind die moderneren
Formen.
''Slave'' ist irreführend, denn ein Slave kann für einen
anderen ''Slave'' auch ''Master'' sein, und
außerdem ist ein Slave auch authoritativ für diese Zone.
 

 
Die DNS-Server von großen Zonen kann man in der Regel gar nicht
fragen, da sie stark abgesichert sind, dazu sind die
Secondaries da.
 

 
  \par
  
Von ''außen'' kann man nicht erkennen, ob man einen
Master oder einen Slave fragt, beide sind genauso authoritativ für
die Zone. Ein Slave legt die Zonendaten auch auf seiner Platte
ab, damit er auch nach einem Neustart Antworten liefern kann,
wenn der Master nicht erreichbar ist. Hier liegt der große
Unterschied zum Caching. Daten aus dem Cache werden beim
Neustart verworfen.
 

 
Daten aus dem Cache können niemals authoritativ sein.
 

 
  \par
  
Der DNS-Server bestimmt auch einige Eigenschaften der Zone
selbst, z.B. wie lange die Zone gecached werden darf, und in
welchen Zeitabständen die Secondaries prüfen sollen, ob sich die Zone
geändert hat. Diese Daten liegen in einem ganz speziellen
Record, dem {\bf Start of Authority}, kurz
{\bf SOA}. Dieser legt den Beginn und die
Eigenschaften einer Zone fest.
   
 \section{Resource Records} \label{d55e450}
        
  

  
  \par
  
Ein Record besteht aus mehreren Teilen: dem
{\bf Objekt} (Datenbankleute nennen es auch das
Schlüsselfeld), der {\bf TTL} (Time to live, die
maximale Zeit, die es gecacht werden darf), der
{\bf Klasse}, zu der der Record gehört, der
{\bf Typ} des Records (z.B. ''A'' für eine
Namen-Address-Zuordnung) und dem {\bf Inhalt}.
  

  
  \par
  
Die TTL gibt an, wie lange ein Objekt gecached werden darf, also
wie lange es in einem Cache lebt. Üblich sind Werte von drei oder
besser acht Stunden.
  

  
  \par
  
Die Klasse gibt an, zu welcher Netzwerkart der Name gehört.
Das Internet heißt {\bf IN}, das ist in 99,99% der
Fälle die verwendete Klasse, die wenigen Ausnahmen (Chaosnet
und Hesiod - damit man es mal gehört hat, früher gab es auch mal
CSNET) werden hier nicht behandelt, bis auf eine kleine Ausnahme.
  

  
  \par
  
Der Typ wurde schon erwähnt: Es gibt Namen, Adressen, Texte (die
wichtige Zusatzinformationen enthalten können), Aliasnamen,
Hostinformationen, Mailserver und andere. Einige davon gibt es
praktisch fast nur ''auf dem Papier''.
  
 \section{Start of Authority - Ein Beispiel} \label{d55e486}
        
 
 
  \par
  
Die Zone {\bf selflinux.de.} (ab jetzt schreiben wir immer, wenn wir
sicher sind, den vollen Namen zu meinen, einen
''.'' hinten dran, den Namen der Root-Zone) könnte so
aussehen (nur der SOA RR):
 

 
selflinux.de.  IN SOA [Inhalt]
 

  
  \par
  
Das Objekt ist die Zone. Es gehört zur Klasse Internet, und es handelt
sich um eine Zone, genauer gesagt, um den Start einer Autorität. 
  

  
  \par
  
Nun müssen hier etliche Informationen drinstehen: 
  

  \begin{list}{*}{}
    
	\item 
Der Name des primären Nameservers (Ursprungsserver)
    

    
	\item 
Eine EMailadresse, falls jemand mal eine Frage
  oder einen Hinweis hat. Hier wird anstatt des ''@'' Zeichens ein
  ''.'' verwendet (ja, hier darf eine EMailadresse im ersten Teil
  keinen Punkt enthalten!)
    
  \end{list}

  
  \par
  
Dann in Klammern:
  

  \begin{list}{*}{}
    
	\item 
Eine Seriennummer der Zonenversion, an der die Secondaries
  erkennen, ob sich was geändert hat
    

    
	\item 
Informationen, wann die Secondaries diese Zonendaten
  aktualisieren sollen (refresh) 
    

    
	\item 
Wie lange sie warten sollen, wenn das nicht klappt (retry)
    

    
	\item 
Nach welcher Zeit die Daten definitiv ungültig sind (expire)
    

    
	\item 
Wie lange ein RR mindestens gültig ist (min. TTL).
    
  \end{list}

  
  \par
  
Die Zeiten werden alle in Sekunden angegeben.
Da sich die Seriennummer stets erhöhen muß, hat es sich bewährt,
das aktuelle Datum im Format JJJJMMTT und eine zweistellige
tägliche laufende Nummer zu verwenden. So erkennt man auch
gleich, wann die Zone zum letzten Mal verändert wurde. 
  

  
  \par
  
Damit sieht ein SOA so aus ('';'' trennt Kommentare):
  

  \begin{tabular}{|l|}
                  \hline
                  \begin{tt} 
        named.hosts\end{tt} \\ 
                  \hline
                  \begin{minipage}{130mm} 
                  \begin{scriptsize} 
                  \begin{verbatim} 
        
selflinux.de. IN SOA pri-ns.selflinux.de. admin.selflinux.de. (
	2000012501 ; Serial (Seriennummer)
	10800	   ; Refresh (Aktualisierung) 3 Stunden
	3600	   ; Retry (neuer Versuch)
	864000	   ; Expire (ungültig nach 10 Tagen)
	86400 )    ; min. TTL (Mindestgültigkeit) 1 Tag
   \end{verbatim} 
                  \end{scriptsize} 
                  \end{minipage} \\
                  \hline
                  \end{tabular}

  
  \par
  
DNS ist nicht case-sensitv, {\bf .de.}, {\bf .De.};,
{\bf .DE.} ist also das gleiche. Deshalb schreibe ich RR-Typen und Klassen 

groß, Namen
klein, um besser unterscheiden zu können.
			
		\section{Die benötigten Resource Records für unsere Zone} \label{d55e567}
        
 

 
  \par
  
In dieser Zone gibt es selbstverständlich DNS-Server, die diese
Angaben weitergeben können. Diese RR's heißen {\bf NS}
- Name Server, das sieht dann so aus:
 
 \begin{tabular}{|l|}
                  \hline
                  \begin{tt} 
        selflinux.zone\end{tt} \\ 
                  \hline
                  \begin{minipage}{130mm} 
                  \begin{scriptsize} 
                  \begin{verbatim} 
        
selflinux.de. IN NS ns1.selflinux.de.
selflinux.de. IN NS ns2.selflinux.de.
  \end{verbatim} 
                  \end{scriptsize} 
                  \end{minipage} \\
                  \hline
                  \end{tabular}

 
  \par
  
Wir könnten auch noch pri-ns dazuschreiben, aber wir möchten
nicht, daß dieser viel gefragt wird, also lassen wir ihn weg.
 

 
  \par
  
Nun finden sich in der {\bf /etc/hosts} (beispielsweise) folgende
Einträge:
 

 \begin{tabular}{|l|}
                  \hline
                  \begin{tt} 
        /etc/hosts\end{tt} \\ 
                  \hline
                  \begin{minipage}{130mm} 
                  \begin{scriptsize} 
                  \begin{verbatim} 
        
192.168.1.1  ns1.selflinux.de
192.168.1.2  ns2.selflinux.de
192.168.1.3  rebecca.selflinux.de www.selflinux.de
  \end{verbatim} 
                  \end{scriptsize} 
                  \end{minipage} \\
                  \hline
                  \end{tabular}

 
  \par
  
Der ''localhost'' Eintrag paßt nicht in die Zone ''selflinux.de'', da
''localhost'' ja nicht mit ''selflinux.de'' endet.
 

 
  \par
  
rebecca hat einen Zweinamen ''www''. Zweitnamen sind
vom RR Type {\bf CNAME} (canonical name). Dabei
gilt es zu beachten, daß CNAMEs nie ''auf der rechten
Seite stehen dürfen''. Das bedeutet, es gibt keine
CNAMEs von CNAMEs, MX- oder NS-Records ''zeigen'' nicht
auf CNAMEs, sondern immer auf {\bf A}-Address-Records.
 

 
  \par
  
Diese nun übersetzt in RRs:
 

 \begin{tabular}{|l|}
                  \hline
                  \begin{tt} 
        
selflinux.zone
  \end{tt} \\ 
                  \hline
                  \begin{minipage}{130mm} 
                  \begin{scriptsize} 
                  \begin{verbatim} 
        
ns1.selflinux.de.     IN A 192.168.1.1  
ns2.selflinux.de.     IN A 192.168.1.2  
rebecca.selflinux.de. IN A 192.168.1.3  
www.selflinux.de.     IN CNAME rebecca.selflinux.de.
  \end{verbatim} 
                  \end{scriptsize} 
                  \end{minipage} \\
                  \hline
                  \end{tabular}

 
  \par
  
Hier sind keine TTLs (Cache-Zeiten) angegeben, es wird die min TTL
aus dem SOA Record verwendet. Wir könnten das aber machen, z.B.:
 

 \begin{tabular}{|l|}
                  \hline
                  \begin{tt} 
        
selflinux.zone
  \end{tt} \\ 
                  \hline
                  \begin{minipage}{130mm} 
                  \begin{scriptsize} 
                  \begin{verbatim} 
        
www.selflinux.de.     3600 IN CNAME rebecca.selflinux.de.
  \end{verbatim} 
                  \end{scriptsize} 
                  \end{minipage} \\
                  \hline
                  \end{tabular}

 
  \par
  
Der WWW-Name darf nur eine Stunde gecached werden (vielleicht
steht die Umstellung auf eine andere Maschine bevor?). Das senkt
die Performance, führt zu höherem Traffic, darf also nicht
versehentlich drin stehen bleiben.
 

 
  \par
  
Für die gesamte Zone sei ein Mailserver verantwortlich, z.B.
rebecca. Mit dem {\bf MX}-RR definiert man einen Mail Exchanger und
dessen Priorität. Niedrigere Prioritäten werden dabei vorgezogen.
Ein Eintrag könnte demnach lauten:
 

 \begin{tabular}{|l|}
                  \hline
                  \begin{tt} 
        
selflinux.zone
  \end{tt} \\ 
                  \hline
                  \begin{minipage}{130mm} 
                  \begin{scriptsize} 
                  \begin{verbatim} 
        
selflinux.de.	       IN MX 10 rebecca.selflinux.de.
  \end{verbatim} 
                  \end{scriptsize} 
                  \end{minipage} \\
                  \hline
                  \end{tabular}

 
  \par
  
Damit bekommt rebecca Mail für \verb+<+user\verb+>+@selflinux.de.
Natürlich muß das dortige Mailprogramm eMail dieses Aussehens 
annehmen, und nicht weitersenden (z.B. Klasse ''Cw''
bei {\bf sendmail} muß diese Namen
''selflinux.de'' [als Hostnamen] beinhalten).
Zusätzlich kann für jeden Host mittels Wildcard
''*'' dieser Mailexchanger erzwungen werden:
 

 \begin{tabular}{|l|}
                  \hline
                  \begin{tt} 
        
selflinux.zone
  \end{tt} \\ 
                  \hline
                  \begin{minipage}{130mm} 
                  \begin{scriptsize} 
                  \begin{verbatim} 
        
*.selflinux.de.	       IN MX 10 rebecca.selflinux.de.
  \end{verbatim} 
                  \end{scriptsize} 
                  \end{minipage} \\
                  \hline
                  \end{tabular}
 
 
  \par
  
Dabei ist zu beachten, daß das auch für garnicht existierende
Hosts matched, man kann also EMail an sowas wie
\verb+<+user\verb+>+@halleluja.ax123.selflinux.de senden.
 
\section{Die andere Seite - Reverse Lookups} \label{d55e681}
        
 

 
  \par
  
Nun kann hosts aber mehr, und zwar auch rückwärts: IP in Namen
''auflösen''. Das nennt man
{\bf reverse-lookups}. Um nicht ein neues
Schema (neben Domains und Zones) zu benötigen, hat man einfach
die Zones benutzt, das Konzept ist ja flexibel - schließlich kann
man nicht alle Domains durchfragen, bis man die Adresse gefunden
hat! 
 

 
  \par
  
Diese Art der Auflösung wird vor allem bei
sicherheitsempfindlichen Diensten verwendet. Das Tool
{\bf nslookup}
(siehe auch Abschnitt ''Testen der Konfigurationen'')
beispielsweise prüft, ob die IP-Adresse zu einem DNS-Server
existiert (macht also ein Reverse Lookup), und auch NFS-Server
lösen Client-IP-Adressen rückwärts auf. Der Sinn darin ist, DNS
Spoof-Angriffe zu erschweren. \linebreak 
Bei diesen Angriffen werden
DNS-Namen gefälscht, beispielsweise durch einen Eindringling auf
einem DNS-Server. Da häufig für Vorwärts- und Rückwärtsauflösung
verschiedene Server und vor allem verschiedene Delegationen
verwendet werden, muß ein Angreifer häufig die Kontrolle über
zwei DNS-Server erlangen, hat also etwas schlechtere Chancen.
 
 
 
  \par
  
Dafür gibt es einen neuen Domain-Namensraum, der nicht Namen
als Domains benutzt, sondern IP-Adressen. Dieser ist ziemlich
unabhängig vom ''normalen'' Namensraum! Diese Domain
hat man ''arpa'' genannt (eben aus historischen Gründen).
Da es für alle Klassen (z.B. Internet) eigene Adressen gibt,
ist auch diese Teil des Namens. Internet-Adressen sind
{\bf in-addr}, also heißt die Domain
''in-addr.arpa.''. Dieser Baum enthält dann letztlich
alle IP-Adressen. Diese muß man natürlich delegieren können! \linebreak 
Dabei gibt es eine Besonderheit: die allgemeineren, die
Netzwerknamen (Domainnamen) stehen ja hinten,
z.B. ist ''www'' ein Host im Netzwerk
''selflinux.de.''. Bei IP-Adressen steht das Netzwerk
aber vorn, der Hostanteil hinten! Bei der
Delegation wird ein bestimmter Teil (etwas
''Allgemeineres'', z.B. eine Domain) delegiert.
Wenn man das jetzt mit IP-Adressen macht, kann man nicht den
ersten Teil einer IP-Adresse delegieren, denn dann hätte man
ein ''Loch'' - den Hostanteil - das erst in einer
tieferen Instanz gefüllt werden könnte! Also muß man die
IP-Adresse byteweise umdrehen, so wird aus
''192.168.1.2'' ''2.1.168.192''.
Nun steht der Netzwerkanteil hinten, und man kann einen Teil
delegieren, wie auch bei Domainnamen. \linebreak Das kann
man wie bei Namen an jedem ''.'' machen. Die Zone
''in-addr.arpa.'' enthält also 255 Zonen, eine davon ist
''192.in-addr.arpa.'', diese enthält wiederum 255 Zonen
usw. Rebecca liegt also in Zone
''1.168.192.in-addr.arpa.''. Diese benötigt erst einmal
einen SOA Record. Namensserver und EMail seien wie oben.
 

\section{Eine Reverse Lookup Zone} \label{d55e714}
        
 

 \begin{tabular}{|l|}
                  \hline
                  \begin{tt} 
        1.168.192.zone\end{tt} \\ 
                  \hline
                  \begin{minipage}{130mm} 
                  \begin{scriptsize} 
                  \begin{verbatim} 
        
1.168.192.in-addr.arpa. IN SOA pri-ns.selflinux.de. admin.selflinux.de. (
	2000012501 ; Serial (Seriennummer)
	10800	   ; Refresh (Aktualisierung) 3 Stunden
	3600	   ; Retry (neuer Versuch)
	864000	   ; Expire (ungültig nach 10 Tagen)
        86400 )    ; min. TTL (Mindestgültigkeit) 1 Tag
  \end{verbatim} 
                  \end{scriptsize} 
                  \end{minipage} \\
                  \hline
                  \end{tabular}

 
  \par
  
Die Nameserver schreibt man auch einfach dazu:
 
 
 \begin{tabular}{|l|}
                  \hline
                  \begin{tt} 
        1.168.192.zone\end{tt} \\ 
                  \hline
                  \begin{minipage}{130mm} 
                  \begin{scriptsize} 
                  \begin{verbatim} 
        
1.168.192.in-addr.arpa. IN NS ns1.selflinux.de.
1.168.192.in-addr.arpa. IN NS ns2.selflinux.de.
  \end{verbatim} 
                  \end{scriptsize} 
                  \end{minipage} \\
                  \hline
                  \end{tabular}

 
  \par
  
Nun die drei eigentlichen Einträge. Man hat jetzt
{\bf PTR}-Records, weil wir ja rückwärts auflösen:
 

 \begin{tabular}{|l|}
                  \hline
                  \begin{tt} 
        1.168.192.zone\end{tt} \\ 
                  \hline
                  \begin{minipage}{130mm} 
                  \begin{scriptsize} 
                  \begin{verbatim} 
        
1.168.192.in-addr.arpa.1.	IN PTR	ns1.selflinux.de.
1.168.192.in-addr.arpa.2.	IN PTR	ns2.selflinux.de.
1.168.192.in-addr.arpa.3.	IN PTR	rebecca.selflinux.de.\end{verbatim} 
                  \end{scriptsize} 
                  \end{minipage} \\
                  \hline
                  \end{tabular}

 
  \par
  
(wieder ohne TTLs)
 

\section{Zonefiles} \label{d55e762}
        
 

 
  \par
  
Da das später Zonefiles für {\bf bind} werden
sollen, müssen diese in Dateien geschrieben werden.
Standardmäßig liegen diese in {\bf /var/named/}
- auch die von Primären Servern. Über die Namen der Dateien
gehen die Meinungen auseinander, insbesondere, wenn es um
Reverse-Lookup-Dateien geht. Viele sind gewoht, bei Dateien einen
Postfix anzuhängen (''.txt'', ''.c''), deshalb
kann man hier ''.zone'' verwenden. \linebreak 
Hier wird der Domainname + ''.zone'' verwendet, also
''selflinux.zone'' und ''1.168.192.zone'' (wenn
man nur in-addr für Reverse braucht, also vermutlich alle bis
auf ein paar Jungs vom MIT).
 

 
  \par
  
Bei Secondary Servern (Slaves) werden diese Dateien nicht per
Hand angelegt.  Sie werden vom Primary geholt, wenn es nötig ist,
also wenn die Refresh-Zeit um ist, oder der Primary eine
entsprechende Nachricht schickt. Die Daten werden dann in die
Dateien geschrieben, damit sie notfalls auch einen Neustart
''überleben''.
 

 
  \par
  
Für jede Zone gibt es eine Datei, und in jeder Datei darf nur ein
SOA vorkommen. Wir brauchen also bereits zwei, und da wir auch
vermutlich ''localhost'' auflösen können möchten, wie im
Prinzip fast jeder DNS-Server, sind wir schon bei vier.
 

\section{Abkürzungen} \label{d55e788}
        
 

 
  \par
  
Unsere Zonefiles sind nun ziemlich unübersichtlich, aber bei
{\bf bind}
sind einige Abkürzungen möglich. {\bf bind} weiß ja
(wir werden es ihm später sagen), welche Domain in welcher Datei
liegt.
 


 
  \par
  
bei dem Eintrag:
 
 
 \begin{tabular}{|l|}
                  \hline
                  \begin{tt} 
        selflinux.zone\end{tt} \\ 
                  \hline
                  \begin{minipage}{130mm} 
                  \begin{scriptsize} 
                  \begin{verbatim} 
        
ns1.selflinux.de.     IN A 192.168.1.1
  \end{verbatim} 
                  \end{scriptsize} 
                  \end{minipage} \\
                  \hline
                  \end{tabular}

 
  \par
  
Beispielsweise ist ja klar, daß er zu ''.selflinux.de.''
gehört (sonst wäre es die falsche Datei!). Das kann man
weglassen. Auch die Klasse kann man weglassen, dann wird
''IN'' angenommen, man erhält:
 

 \begin{tabular}{|l|}
                  \hline
                  \begin{tt} 
        selflinux.zone\end{tt} \\ 
                  \hline
                  \begin{minipage}{130mm} 
                  \begin{scriptsize} 
                  \begin{verbatim} 
        
ns1	A	192.168.1.1
  \end{verbatim} 
                  \end{scriptsize} 
                  \end{minipage} \\
                  \hline
                  \end{tabular}

 
  \par
  
Die Domain wird an alle Namen angehängt, nicht jedoch an 
IP-Adressen, die hinter einem ''A'' stehen. Aber an Namen,
die z.B. hinter einem ''CNAME'' stehen, es sei denn,
diese sind explizit als vollständig angegeben und enden mit
einem ''.''. \linebreak 
Beim SOA Record ist das ähnlich:
 

 \begin{tabular}{|l|}
                  \hline
                  \begin{tt} 
        selflinux.zone\end{tt} \\ 
                  \hline
                  \begin{minipage}{130mm} 
                  \begin{scriptsize} 
                  \begin{verbatim} 
        
selflinux.de. IN SOA pri-ns.selflinux.de. admin.selflinux.de.  (...)
  \end{verbatim} 
                  \end{scriptsize} 
                  \end{minipage} \\
                  \hline
                  \end{tabular}
 
 
  \par
  
Für die Domain ''selflinux.de'', in deren Datei wir uns
ja befinden, kann man auch ''@'' schreiben, also:
 

 \begin{tabular}{|l|}
                  \hline
                  \begin{tt} 
        selflinux.zone\end{tt} \\ 
                  \hline
                  \begin{minipage}{130mm} 
                  \begin{scriptsize} 
                  \begin{verbatim} 
        
@ IN SOA pri-ns.selflinux.de. admin.selflinux.de.  (...)
  \end{verbatim} 
                  \end{scriptsize} 
                  \end{minipage} \\
                  \hline
                  \end{tabular}
			
 
  \par
  
Die Domain wird auch hier angehängt, deshalb geht auch:
 
		       
 \begin{tabular}{|l|}
                  \hline
                  \begin{tt} 
        selflinux.zone\end{tt} \\ 
                  \hline
                  \begin{minipage}{130mm} 
                  \begin{scriptsize} 
                  \begin{verbatim} 
        
@	SOA	pri-ns admin (...)
  \end{verbatim} 
                  \end{scriptsize} 
                  \end{minipage} \\
                  \hline
                  \end{tabular} 

 
  \par
  
aber es sieht nicht mehr sehr gut aus...  Der Author mag z.B. gar
keine Abkürzungen in SOA Records, aber das ist Geschmackssache. 
 
 
 
  \par
  
Es gibt noch eine weitere Abkürzung: Gibt es mehrere RRs für
dasselbe Objekt, so muß dieses nur einmal (beim ersten RR)
genannt werden. Die weiteren werden dann so angenommen, also ist
auch erlaubt:
 
 
 \begin{tabular}{|l|}
                  \hline
                  \begin{tt} 
        selflinux.zone\end{tt} \\ 
                  \hline
                  \begin{minipage}{130mm} 
                  \begin{scriptsize} 
                  \begin{verbatim} 
        
selflinux.de. IN NS ns1.selflinux.de.
	      IN NS ns2.selflinux.de. 
  \end{verbatim} 
                  \end{scriptsize} 
                  \end{minipage} \\
                  \hline
                  \end{tabular}

 
  \par
  
Da hier diese Einträge direkt nach dem SOA Record kommen (der ja
ein RR für ''selflinux.de.'' ist), kann man bei 1. NS RR
(also beim 2. RR der Zone) dieses auch noch weglassen, was in
der Praxis meistens gemacht wird.
 

 
  \par
  
Auch muß man (für {\bf bind}, andere DNS-Server
machen das vielleicht anders!) die Zeiten im SOA und TTLs nicht
unbedingt in Sekunden angeben, man schreibt statt
''3600'' einfach ''3H''.
Es gibt für Tage (days) ''D'', für Wochen (weeks)
''W'' und für Monate (month) ''M''.
 

 
  \par
  
Verwendet man keine TTL-Angaben bei den Records, wird ein
Defaultwert verwendet. Ältere {\bf bind}-Versionen
verwenden hierzu stets min. TTL aus dem SOA Record, neuere
kennen dazu die Direktive {\bf \$TTL}, die im Zonefile
eingestellt wird. In den Beispielen wird hier immer eine
Default-TTL von einem Tag verwendet: {\bf \$TTL 1d}.
 
\section{Die fertigen Dateien} \label{d55e904}
        
 

 
  \par
  
Nun seien die folgenden beiden Dateien in
{\bf /var/named}:
 

 \begin{tabular}{|l|}
                  \hline
                  \begin{tt} 
        /var/named/selflinux.zone\end{tt} \\ 
                  \hline
                  \begin{minipage}{130mm} 
                  \begin{scriptsize} 
                  \begin{verbatim} 
        
$TTL 1d

selflinux.de.	IN  SOA pri-ns.selflinux.de. admin.selflinux.de. (
	2000012501 ; Serial (Seriennummer)
	3H	   ; Refresh (Aktualisierung)
	1H	   ; Retry (neuer Versuch)
	1M	   ; Expire (ungültig nach)
	1D )	   ; min. TTL (mindeste Gültigkeit)

		IN  NS    ns1.selflinux.de.
		IN  NS    ns2.selflinux.de.

ns1		IN  A	  192.168.1.1  
ns2		IN  A	  192.168.1.2  
rebecca		IN  A	  192.168.1.3  
www		IN  CNAME rebecca.selflinux.de.
 \end{verbatim} 
                  \end{scriptsize} 
                  \end{minipage} \\
                  \hline
                  \end{tabular}

 \begin{tabular}{|l|}
                  \hline
                  \begin{tt} 
        /var/named/1.168.192.zone\end{tt} \\ 
                  \hline
                  \begin{minipage}{130mm} 
                  \begin{scriptsize} 
                  \begin{verbatim} 
        
$TTL 1d

1.168.192.in-addr.arpa. IN SOA pri-ns.selflinux.de. admin.selflinux.de. (
	2000012501 ; Serial (Seriennummer)
	3H	   ; Refresh (Aktualisierung)
	1H	   ; Retry (neuer Versuch)
	1M	   ; Expire (ungültig nach)
	1D )	   ; min. TTL (mindeste Gültigkeit)

		IN  NS    ns1.selflinux.de.
		IN  NS    ns2.selflinux.de.

1		IN  PTR	  ns1.selflinux.de.
1 		IN  PTR	  ns2.selflinux.de.
1		IN  PTR	  rebecca.selflinux.de.
  \end{verbatim} 
                  \end{scriptsize} 
                  \end{minipage} \\
                  \hline
                  \end{tabular}

 
  \par
  
(ein hohes Expire ist in der Praxis durchaus sinnvoll)
 

 
  \par
  
Diese sollen nun von {\bf bind} als Primäre Zonen
verwaltet werden, er
soll autorativ sein, dafür sind die Dateien entwickelt worden.
 

\section{Konfiguration des Bind} \label{d55e946}
        
 
			
 
  \par
  
Nun müssen wir {\bf bind} entsprechend konfigurieren.
Wie schon im ersten Teil wird dabei auf {\bf bind}-Version 8
und höher eingegangen.
 
			
 
Bei Neuinstallationen sollte keinesfalls mehr
{\bf bind} 4 verwendet werden!
 
			
 
  \par
  
Beginnen wir mit einer typischen Konfiguration für ein kleines
Netzwerk. Wir stellen nur einen DNS-Server auf, also soll dieser
alle DNS-Funktionen erfüllen: Er soll unsere Zones halten, von
Clients/Resolvern als DNS-Server verwendet werden können, und
einen Cache aufbauen können, um Datenverkehr zu sparen.
 
 
 
  \par
  
Die Syntax der Konfigurationsdatei ist ähnlich zu C++. Die Datei
besteht aus Anweisungen, die jeweils mit einem Semikolon
abgeschlossen werden. Anweisungen können auch Blöcke sein. Es
gibt Blöcke, die einen Namen haben. Der Block selbst wird in {}
geklammert. \linebreak Eine wichtige Anweisung bzw. ein wichtiger Block
ist {\bf options {};}. Hier stehen die globalen
Optionen. Der andere wichtige Blockname ist
{\bf zone}.
Zwischen Zone und den {} Klammern steht der Name der Zone,
also 'zone ''selflinux.de'' {};'. \linebreak 
Kommentare können wie in C++ in ''/*'' und ''*/''
gefaßt werden, oder nach ''//'' bis zum Zeilenende
reichen. \linebreak Wichtige Anweisungen im Optionsblock sind:
 

 \begin{tabular}{|l|}
                  \hline
                  \begin{tt} 
        /etc/named.conf\end{tt} \\ 
                  \hline
                  \begin{minipage}{130mm} 
                  \begin{scriptsize} 
                  \begin{verbatim} 
        
    directory "/var/named" ;    // Verzeichnis mit den Zonefiles
    forwarders {1.2.3.4;        // Welche DNS Server als
                1.2.3.5;};      // Forwarder verwenden?
    // forward only;            // nicht selbst auflösen,
                                // sondern den Forwarder das
                                // machen lassen
    forward first;              // den Forwarder fragen, wenn
                                // der es nicht weiß, selbst
				// rekursiv nachfragen
  \end{verbatim} 
                  \end{scriptsize} 
                  \end{minipage} \\
                  \hline
                  \end{tabular}

 
  \par
  
Den Rest lassen wir erstmal weg, verwenden also die Defaults.
Diese wurden beim Compilieren festgelegt. Wenn man ein Paket
seiner Distribution verwendet, sollten diese gut zu den anderen
passen.
 

 
Es sei an dieser Stelle ausdrücklich darauf hingewiesen,
daß man keine Forwarders verwenden muß.
 

\section{ROOT-SERVERS konfigurieren} \label{d55e1003}
        
 

 
  \par
  
Wenn der DNS-Server selbst rekursiv fragen können soll (also in
allen Fällen, außer ''forward only;''), muß er natürlich
die ROOT-SERVER kennen. Das sind die Server für die Zone
''.''. Diese Zone konfiguriert man in der Regel wie
folgt:
			
			\begin{tabular}{|l|}
                  \hline
                  \begin{tt} 
        /etc/named.conf\end{tt} \\ 
                  \hline
                  \begin{minipage}{130mm} 
                  \begin{scriptsize} 
                  \begin{verbatim} 
        
zone "." {
        type hint;                 // ist keine "richtig" Zone
	file "root.hint";          // Datei mit den  ROOT-SERVERS 
	};
  \end{verbatim} 
                  \end{scriptsize} 
                  \end{minipage} \\
                  \hline
                  \end{tabular}

 
  \par
  
In ''root.hint'' stehen die ''A'' (Address)
Records (RRs) der ROOT-SERVER, das sieht z.B. so aus:
 

 \begin{tabular}{|l|}
                  \hline
                  \begin{tt} 
        /var/named/root.hint\end{tt} \\ 
                  \hline
                  \begin{minipage}{130mm} 
                  \begin{scriptsize} 
                  \begin{verbatim} 
        
.                        3600000  IN  NS    A.ROOT-SERVERS.NET.
A.ROOT-SERVERS.NET.      3600000      A     198.41.0.4

.                        3600000      NS    B.ROOT-SERVERS.NET.
B.ROOT-SERVERS.NET.      3600000      A     128.9.0.107
  \end{verbatim} 
                  \end{scriptsize} 
                  \end{minipage} \\
                  \hline
                  \end{tabular}

 
  \par
  
Das sollte jetzt verständlich sein: Für ''.'' gibt es in
der Klasse IN einen Nameserver mit sehr langer TTL, der
A.ROOT-SERVERS.NET. heißt, und dessen IP-Adresse.
 

 
  \par
  
Da sich die IP-Adressen auch ändern können, muß diese Datei
gepflegt werden. Dazu eignet sich das Dienstprogramm
{\bf dig} aus der
{\bf BIND}-Distribution. \linebreak Hat man
bereits ein System, das funktionierend Namen auflösen kann
(z.B. wenn es einfach einen DNS-Server vom Provider in der
/etc/resolv.conf konfiguriert hat, die ''dns'' in
/etc/nsswitch.conf hinter ''hosts'' steht), braucht
man nur ein:
 

 
  \begin{tt} \begin{scriptsize} user@linux / \$ dig . ns \end{scriptsize} \end{tt} \linebreak 
 

 
  \par
  
zu machen, und erhält eine aktuelle Liste. Man kann auch
explizit einen DNS-Server angeben, mit:
 

 
  \begin{tt} \begin{scriptsize} user@linux / \$ dig @ns.isp.com . ns \end{scriptsize} \end{tt} \linebreak 
 

 
  \par
  
Betreibt man einen nur cachenden Server (mindestens ein solcher
gehört eigentlich in jedes Netzwerk, um die Performance zu
erhöhen), ist damit die Konfiguration im Prinzip fertig. Hat man
gute Verbindung zu DNS-Servern mit gutem Cache (also DNS-Server,
die häufig gefragt werden), so kann man diese als Forwarder
konfigurieren. Hat man die besondere Situation eines sich über
Wählleitungen einwählenden Netzes oder auch Hosts, macht es Sinn,
die DNS-Server des Providers als Forwarders zu verwenden (wie man
es auch als Client tun würde - außer natürlich, diese sind
überlastet). Forwarders sind auch nützlich, wenn der DNS-Server
öfter herruntergefahren wird. Verwendet man mehrere verschiedene
Provider, so verwendet man am besten keine Forwarder, um Probleme
mit Zugriffsbeschränkungen zu vermeiden.
 

\section{Eigene Zones konfigurieren} \label{d55e1068}
        
 

 
  \par
  
Die Zones, für die der Server authoritative ist (also wenn er
Primary oder Secondary ist, das hieß früher irreführend Master
bzw. Slave), müssen jetzt in der Konfigurationsdatei aufgeführt
werden:
 

 \begin{tabular}{|l|}
                  \hline
                  \begin{tt} 
        /etc/named.conf\end{tt} \\ 
                  \hline
                  \begin{minipage}{130mm} 
                  \begin{scriptsize} 
                  \begin{verbatim} 
        
zone "selflinux.de" {
	type master;	        // wir sind Primary
	file "selflinux.zone";  // in der Datei stehen die Zone-RRs
};

zone "1.168.192.in-addr.arpa" {
	type master;
	file "1.168.192.zone";
	};
  \end{verbatim} 
                  \end{scriptsize} 
                  \end{minipage} \\
                  \hline
                  \end{tabular}

 
  \par
  
Bei Secondaries konfiguriert man ''type slave;'' und
ebenfalls ein File (z.B. file ''slave/myzone.zone'';).
Zusätzlich muß man dann aber noch den (die) Masterserver
angeben: ''masters {1.2.3.4;};''.
 

\section{Eine Zone für ''localhost''} \label{d55e1092}
        

 
 
  \par
  
Der Name ''localhost'' sollte immer mit der IP 127.0.0.1
verknüpft sein. Um dies per DNS zu erreichen, gibt es zwei
grundlegende Herangehensweisen, die in der Praxis auftauchen.
Einmal denkt man sich ''localhost'' zu einer Zone
zugehörig, zum Beispiel als ''localhost.selflinux.de.''.
In diesem Fall wird der Name einfach als Address-Record in das
entsprechende Zonefile eingetragen.
 

 
  \par
  
Eine andere Möglichkeit ist, den Namen als ''localhost.''
zu interpretieren. Aus Sicht des DNS handelt es sich dabei um
eine Toplevelzone (mit einer IP-Adresse, aber keinen weiteren
darunterliegenden Records). Das verletzt allerdings etwas das
Konzept von den Toplevel-Domains, funktioniert in der Praxis
jedoch sehr gut. Um dies zu erreichen, erzeugt man ein
entsprechendes Zonefile:
 

 \begin{tabular}{|l|}
                  \hline
                  \begin{tt} 
        /var/named/localhost.zone\end{tt} \\ 
                  \hline
                  \begin{minipage}{130mm} 
                  \begin{scriptsize} 
                  \begin{verbatim} 
        
$TTL 1d

localhost. IN SOA pri-ns.selflinux.de. admin.selflinux.de. (
	2000012501 ; Serial (Seriennummer)
	3H	   ; Refresh (Aktualisierung)
	1H	   ; Retry (neuer Versuch)
	1M	   ; Expire (ungültig nach)
	1D )	   ; min. TTL (mindeste Gültigkeit)

		IN  NS    ns1.selflinux.de.
		IN  NS    ns2.selflinux.de.

		IN  A     127.0.0.1
  \end{verbatim} 
                  \end{scriptsize} 
                  \end{minipage} \\
                  \hline
                  \end{tabular}

 
  \par
  
Eine zugehörige Reverse-Zone:
 

 \begin{tabular}{|l|}
                  \hline
                  \begin{tt} 
        /var/named/0.0.127.zone\end{tt} \\ 
                  \hline
                  \begin{minipage}{130mm} 
                  \begin{scriptsize} 
                  \begin{verbatim} 
        
$TTL 1d

0.0.127.in-addr.arpa. IN SOA pri-ns.selflinux.de. admin.selflinux.de. (
	2000012501 ; Serial (Seriennummer)
	3H	   ; Refresh (Aktualisierung)
	1H	   ; Retry (neuer Versuch)
	1M	   ; Expire (ungültig nach)
	1D )	   ; min. TTL (Mindestgültigkeit)

		IN  NS    ns1.selflinux.de.
		IN  NS    ns2.selflinux.de.

1               IN  PTR   localhost.
  \end{verbatim} 
                  \end{scriptsize} 
                  \end{minipage} \\
                  \hline
                  \end{tabular}

 
  \par
  
In der named.conf werden beide Zonen eingetragen:
 

 \begin{tabular}{|l|}
                  \hline
                  \begin{tt} 
        /etc/named.conf\end{tt} \\ 
                  \hline
                  \begin{minipage}{130mm} 
                  \begin{scriptsize} 
                  \begin{verbatim} 
        
zone "localhost" {
        type master;
        file "localhost.zone";
};

zone "0.0.127.in-addr.arpa" {
        type master;
        file "0.0.127.zone";
};
  \end{verbatim} 
                  \end{scriptsize} 
                  \end{minipage} \\
                  \hline
                  \end{tabular}

 
  \par
  
Wird die erste Methode verwendet, also localhost als Host einer
Domain interpretiert, so wird nur die Reverse-Zone benötigt (da
es ja keine Toplevel-Zone ''localhost.'' gibt). In dieser
muß der PTR-Record dann konsistenterweise auf die Domain zeigen,
beispielsweise ''localhost.selflinux.de.''. Man kann auch
eine Mischung aus beiden Methoden konfigurieren. Dazu wird eine
Zone ''localhost.'' erzeugt, und ein Hosteintrag in der
Domain. Dieser Eintrag im Zonefile der Domain ist
sinnvollerweise ein CNAME auf ''localhost.'':
 

 \begin{tabular}{|l|}
                  \hline
                  \begin{tt} 
        /var/named/localhost.zone\end{tt} \\ 
                  \hline
                  \begin{minipage}{130mm} 
                  \begin{scriptsize} 
                  \begin{verbatim} 
        
localhost	IN CNAME localhost.
  \end{verbatim} 
                  \end{scriptsize} 
                  \end{minipage} \\
                  \hline
                  \end{tabular}

 
  \par
  
Die Reverse-Zone sieht damit wie im Beispiel aus. 
 \linebreak 
Vergleicht man beide Methoden, stellt man fest, daß deren
Funktion von der Konfiguration der Clients abhängt. Normalerweise
muß eine Maschine in der Lage sein, ''localhost''
aufzulösen. Verwendet man die erste Methode, muß also eine
Suchliste definiert sein, bei der unter mindestens einer Domain
der Host ''localhost'' existiert. Hier liegt also ein
Vorteil der zweiten Methode. \linebreak Der Hauptnachteil der zweiten
Methode ist, daß man eine ''localhost.''-Topleveldomain
definiert, was das Toplevel-Konzept etwas verletzt, und dadurch
von einigen Administratoren als unsauber bezeichnet wird. In
der Praxis hat sich jedoch die zweite Methode bewährt, die
zudem etwas performanter ist, und findet breiten Einsatz.
 

\section{Weitere wichtige Konfigurationsoptionen} \label{d55e1159}
        
 

 
  \par
  
Hier ganz kurz noch ein paar wichtige Optionen:
 

 \begin{tabular}{|l|}
                  \hline
                  \begin{tt} 
        named.conf\end{tt} \\ 
                  \hline
                  \begin{minipage}{130mm} 
                  \begin{scriptsize} 
                  \begin{verbatim} 
        
listen-on port 53 { 1.2.3.4; }; //Port 53 des angebenen
				//Interfaces verwenden. Sinnvoll,
				//wenn man z.B. Dialup-Interfaces 
				//hat, die nicht von Clients
				//verwendet werden sollen
query-source address * port 53; //Port 53 beim _Senden_ verwenden
				//sinnvoll hinter Firewalls.
				//Zusätzlich kann auch eine
				//Interfaceaddresse angeben
				//werden, sinnvoll bei Multihomed-Hosts
notify yes;			//bei Änderungen an den
				//Datenbanken dies den
				//Secondaries mitteilen
recursion no;			//Verwendet man am besten
				//bei
				//Servern, die nur Primary sind
				//Clienten können
				//diesen Namen nicht verwenden!
check-names master warn;	//sind Zone-RRs falsch, nur warnen,
				//nicht abbrechen
check-names master fail;	//Abbruch, wenn Zone fehlerhaft ist
allow-query { any; };		//Jeder darf fragen
allow-update { none; };		//keiner darf updaten (ändern)
allow-update { 1.2.3.4; };	//1.2.3.4 darf updaten
allow-transfer { 1.2.3/24; };   //nur Netz 1.2.3.0/24 darf
				//Zonetransfers machen
  \end{verbatim} 
                  \end{scriptsize} 
                  \end{minipage} \\
                  \hline
                  \end{tabular}

 
  \par
  
Die ersten vier Optionen dürfen nur im
''options {};''-Block auftreten, die anderen hier
genannten Optionen können auch in ''zone {};''-Blöcken
auftauchen, so daß sich beispielsweise
Zugriffsrechte pro Zone einstellen lassen. ''notify''
sollte bei Slaves auf ''no'' stehen, da diese sonst
dem Primary Zonenänderungen überflüssigerweise mitteilen.
 

\section{Starten} \label{d55e1183}
        
 

 
  \par
  
{\bf bind} wird normalerweise über ein kleines
rc-script gestartet. Man kann {\bf bind} starten,
indem man ''/pfad/named'' aufruft, z.B.
{\bf /usr/sbin/named}. Beenden geht unter Linux
einfach mit {\bf killall named}. Aber dabei ist zu
beachten, daß andere Systeme wie z.B. Solaris ein anderes
{\bf killall} haben - dieses killt wirklich alles,
hier müßte man mit {\bf ps -ef|grep named} die PID
des Prozesses ermitteln, und diesen mit
{\bf kill \verb+<+pid\verb+>+} beenden.
 

 
Eleganter geht das mit dem Dienstprogramm {\bf ndc}:
zum Starten verwendet man {\bf ndc start}, zum
Beenden {\bf ndc stop}. 
 

 
  \par
  
Man muß nun sorgfältig die Logfiles des
{\bf syslogd} prüfen, um Fehler
zu erkennen. Die Fehlermeldungen sind in der Regel sehr
aussagekräftig, und führen schnell zur Ursache. Schwierig zu
erkennen ist aber z.B. eine vergessene geschweifte Klammer in der
{\bf named.conf}, besonders für ungeübte und
nicht-C++-Kenner. Wird eine Zone angemeckert, so muß das
Zonefile untersucht werden. 
 

 
  \par
  
Sehr ungünstige Werte innerhalb des SOA-Records führen z.B. zu
einer Warnung. In diesem Fall sagt {\bf bind} aber
sogar, was ihn stört, so daß man den Fehler schnell
korrigieren kann. Problematischer sind Fehler in der Art von
''Cannot find NS on...''. Das deutet darauf hin, daß der
NS für eine Zone nicht erreichbar ist, oder nicht existiert.
Es muß hier der Name eines DNS-Servers stehen, der authoritativ
für die Zone ist! Dieser Fehler wird häufig nicht sofort erkannt.
 

 
  \par
  
Wird ein Server von einem anderen als authoritativ für diese Zone
genannt, und ist dieser genannte Server aber selbst nicht der
Meinung, authoritativ für diese Zone zu sein, nennt man ihn
{\bf lame server}. Wären alle ''lame'',
verfällt die Zone mit Ablauf der Cache- bzw. Expirezeiten,
man merkt es also nicht unbedingt sofort, aber es ist ein
schweres Problem.
 

 
  \par
  
Hat man die Zonefiles geändert, und die Seriennummer erhöht,
müssen die Datenbanken neu geladen werden, dazu macht man ein:
 

 
  \begin{tt} \begin{scriptsize} user@linux / \$ ndc reload \end{scriptsize} \end{tt} \linebreak 
 

 
  \par
  
und prüft natürlich wieder die Logfiles.
 

\section{Zoneänderungen und Secondaries} \label{d55e1258}
        
 

 
  \par
  
Ist ''notify yes;'' konfiguriert, so sendet
{\bf BIND} bei
jedem Reload eine Nachricht an die Secondaries, daß die
Zone modifiziert wurde. Die Secondaries holen daraufhin den
SOA-Record, und schauen, ob sich die Seriennummer erhöht hat.
Wenn ja, so wird die Zone vom Primary transferiert,
ansonsten passiert nichts. Deshalb darf man nie vergessen,
die Seriennummer zu erhöhen!
 

 
Der Vorgang, der von den Secondaries beim Empfang einer Notify
Message stattfindet, ist der selbe wie der, der beim Erreichen
der Refresh-Time einer Zone stattfindet. 
 

\section{Testen der Konfigurationen} \label{d55e1276}
        
 

 
  \par
  
Es gibt ein Tool, mit dem man fast beliebige DNS-Anfragen machen
kann, um z.B. Konfigurationen zu testen. Dieses ist Teil der
{\bf bind}-Distribution und heißt
{\bf nslookup}. Dieses
versteht viele Optionen als Parameter, kann aber auch
interaktiv verwendet werden. \linebreak Um die Wirkung der Searchlist zu
unterdrücken, sollten wiederum vollqualifizierte Hostnamen mit
einem anschließenden Punkt verwendet werden. Mit diesem Tool
fragt man nach Daten der Zone, z.B. ''www.selflinux.de.''
Folgende Optionen stehen im interaktiven Modus zur Verfügung
(hier teilweise abgekürzt):
 

 \begin{list}{*}{}
  
	\item 
''server \verb+<+server\verb+>+'', z.B.
{\bf server ns.selflinux.de} \linebreak 
Die Anfragen werden an \verb+<+server\verb+>+ gesendet.
  
  
	\item 
''set querytype=\verb+<+RR Typ\verb+>+'', z.B.
{\bf set q=any} \linebreak 
Anfragen nach RR-Typ machen
  
  
	\item 
''set debug'' / ''set nodebug'' \linebreak 
Es werden viele zusätzliche Informationen angezeigt, sehr
hilfreich bei der Fehlersuche
  
  
	\item 
''set recurse'' / ''set norecurse'' \linebreak 
Rekursive oder nicht rekursive Anfragen machen
  
  
	\item 
''ls \verb+<+zone\verb+>+'', z.B.
{\bf ls selflinux.de} \linebreak 
Zonentransfer machen, und diese auflisten \linebreak 
{\bf ls} kennt mehrere Optionen, z.B.
''-t \verb+<+RR Type\verb+>+''
  
 \end{list}

 
  \par
  
Beim Testen muß natürlich auch nach IP-Adressen gefragt werden,
um zu testen, ob diese richtig zurück in Hostnamen übersetzt
werden.
 

 
  \par
  
Ein sehr gutes automatisches Tool für derartige Tests ist
{\bf dnswalk}, insbesondere bei großen Zones ist
es sehr nützlich. Dieses erfordert {\bf Perl5}, und
das Modul {\bf Net::DNS}.
Dieses kann, falls erforderlich, mit der CPAN-Shell
einfach und meist unproblematisch installiert werden
({\bf perl -MCPAN -e shell}, nach der
Konfiguration genügt in der Regel ein
 {\bf install Net::DNS}). \linebreak 
{\bf dnswalk} findet man unter:
 
http://www.cis.ohio-state.edu/\~{}barr/dnswalk/
Beim Aufruf übergibt man mindestens die zu testende Zone (mit
abschließendem Punkt). DNSwalk kann auch rekursiv delegierte
Zones durchlaufen.
 

 
  \par
  
Das Tool {\bf nslookup} hat aber auch einige
Nachteile, die das Debugging erschweren können.
Beispielsweise versucht {\bf nslookup} stets, 
zumindest in neueren Versionen, den Namen des DNS-Servers
rückwärts aufzulösen. Dies ist oft sinnvoll, um
DNS-Spoof-Angriffe zu erschweren.
Bei Aufsetzen eines DNS-Systems funktioniert damit
das Tool jedoch erst, wenn die Reverse-Zonen konfiguriert sind,
und die DNS-IPs richtig auflösen. Um ''nur'' einfache
Tests der Namen zu machen, kann man jedoch andere Tools
verwenden, zum Beispiel die, die den normalen Resolver verwenden
(beispielsweise zeigt auch {\bf ping} die IP-Adresse
an).
 

 
  \par
  
{\bf bind} kann auch sämtliche Anfragen via
{\bf syslog}(3) loggen. Dazu
verwendet man das Dienstprogramm {\bf ndc} (das
Kontroll-Interface), um es einzuschalten:
 

 
  \begin{tt} \begin{scriptsize} user@linux / \$ 
ndc querylog
   \end{scriptsize} \end{tt} \linebreak 
 

 
  \par
  
Nun kann man verfolgen, welche Namen aufgelöst werden sollen,
welche Server dazu verwendet werden, usw. Das ist auch bei
Dial-On-Demand-Verbindungen hilfreich. Ein Blick in die Manpage
von {\bf ndc} verrät außerdem weitere Kommandos.
Eines davon ist {\bf dumpdb}:
 

 
  \begin{tt} \begin{scriptsize} user@linux / \$ 
ndc dumpdb
   \end{scriptsize} \end{tt} \linebreak 
 

 
  \par
  
Das sorgt dafür, daß die gesamte Datenbank in eine
Datei geschrieben wird. Deren Name kann mit der
''dump-file''-Direktive im ''options {};''-
Block gesetzt werden, ansonsten wird
{\bf /var/tmp/named\_dump.db} verwendet. Diese Datei
enthält alle autoritativen Zonendaten und den gesamten Cache,
d.h. sie ist ziemlich groß (ein normaler Server produziert dabei
einige tausend Zeilen!). Dort kann man z.B. die Zonen überprüfen,
oder nach evtl. falsch gecachten Einträge suchen (wenn z.B. zu
klären ist, welcher Server eine bestimmte Anfrage falsch
beantwortet),
in der Praxis wird das aber vermutlich die Ausnahme sein.
 

\section{Spielzonen} \label{d55e1412}
        
 

 
  \par
  
Nach RFC 2606 darf man ''.test'',
''.example'', ''.localhost''
und ''.invalid'' als TLD verwenden.
Diese TLDs sind für entsprechenden Gebrauch reserviert, wobei
''.example'' für Beispiele und Dokumentationen
und ''.test'' für Software-Tests empfolen ist.
''.localhost'' ist für 127.0.0.1 reserviert und sollte
nicht anders verwendet werden.
 

\section{Mehr Informationen als Namen und Adressen} \label{d55e1427}
        
 

 
  \par
  
Es gibt RR-Typen, die weniger technischen Aufgaben dienen,
sondern allgemeine Informationen liefern. Zunächst gibt es den
Typ {\bf HINFO}, das steht für
''Host Information''.
Damit besteht die Möglichkeit, einen Maschinennamen
(Hardware-Namen) und einen Betriebsystemnamen aufzunehmen.
Historisch gesehen sollte es dazu dienen, um Dienste von den
richtigen Maschinen zu verlangen (z.B. HTTP vom WWW-Server),
deshalb sollten diese Werte Abkürzungen aus RFC 1700
(oder
Nachfolger) sein, oder auch eigene Abkürzungen. In der Praxis
findet dieser RR-Typ nicht die breite Verwendung. 
 

 
Die Verwendung dieses Records veröffentlicht Informationen, die
die Sicherheit beeinflussen können, da ein potentieller Attacker
mehr Informationen besitzt, die er gegen das Netz einsetzen kann.
 

 
  \par
  
Ein Beispiel wäre:
 

 \begin{tabular}{|l|}
                  \hline
                  \begin{tt} 
        selflinux.zone\end{tt} \\ 
                  \hline
                  \begin{minipage}{130mm} 
                  \begin{scriptsize} 
                  \begin{verbatim} 
        
sun12		IN HINFO "Sun Enterprise 450" "SunOS 5.6"
  \end{verbatim} 
                  \end{scriptsize} 
                  \end{minipage} \\
                  \hline
                  \end{tabular}

 
  \par
  
Für die Dienstzuordnung dient auch der
{\bf SRV}-Record, der in RFC 2052
beschrieben wird. Dabei wird eine zu einem Namen
{\bf Assigned Number}
(d.h. laut RFC 1700) verwendet,
die als Prefix vor den Namen gesetzt wird. Sucht ein Client z.B.
einen FTP-TCP/IP-Dienst in der Domain selflinux.dx, so würde er
nach ftp.tcp.selflinux.de fragen. Ein solcher Datensatz enthält
dann die folgenden Felder: Priorität (niedrige werden
vorgezogen),
Wichtung (größere Server bekommen höhere Nummern), Portnummer
(auf der Zielmaschine), Zielmaschine. Ein Beispiel wäre:
 

 \begin{tabular}{|l|}
                  \hline
                  \begin{tt} 
        selflinux.zone\end{tt} \\ 
                  \hline
                  \begin{minipage}{130mm} 
                  \begin{scriptsize} 
                  \begin{verbatim} 
        
nntp.tcp	IN SRV   10 0 119   sun12
  \end{verbatim} 
                  \end{scriptsize} 
                  \end{minipage} \\
                  \hline
                  \end{tabular}

 
  \par
  
Dieser RR findet anscheinend in der Praxis kaum Verwendung.
 

 
  \par
  
Eine weitere Art der Information ist der geographische Standort.
Dieser kann mit einem {\bf LOC}-RR dargestellt werden.
Dieser enthält
dabei geographische Breite, Länge und die Höhe über dem
Meeresspiegel. Das Format des
Datensatzes ist Grad, Minuten, Sekunden, N/S (Nord/Süd), Grad,
Minuten, Sekunden (Komma erlaubt, z.B. ''4.12''), W/E
(West/East), Höhe (in Metern). Sekunden und Minuten dürfen
weggelassen werden.
				 \linebreak 
Bei der Ermittlung der Werte hilft
				
http://www.ckdhr.com/dns-loc/
				
und sehr gut ist auch
				
http://www.mapblast.com/
				
. Ein Beispiel (Der Ort sei Lat.: 52 56' (etwa 52,9) N,
Long.: 12 49' (12,8) E:
 

 \begin{tabular}{|l|}
                  \hline
                  \begin{tt} 
        selflinux.zone\end{tt} \\ 
                  \hline
                  \begin{minipage}{130mm} 
                  \begin{scriptsize} 
                  \begin{verbatim} 
        
selflinux.de	LOC    52 55 N    12 50 E    100m
  \end{verbatim} 
                  \end{scriptsize} 
                  \end{minipage} \\
                  \hline
                  \end{tabular}

 
  \par
  
Dahinter kann dann noch die Größe, die vertikale, die horizontale
Genauigkeit kommen (alle drei in Metern). Damit kann man z.B. die
Genauigkeit senken, in dem man sie nur grob auf ein paar tausend
Meter angibt, um Sicherheitsrisiken zu vermeiden. Näheres siehe
RFC 1876.
 

 
  \par
  
Diese Informationen können dann z.B. von graphischen
{\bf traceroute}-ähnlichen
Programmen verwendet werden, die dann auf einer
(Welt-)Karte die Routenwege einzeichnen. 
 

\section{Quickstart} \label{d55e1519}
        
 

 
  \par
  
Es gibt noch einen ganz anderen, ''unorthodoxen'' Weg zu
einem DNS-Server. Man schreibt einfach alle Daten in die
{\bf /etc/hosts}, und verwendet das Tool
{\bf h2n}.
Dieses erzeugt aus der hosts Zonefiles und sogar ein
Konfigurationsfile für {\bf bind}. Es ist durchaus
keine schlechte
Idee, dieses Tool zum ersten Erstellen der Files zu verwenden,
und diese dann weiterzupflegen. Der Autor hat es jedoch nie
benutzt, so daß an dieser Stelle nicht näher darauf eingegangen
werden kann.
 

\section{Ein Produktivsystem} \label{d55e1540}
        
 

 
  \par
  
Bis jetzt war alles Spaß. Für einen Produktionsserver sind noch
einige Dinge zu beachten. Im folgenden ein paar Tips, die das
Leben hoffentlich vereinfachen.
 

 
  \par
  
Im Allgemeinen muß man natürlich vor allem sorgfältig arbeiten.
Die meisten Leute sind es sowieso gewohnt, daß DNS-Einträge bis zu
drei Tage dauern. Man sollte sich also Zeit lassen, nicht
''eben mal auf die Schnelle ein paar RRs einfügen''.
Man sollte immer Backups von den Datenbanken haben. Dabei bietet
sich ein Revision Control System an, z.B. {\bf rcs}
oder {\bf cvs}. Verwaltet man mehrere Zonen,
so kann man darüber nachdenken, ein Script zu erstellen, das
{\bf dnswalk} für alle Zonen automatisch machen
kann.
Evtl. kann man den Primary direkt nach ausgesuchteten, sehr
wichtigen Adressen per {\bf cron} fragen, um im
Fehlerfalle schnell eine EMail zu bekommen.
 

 
Es ist auch zu beachten, daß sich unter Umständen Fehler erst
nach einigen Tagen zeigen, da die Cachezeiten u.U. relativ groß
sind.
 

 
  \par
  
Es ist sinnvoll, die Option ''check-names fail;'' beim
Primary zu setzen, um Fehler schnellstmöglich festzustellen, bevor
ebtl. falsche Daten von Secondaries geholt werden. Im Extremfalle
verwenden diese diese Option, und werfen die fehlerhafte Zone
nach dem Transfer sofort weg!
 

 
  \par
  
Um sicher zugehen, nach jeder Änderung die Serial richtig zu
setzen, kann ein kleines Script verwendet werden. Dies erscheint
sinnvoll, da die Serial eine wichtige Rolle spielt. Da man in der
Regel das Datum im Format JJJJMMTT plus eine zweistellige
laufende Nummer verwendet (falls man mehrmals am Tag etwas
ändert), wird diese zwangsläufig immer größer. Ein großes Problem
aber ist z.B., wenn man sich vertippt, und eine Ziffer zuviel
verwendet. Dann hat man eine Serial, die so groß ist, daß sie nie
''richtig'' erreicht wird. Eine Serial zurückzusetzen, ist
so einfach jedoch nicht möglich.
 

 
  \par
  
Ein derartiges Script könnte z.B. nach der Zeichenkette
''; Serial'' suchen, die nach einem entsprechenden
Datumscode steht (dieser Kommentar wurde auch hier in den
Beispielen verwendet). Verwendet man dazu {\bf perl},
könnte man zu folgender Lösung kommen:
 

 \begin{tabular}{|l|}
                  \hline
                  \begin{tt} 
        new\_serial.pl\end{tt} \\ 
                  \hline
                  \begin{minipage}{130mm} 
                  \begin{scriptsize} 
                  \begin{verbatim} 
        
#!/usr/bin/perl -pi.ser
#Y2K stable - Perl RULES :) <steffen@dett.de>

#Starten mit einem Bind Zone File als Paramter. Es wird ein
#Backup erzeugt (Endung .ser), und alle Zeilen der Form
#"JJJJMMTTNN ; Serial", z.B. "2000012501 ; Serial" angepaßt
#aufs aktuelle Datum bzw. die laufende Nummer erhöht.

#start with bind zone files, it will replace serial of the form
#"YYYYMMDD00 ; Serial"  i.e. "2000012501 ; Serial"
#to new date or incrementing last two digits

my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) =
localtime(time);
my $date = sprintf("%4d%02d%02d", 1900+$year, $mon+1, $mday);

if (m/((20|19)\d{6})(\d{2})(\s+\;\s+[Ss]erial\s+)$/) {
    my $old_date = $1;
    my $old_serial = $3;
    my $rest = $4;
    my $serial = $old_serial;
    if ($old_date eq $date) {
        $serial++;
    } else {
        $serial = 0;
    }
    $serial = sprintf("%02d", $serial);
    s/${old_date}${old_serial}${rest}/${date}${serial}${rest}/;
    print STDERR "Serial found! Old: [$old_date $old_serial]  --> ",
        "Changed to [$date $serial]\n";
}
  \end{verbatim} 
                  \end{scriptsize} 
                  \end{minipage} \\
                  \hline
                  \end{tabular}

 
  \par
  
Es mag Sinn machen, das so aktualisierte File von diesem Script
auch gleich ins RCS/CVS einzuchecken bzw. zu
 ''committen'' ({\bf ci -l \verb+<+file\verb+>+} /
{\bf cvs commit \verb+<+file\verb+>+} - letzteres geht in der
Regel allerdings nicht als ''root'').
 

\section{Sinnvolle SOA-Values} \label{d55e1600}
        
 

 
  \par
  
Viele machen sich kaum Gedanken um die Wahl günstiger SOA-Werte.
Um Ressourcen zu sparen, sollten diese nicht zu klein sein. Hohe
TTLs haben dafür den Nachteil, daß im Falle einer Umstellung viel
Zeit vergeht, bis die neuen Namen verteilt sind. Da man oft schon
im vorraus weiß, wann eine solche Umstellung beginnt, kann man
z.B. drei Tage vorher die TTL für die betroffenen RRs senken,
z.B. von acht auf zwei Stunden. Einen Tag nach der Umstellung
erhöht man sie einfach wieder (Erhöhung der Seriennummer nicht
vergessen). 
 

 
  \par
  
Bei sehr statischen Zonen kann man das Refresh auch relativ hoch
ansetzen, und auch, wenn das Notify von allen Secondaries
unterstützt und in der Zone eingesetzt wird. Hier sind dann
durchaus Werte von 24 Stunden sinnvoll. Kann man Notify nicht zu
allen Secondaries einsetzen, muß man allerdings für einen zügigen
Betrieb diesen Wert senken, z.B. auf drei Stunden.
 

 
  \par
  
Das Expire sollte immer hoch angesetzt werden. Kann ein
Secondary seinen Primary nicht erreichen, wird nach diesem
Zeitraum die Zone ungültig, d.h. sie wird nicht mehr beantwortet.
Bei einem geringen Expire, z.B. nur zwei Tage, könnte ein
Ausfall eines einzigen Servers, nämlich des Secondaries, über das
Wochenende das DNS-System lahmlegen, ein sehr unangenehmer
Gedanke. Deshalb sollte man als absolutes Minimum eine Woche
setzen!
 

\section{Secondaries betreiben} \label{d55e1615}
        
 

 
  \par
  
Stellt man DNS für eine Zone, so sind die Vorschriften des
Betreibers der übergeordneten Zone zu beachten. Betreibt man z.B.
eine ''de.''-Domain, wie ''selflinux.de.'', so
gelten die Vorschriften des DENIC. Eine sehr
sinnvolle ist z.B.,
daß eine Zone über mindestens zwei, über verschiedene Wege zu
erreichende authorative Server verfügen muß.
 
			
 
  \par
  
Normalerweise hat man einerseits den Primary und andererseits
braucht man mindestens einen Secondary in einem anderen Netzwerk.
Für einen guten ISP sollte es kein Problem darstellen, einen
Secondary zu betreiben. Es scheint auch eine gute Idee zu sein,
zwei Secondaries vom ISP machen zu lassen, was diesem technisch
keine Probleme bereiten sollte, da er vermutlich auch selbst
Zonen bedient. Damit kann man diese beiden als NS-Einträge
verwenden, so daß er Primary gar nicht gefragt wird. Das
ermöglicht, die Firewall entsprechend scharf einzustellen.
 

 
  \par
  
DNS ist sicherheitsempfindlich. Gefälschte Datenbanken können es
einem Eindringling z.B. ermöglichen, auf NFS- Shares zuzugreifen,
wenn er die entsprechende in-addr.arpa.-Zone modifiziert. Auch
mit dem Verändern der lokalen DNS-Server kann er
Sicherheitslücken erzeugen, so z.B. Anfragen zu einer anderen
Maschine umleiten, und so z.B. Passwörter stehlen, von einer
Vielzahl von Denial-Of-Service-Attacken ganz zu schweigen.
 

 
  \par
  
Betreibt man selbst Secondaries, so sollten auf diesen Maschinen
möglichst wenig andere Dienste laufen (das gilt
selbstverständlich ganz besonders für Primaries!). 
 

 
  \par
  
Secondaries sollten ''check-names warn;'' verwenden, um
einen Ausfall durch einen Tippfehler oder ähnliches möglichst zu
verhindern.
 

\section{Zugriffsbeschränkungen konfigurieren} \label{d55e1642}
        

 

 
  \par
  
Nach Möglichkeit sollte der Zugriff so weit wie möglich
beschränkt werden. Verwendet man kein dynamisches Update, so
sollte man die option ''allow-update { none; };''
verwenden, ansonsten die IP-Adresse von jeder berechtigten
Maschine aufzählen.
Steht diese Option im ''options {};''-Block, so
gilt sie für alle Zones. Hat eine Zone einen eigenen Eintrag, so
überschreibt dieser den globalen im ''Options {};''-Block
stehenden.
 

 
  \par
  
Ein Primary, der nirgendwo als ''NS''-Record auftritt,
wird normalerweise nie Anfragen erhalten, außer Zonetransfers von
seinen Secondaries. Deshalb kann man in diesem Falle die Option
''allow-query { none; };'' setzen, diese darf ebenfalls
im ''options {};''-Block stehen, und damit global gelten.
 

 
  \par
  
Sehr häufig erlauben die Server Zonetransfers nur ihren
Secondaries. Damit erlaubt auch ein Secondary (der von keinem als
Primary verwendet wird, theoretisch lassen sich die Server aber
{\bf kaskadieren}) überhaupt keine Zonetransfers,
höchstens zu ein, zwei Maschinen zu Testzwecken (wo z.B.
{\bf dnswalk} läuft, das Zonetransfres benötigt).
Das konfiguriert man mit der Option
''allow-transfer { none; };'', bzw. bei Primaries durch
Aufzählen der IP-Adressen der Secondaries (und evtl. Testhosts),
z.B. ''allow-transfer { 1.2.3.4; 1.2.3.5; };''. Anstatt
einzelner Adressen können selbstverständlich auch Netzwerke
angegeben werden.
 

 
  \par
  
{\bf bind} (ab Version 8) unterstützt auch
{\bf ACL}s (Access Control Lists),
was die Übersicht erhöht. Hier kann man symbolische Namen
für IP Adressen und Netzwerke vergeben, ein Beispiel:
 
			
 \begin{tabular}{|l|}
                  \hline
                  \begin{tt} 
        /etc/named.conf\end{tt} \\ 
                  \hline
                  \begin{minipage}{130mm} 
                  \begin{scriptsize} 
                  \begin{verbatim} 
        
acl fremde_clients { !1.2.3/24; any; };    // alle, außer 1.2.3.0/24
acl locals  { 1.2.4.0/24; };               // eigenes Netz
acl transfer { 1.2.10.53; 1.2.11.53; };    // Secondaries
acl clients { locals; transfer; };	   // Resolver
acl dhcp { 1.2.4.254; };                   // DHCP-Server 

allow-transfer { transfer; };
allow-query { clients; };
allow-update { dhcp; };
  \end{verbatim} 
                  \end{scriptsize} 
                  \end{minipage} \\
                  \hline
                  \end{tabular}
			
 
  \par
  
Das ist dann besser lesbar.
 
 
 
  \par
  
Dabei müssen die ACLs natürlich vor deren Verwendung definiert
werden. Sollen diese bereits im ''options {};''-Block
verwendet werden, müssen diese davor (also außerhalb dieses
Blockes) definiert werden. Finden die ACLs in den
''zone {};''-Blöcken Anwendung, so können nach dem
''options {};''-Block (und vorzugsweise vor dem ersten
''-zone {};''-Block) definiert werden.
Die Struktur sähe z.B. so aus:
 
			
 \begin{tabular}{|l|}
                  \hline
                  \begin{tt} 
        /etc/named.conf\end{tt} \\ 
                  \hline
                  \begin{minipage}{130mm} 
                  \begin{scriptsize} 
                  \begin{verbatim} 
        
acl transfer { 1.2.10.53; 1.2.11.53; };    // Secondaries

options {
	....
	allow-transfer { transfer; };
};

acl locals  { 192.168.0.0/16; };           // eigenes Netz

zone "my.play.net.de" {
	....
	allow-query { locals; };
	};
  \end{verbatim} 
                  \end{scriptsize} 
                  \end{minipage} \\
                  \hline
                  \end{tabular}

 
  \par
  
Damit könnte man dann eventuell eine interne, private Zone für
private IP-Adressen auf dem normalen DNS-Server konfigurieren,
aber den Zugriff aus dem Internet verbieten. Ansonsten kann es zu
Störungen fremder Clienten führen, da Namen u.U. falsch aufgelöst
werden könnten.
 

\section{Betrieb hinter einer Firewall} \label{d55e1702}
        
 
		
 
  \par
  
Hierbei gibt es zwei zu trennenden Dinge: DNS-Server, die
Clientanfragen bearbeiten, und Autoritative-Server. Man kann
diese auf getrennten Maschinen unterbringen, denn DNS-Server, die
Clientanfragen beantworten, sind von Denial-Of-Service Attacken
nicht so stark betroffen, wie Authoritative-Server. Mit der Option
query-source address * port 53;
kann man {\bf bind} anweisen, alle Anfragen von
Port 53 aus zu machen.
Damit kann man die Firewall für die hohen Ports (\verb+>+1023) auch
noch sperren. Zusätzlich kann man auch die Zieladdressen
begrenzen, wenn man den Server ''forward-only;''
konfiguriert. Dann
gibt man ihm z.B. drei Forwarder, und erlaubt nur Verbindungen zu
diesen. Diese Verbindungsregeln müssen für UDP und TCP gelten, da
{\bf bind} bei Anfragen, die nicht mehr in ein einzelnes UDP-Paket
passen, TCP verwendet. Selbstverständlich sollte die Firewall
Regelverstöße loggen.
 

 
  \par
  
Betreibt man einen Primary, und läßt die Secondaries vom ISP
machen, so muß mit diesem abgesprochen werden, von welchen
Maschinen aus welche Art von Zugriff zu erlauben ist. Einige
verwenden z.B. {\bf ping} für Tests, außerdem wird
evtl. von einer anderen Maschine zu Testzwecken ein Zonetransfer
probiert, bevor der Eintrag in den ''richtigen'' Server
gemacht wird. Erhält man ungenügende Auskunft, so erstellt man
eine Firewallregel, die alle Anfragen durchläßt, aber dabei
loggen (Es reicht aus, Pakete mir gesetztem SYN-Bit zu loggen,
allerdings macht das in der Praxis selten Sinn, da zu verbotenen
Ports sowieso nur SYN-Pakete kommen werden, und der Aufwand für
die zusätzlichen Regeln [die für TCP] kaum Nutzen bringt, sofern
man keine ''ACCEPTS'' loggt).
Dann kann man das Logfile analysieren, und erkennt, welche
Maschinen Daten austauschen.
 

 
  \par
  
Leider kann man DNS nicht durch den {\bf rinetd}
redirecten, da dieser kein UDP unterstützt.
 

 
  \par
  
Da mindestens ein Slave außerhalb des Netzes steht, muß also
mindestens dieser durch die Firewall dürfen. Um das testen zu
können, sollte immer ein zusätzlicher Host erlaubt werden, also
sowohl durch die Firewall dürfen, als auch einen Zonentransfer
machen dürfen. Dann kann man {\bf nslookup} auf
diesem Host verwenden, um mit
{\bf ls \verb+<+Zonenname\verb+>+} einen
Test-Zonetransfer durchzuführen.
 
			
 
  \par
  
Beim ersten Zugriff der Secondaries sollte man immer das Firewall-
Log im Auge behalten, da die Provider gern einen Host, der
Zugriff benötigt, vergessen. Das ist z.B. die Testmaschine, an
dem die Zonen geprüft werden. So sieht man das Problem sofort,
und kann eine entsprechende Regel evtl. schnell einfügen.
 
\section{Classless Routing (CIDR)} \label{d55e1747}
        

 
			
 
  \par
  
Bei der klassischen Struktur des Internet gab es als kleinstes
Netzwerk ein ''Class C''-Netz mit 8 Bit Hostanteil, also für 254
Maschinen. Da viele kleinere Firmen existieren, wäre das eine
große Verschwendung von IP-Adressen, deshalb vergibt man auch
Teilnetze davon (z.B. mit 4-7 Bit Hostanteil, also /25 bis /29
Netze mit 6 bis 126 nutzbaren Adressen). Diese Technik nennt man
{\bf CIDR} (Classless Internet Domain Routing -
Klassenloses
Internetrouting), weil man nicht mehr an Klasse-A/B/C-Netze
gebunden ist, und ein klassisches A-Netz z.B. wie 256 B-Netze
routen und vergeben kann. 
 

 
  \par
  
Dabei tut sich dann ein Problem auf: die Auflösung der
IP-Adressen in Namen in der in-addr.arpa Zone. Da Delegation ja
nur an den ''Punkten'', also an der Bytegrenze einer 
IP-Adresse möglich ist, muß das C-Netz, das zu verschiedenen 
Teilen von verschiedenen Firmen verwendet wird, vom Provider 
verwaltet werden, da erstmal keine Delegation möglich ist. Das 
ist dann unpraktisch, da eine Firma jede Veränderung über diesen 
Umweg durchführen muß.
 

 
  \par
  
Mit einem Trick, der auf ein Newsposting von
G.A. Herrmannsfeldt zurückgeht (und inzwischen in
RFC 2317 beschrieben ist), lassen sich die Adressen
eines solchen
Teilnetzes dann aber doch delegieren. Die Idee dabei ist, daß in 
der eigentlichen in-addr.arpa die Adressen CNAME-Records sind 
(also Aliasnamen), die auf andere Zonen zeigen. Diese anderen 
Zonen lassen sich dann ''delegieren'', bzw. 
werden dort und dafür die entsprechenden Nameserver eingesetzt. 
Im klassischen Falle sähe die unpraktische Zone beim Provider ja 
so aus (zu den Netzen 192.168.2.0/30, 192.168.2.4/30 usw.):
 

\begin{tabular}{|l|}
                  \hline
                  \begin{tt} 
        
2.168.192.zone
  \end{tt} \\ 
                  \hline
                  \begin{minipage}{130mm} 
                  \begin{scriptsize} 
                  \begin{verbatim} 
        
$TTL 1d

2.168.192.in-addr.arpa. IN SOA pri-ns.selflinux.de. admin.selflinux.de. (
	2000012501 ; Serial (Seriennummer)
	3H	   ; Refresh (Aktualisierung)
	1H	   ; Retry (neuer Versuch)
	1M	   ; Expire (ungültig nach)
	1D )	   ; min. TTL (mindeste Gültigkeit)

		IN  NS		ns1.selflinux.de.
		IN  NS		ns2.selflinux.de.

1		IN  PTR		lisa.simpson.net.
2		IN  PTR		bart.simpson.net.

5		IN  PTR		ernie.sesam.org.
6		IN  PTR		bert.sesam.org.
  \end{verbatim} 
                  \end{scriptsize} 
                  \end{minipage} \\
                  \hline
                  \end{tabular}
			
 
  \par
  
usw. Nun möchte man das also über CNAMES in andere Zonen zeigen
lassen. Als Namen für diese Zone könnte man die Netzwerknummer
verwenden (also 0.2.168.192.in-addr.arpa und
[kurz] ''4'' - die Telekom macht das z.B. so), oder auch
noch die Broadcastaddressen dazunehmen (also ''0-3''),
oder die Netzmaske (''0-3'', oder auch ''0/30'',
was genau genommen nicht verboten ist, da es sich hierbei nicht
um einen Hostnamen handelt, wäre der ''/'' erlaubt), also
erhält man z.B. (nur diese Records):
 
			
 \begin{tabular}{|l|}
                  \hline
                  \begin{tt} 
        
2.168.192.zone
  \end{tt} \\ 
                  \hline
                  \begin{minipage}{130mm} 
                  \begin{scriptsize} 
                  \begin{verbatim} 
        
1		IN  CNAME	1.0-3.2.168.192.in-addr.arpa.
2		IN  CNAME	2.0-3.2.168.192.in-addr.arpa.

5		IN  CNAME	5.4-8.2.168.192.in-addr.arpa.
6		IN  CNAME	6.4-8.2.168.192.in-addr.arpa.
  \end{verbatim} 
                  \end{scriptsize} 
                  \end{minipage} \\
                  \hline
                  \end{tabular}

 
  \par
  
Der Zone 0-3.2.168.192.in-addr.arpa. müssen dann natürlich noch
NS-RRs hinzugefügt werden. Diese müssen in der zu ''0-3''
übergeordneten Zone eingetragen werden - also in der, in der auch
die CNAMES stehen. Das ist günstig, man erhält zusätzlich z.B.:
 
			
 \begin{tabular}{|l|}
                  \hline
                  \begin{tt} 
        
  2.168.192.zone
  \end{tt} \\ 
                  \hline
                  \begin{minipage}{130mm} 
                  \begin{scriptsize} 
                  \begin{verbatim} 
        
0-3.2.168.192.in-addr.arpa. IN NS ns1.simpson.net.
0-3.2.168.192.in-addr.arpa. IN NS ns2.simpson.net.
  \end{verbatim} 
                  \end{scriptsize} 
                  \end{minipage} \\
                  \hline
                  \end{tabular}
			
 
  \par
  
In diesen delegierten Zonen werden dann vom DNS-Admin von
simpson.net die PTR Records untergebracht. Das sieht dann z.B. so
aus:
 
 
 \begin{tabular}{|l|}
                  \hline
                  \begin{tt} 
        
0-3.2.168.192.zone
  \end{tt} \\ 
                  \hline
                  \begin{minipage}{130mm} 
                  \begin{scriptsize} 
                  \begin{verbatim} 
        
$TTL 1d

0-3.2.168.192.in-addr.arpa. IN SOA pri-ns.simpson.net. admin.simpson.net. (
	2000012501 ; Serial (Seriennummer)
	3H	   ; Refresh (Aktualisierung)
	1H	   ; Retry (neuer Versuch)
	1M	   ; Expire (ungültig nach)
	1D )	   ; min. TTL (Mindestgültigkeit)

		IN NS ns1.simpson.net.
		IN NS ns2.simpson.net.

1		IN  PTR		lisa.simpson.net.
2		IN  PTR		bart.simpson.net.
  \end{verbatim} 
                  \end{scriptsize} 
                  \end{minipage} \\
                  \hline
                  \end{tabular}

 
  \par
  
Es ist auch nicht zwingend notwendig, die ''erfundenen'' neuen
Zones unter die in-addr.arpa.-Zone zu legen, man könnte auch 
0-3.simpson.net. verwenden, oder gar arpa.simpson.net. Das muß je
nach Fall entschieden werden. Diese Entscheidung liegt beim
übergeordneten Provider. 
			
			
  \par
  
Leider kann man dieses Verfahren nicht mehrfach anwenden, um
weiter zu delegieren, da in diesem Fall ein CNAME auf einen CNAME
zeigt, was nicht sein soll (und was damit zu Problemen führen
kann).
 
\section{Umgang mit Störungen} \label{d55e1825}
        
 

 
  \par
  
Schäden durch DNS-Serverausfälle lassen sich durch redundante
Systeme weitgehend vermeiden. Clienten sind so zu konfigurieren,
daß sie mehrere Server kennen. Fällt ein solcher Server aus (der
ja ein caching-only Nameserver sein kann, also einer, der für
keine Zone authoritative ist), wechselt der Resolver einfach auf
einen anderen, bis auf etwas Zeitverlust kein weiterer Nachteil. 
Die Reihenfolge der Server ist von Client zu Client zu mischen,
um Lastverteilung zu erreichen.
 
			
 
  \par
  
Es sind ausreichend viele Secondaries bereitzustellen, ansonsten
wird der Betrieb u.U.  durch Überlast gestört. Verwenden lokale
Clienten andere DNS-Server, so wird das u.U. spät bemerkt. Fällt
ein Secondary aus, stellt das kurzfristig kein allzu großes
Problem dar, solange noch mindestens ein Secondary verfügbar ist.
Dabei muß vermieden werden, daß in diesem Falle der oder die
verbleibenden Secondaries überlastet werden.
 
			
 
  \par
  
Fällt ein Primary aus, und ist dieser nur Primary, aber keiner
mit einem NS-RR aufgeführter (auch
{\bf hidden primary}; genannt), so verläuft der Ausfall 
vollkommen transparent, bis die Secondaries die Zone expiren 
(also wegwerfen), was so um die zwei bis sechs Wochen dauern 
sollte (je nach Konfiguration der SOA-Records der Zone). 
Nach dieser Zeit ist die Zone jedoch vollkommen unbekannt! In 
der Praxis ist das jedoch mehr als genug Zeit, um einen neuen 
Server aufzusetzen, ein Backup einzuspielen, und so notfalls 
einfach den kompletten Server zu wechseln.
 
			
 
  \par
  
Da DNS auf verteilten Datenbanken beruht, muß bei einer Kontrolle
bzw. beim Debugging beachtet werden, welcher Server (welcher
Secondary, welcher Forwarder etc.) welche Antwort gibt. So kann
es z.B. sein, daß ein Secondary fehlerhaft arbeitet. Ein Test
kann aber die richtige Antwort liefern, falls dieser zufällig
nicht gefragt wird. Diese Antwort wird dann evtl. noch von einem
Forwarder gecached. Deshalb sollte man bei Tests die Secondaries
einen nach dem anderen direkt fragen. Widersprechen sich z.B.
zwei Secondaries, können die Fehler diffus und versteckt
auftreten.
 
			
 
  \par
  
Haben sich die Zonendateien in letzter Zeit geändert, ist es auch
möglich, daß ein Secondary den Transfer noch nicht durchführen
konnte. Deshalb muß als erstes geprüft werden, ob die SOA-Serial
überhaupt die aktuelle ist. Eventuell gibt es Probleme mit der
Notification (wenn alles funktioniert, sollten die aktualisierten
Zonen in wenigen Minuten den Secondaries bekannt sein).
 
 
 
  \par
  
Es gibt auch Fehler, die eigentlich in anderen Zonen liegen, als
in der sie bemerkt werden. So ist es zum Beispiel denkbar, daß
ein NS-Record fehlerhaft scheint, in Wirklichkeit aber der
dazugehörige A-Record aus der Zone, zu der der DNS-Server gehört,
fehlerhaft ist oder nicht existiert. Diese Zone wird dann
eventuell auch noch von anderen verwaltet...
 
\section{Root-Rechte} \label{d55e1855}
        
 

 
  \par
  
Häufig wird {\bf BIND} unter root-Rechten gestartet.
Das ist natürlich ein Sicherheitsrisiko und sollte vermieden
werden. Bei aktuellen Versionen ist das sehr einfach. Zunächst
müssen eine eigene Gruppe und ein eigener Benutzer eingerichtet
werden. Unter Linux kann man diese ganz einfach mit den folgenden
beiden Kommandos anlegen:
 

 
   \begin{tt} \begin{scriptsize} root@linux / \# 
groupadd named
   \end{scriptsize} \end{tt} \linebreak 
   \begin{tt} \begin{scriptsize} root@linux / \# 
useradd -d /var/named -g named named
   \end{scriptsize} \end{tt} \linebreak 
 

 
  \par
  
Nun muß das Verzeichnis {\bf /var/named} an diesen
Benutzer ''verschenkt'' werden:
 
			
 
   \begin{tt} \begin{scriptsize} root@linux / \# 
chown -R named:named /var/named
   \end{scriptsize} \end{tt} \linebreak 
 

 
  \par
  
Eigentlich besteht kein Grund, eigene, primäre Zonenfiles (also
die, für die der Server authorativ und kein Secondary ist) zu
verschenken. {\bf bind} muß aber in der Lage sein,
sekundäre Zonefiles
zu schreiben, nachdem sie vom Primary geladen wurden. Dazu kann
man aber auch ein Unterverzeichnis verwenden, und nur dieses
schreibbar machen. Dann kann im Falle des Mißbrauches der
Benutzerkennung (z.B. durch einen erfolgreichen Angriff) kein
primäres Zonefile verändert werden.
 

 
  \par
  
Nun muß der Startaufruf um zwei Parameter erweitert werden, damit
bind weiß, das er unter anderen Benutzerrechten laufen soll:
 
			
 
   \begin{tt} \begin{scriptsize} root@linux / \# /usr/sbin/named -u named -g named \end{scriptsize} \end{tt} \linebreak 
 
			
 
  \par
  
Nach der Initialisierung werden dann die root-Rechte abgelegt.
Beim Start sind diese natürlich noch kurz erforderlich, da sonst
der Port 53 nicht verwendet werden könnte (privilegierte Ports
dürfen nur von root verwendet werden).
 
\section{Chroot-Umgebung} \label{d55e1909}
        

 

 
  \par
  
Um es noch sicherer zu bekommen, kann man {\bf bind}
auch in einer {\bf chroot}-Umgebung laufen lassen.
Das macht allerdings etwas mehr Arbeit, denn alle von
{\bf bind} benötigten Dateien müssen dann unterhalb
dieses {\bf chroot}-Verzeichnisses liegen. Dazu sind
dann einige Schritte notwendig. Vorallem muß
{\bf bind} als eigener User laufen, da
{\bf chroot} mit Root-Rechten nicht sinnvoll
funktioniert.
 
			
 
  \par
  
Zunächst muß einen minimale Verzeichnisstruktur erzeugt werden,
die {\bf bind} verwenden kann. Sie kann z.B. unter
{\bf /var/named.chroot}
erzeugt werden. Dazu folgendes Kommando (als root!):
 

 
   \begin{tt} \begin{scriptsize} root@linux / \# mkdir -p /var/named.chroot/etc \end{scriptsize} \end{tt} \linebreak 
   \begin{tt} \begin{scriptsize} root@linux / \# mkdir -p /var/named.chroot/var/named \end{scriptsize} \end{tt} \linebreak 
   \begin{tt} \begin{scriptsize} root@linux / \# mkdir -p /var/named.chroot/var/run \end{scriptsize} \end{tt} \linebreak 
   \begin{tt} \begin{scriptsize} root@linux / \# mkdir -p /var/named.chroot/bin \end{scriptsize} \end{tt} \linebreak 
   \begin{tt} \begin{scriptsize} root@linux / \# mkdir -p /var/named.chroot/usr/sbin \end{scriptsize} \end{tt} \linebreak 
   \begin{tt} \begin{scriptsize} root@linux / \# mkdir -p /var/named.chroot/dev \end{scriptsize} \end{tt} \linebreak 
   \begin{tt} \begin{scriptsize} root@linux / \# mkdir -p /var/named.chroot/lib \end{scriptsize} \end{tt} \linebreak 
 
			
 
  \par
  
Nun müssen die Konfigurationsdatei und die Datenbanken kopiert
werden:
 

 
   \begin{tt} \begin{scriptsize} root@linux / \# 
cp -p  /etc/named.conf /var/named.chroot/etc/
   \end{scriptsize} \end{tt} \linebreak 
   \begin{tt} \begin{scriptsize} root@linux / \# 
cp -pR /var/named /var/named.chroot/var
   \end{scriptsize} \end{tt} \linebreak 
 
			
 
  \par
  
Nun sind die Rechte der Dateien zu korrigieren:
 

 
   \begin{tt} \begin{scriptsize} root@linux / \# 
chown -R root:root /var/named.chroot/
   \end{scriptsize} \end{tt} \linebreak 
   \begin{tt} \begin{scriptsize} root@linux / \# 
chmod 755 /var/named.chroot
   \end{scriptsize} \end{tt} \linebreak 
   \begin{tt} \begin{scriptsize} root@linux / \# 
chmod 755 /var/named.chroot/*
   \end{scriptsize} \end{tt} \linebreak 
   \begin{tt} \begin{scriptsize} root@linux / \# 
chown -R named:named /var/named.chroot/var/named/
   \end{scriptsize} \end{tt} \linebreak 
   \begin{tt} \begin{scriptsize} root@linux / \# 
chown -R named:named /var/named.chroot/var/run/
   \end{scriptsize} \end{tt} \linebreak 
   \begin{tt} \begin{scriptsize} root@linux / \# 
chmod 644 /var/named.chroot/etc/*
   \end{scriptsize} \end{tt} \linebreak 
   \begin{tt} \begin{scriptsize} root@linux / \# 
chmod 755 /var/named.chroot/lib/*
   \end{scriptsize} \end{tt} \linebreak 
   \begin{tt} \begin{scriptsize} root@linux / \# 
chmod 755 /var/named.chroot/usr/sbin
   \end{scriptsize} \end{tt} \linebreak 
   \begin{tt} \begin{scriptsize} root@linux / \# 
chmod 755 /var/named.chroot/usr/sbin/*
   \end{scriptsize} \end{tt} \linebreak 
 

 
  \par
  
Normalerweise verwendet man dynamisch gelinkte Binärdateien, und
so müssen die Bibliotheken kopiert werden. Zuerst muß man schauen,
welche Libs benötigt werden:
 

 
   \begin{tt} \begin{scriptsize} root@linux / \# ldd `which named` \end{scriptsize} \end{tt} \linebreak 
 

 
  \par
  
Eine Ausgabe könnte sein:
 

 
  \begin{tt} \begin{scriptsize} libc.so.6 =\verb+>+ /lib/libc.so.6 (0x4001d000) \linebreak /lib/ld-linux.so.2 =\verb+>+ /lib/ld-linux.so.2 (0x40000000)\end{scriptsize} \end{tt} \linebreak
 

 
  \par
  
Es kann bei anderen Unix-Derivaten sein, daß das Kommando
{\bf ldd} oder {\bf which} nicht
verfügbar ist. Dann muß ein anderer Weg gefunden werden.
				 \linebreak  \linebreak 
Diese Dateien werden kopiert:
 

 
   \begin{tt} \begin{scriptsize} root@linux / \# 
cp -p /lib/libc.so.6 /var/named.chroot/lib/
   \end{scriptsize} \end{tt} \linebreak 
   \begin{tt} \begin{scriptsize} root@linux / \# 
cp -p /lib/ld-linux.so.2 /var/named.chroot/lib/
   \end{scriptsize} \end{tt} \linebreak 
 
			
 
  \par
  
Dann benötigt {\bf BIND} die Gerätedatei
{\bf /dev/null}. Hat man ein modernes
{\bf /bin/cp}, so reicht ein:
 

 
   \begin{tt} \begin{scriptsize} root@linux / \# 
cp -a /dev/null /var/named.chroot/dev/
   \end{scriptsize} \end{tt} \linebreak 
 
			
 
  \par
  
andernfalls muß man das Gerät neu anlegen:
 

 
   \begin{tt} \begin{scriptsize} root@linux / \# 
mknod /var/named.chroot/dev/null c 1 3
   \end{scriptsize} \end{tt} \linebreak 
 

 
  \par
  
(Die konkreten Parameter können wiederum bei anderen
Unix-Derivaten abweichen).
 
			
 
  \par
  
{\bf BIND} benötigt die Datei
{\bf /etc/localtime}:
 

 
   \begin{tt} \begin{scriptsize} root@linux / \# 
cp /etc/localtime /var/named.chroot/etc/
   \end{scriptsize} \end{tt} \linebreak 
 

 
  \par
  
und natürlich seine eigenen
{\bf /etc/passwd}-Einträge. Diese können
z.B. mit folgenden Einzeilern erzeugt werden:
 

 
   \begin{tt} \begin{scriptsize} root@linux / \# 
cat /etc/passwd | grep 'named' \verb+>+ /var/named.chroot/etc/passwd
   \end{scriptsize} \end{tt} \linebreak 
   \begin{tt} \begin{scriptsize} root@linux / \# 
cat /etc/group  | grep 'named' \verb+>+ /var/named.chroot/etc/group
   \end{scriptsize} \end{tt} \linebreak 
 

 
  \par
  
Wenn {\bf bind} über {\bf syslogd}(8)
loggt, und nicht nur über eigene
logfiles, muß hier noch weiter angepaßt werden. Normalerweise
greift {\bf BIND} auf {\bf /dev/log} zu.
Diese Datei ist nun aber nicht mehr erreichbar.
{\bf syslogd} muß also eine Datei zusätzlich
verwenden, die erreichbar ist.
Ein halbwegs moderes {\bf syslogd} kennt dazu den
Parameter ''-a'', der nun beim Start des Syslogdeamons
angegeben werden muß. Dazu muß u.U. das Startscript angepaßt
werden. Bei einer SuSE-Distribution kann man aber auch den
Parameter SYSLOGD\_PARAMS in {\bf /etc/rc.config}
verwenden:
 

 \begin{tabular}{|l|}
                  \hline
                  \begin{tt} 
        
/etc/rc.config
  \end{tt} \\ 
                  \hline
                  \begin{minipage}{130mm} 
                  \begin{scriptsize} 
                  \begin{verbatim} 
        
SYSLOGD_PARAMS="-a /var/named.chroot/dev/log"
  \end{verbatim} 
                  \end{scriptsize} 
                  \end{minipage} \\
                  \hline
                  \end{tabular}
			
 
  \par
  
Sonst muß der ''-a''-Parameter an der entsprechenden
Stelle im Startscript hinzugefügt werden. Danach ist
{\bf syslogd} neu zu starten.
dabei sollte {\bf syslogd} nun diese Datei erzeugt
haben. Leider neigen scheinbar einige
{\bf syslogd}-Versionen dazu,
hier Bugs zu besitzen, und nur noch diesen Socket auzuwerten
oder dergleichen. Ein Update sollte dem abhelfen.
 

 
  \par
  
Soll {\bf bind} nicht über {\bf syslogd}
loggen, sondern in Dateien schreiben, kann folgendes
konfiguriert werden:
 

 \begin{tabular}{|l|}
                  \hline
                  \begin{tt} 
        
/etc/named.conf
  \end{tt} \\ 
                  \hline
                  \begin{minipage}{130mm} 
                  \begin{scriptsize} 
                  \begin{verbatim} 
        
logging {

        channel file_log {
                file "named.log";
                severity info;
        };

        channel file_debug {
                file "named.run";
                severity dynamic;
        };

        category default {
                file_log; file_debug;
        };
};
  \end{verbatim} 
                  \end{scriptsize} 
                  \end{minipage} \\
                  \hline
                  \end{tabular}

 
  \par
  
Nun müssen die Programme selbst kopiert werden, mindestens
{\bf named} und {\bf named-xfer} (mit
{\bf which named} kann herrausgefunden werden, wo
sich diese befinden). Dabei muß beachtet werden, daß der Pfad zu
{\bf named-xfer} ''hardcoded'' im
Binärprogramm steht. Dieser Pfad muß dann um den chroot-Pfad
erweitert werden, damit das Programm von {\bf bind}
gefunden wird. Liegen {\bf named} und
{\bf named-xfer} z.B. in {\bf /usr/sbin}
(wie bei SuSE), so müssen sie nach
{\bf /var/named.chroot/usr/sbin} kopiert werden:
 
			
 
   \begin{tt} \begin{scriptsize} root@linux / \# 
cp /usr/sbin/named* /var/named.chroot/usr/sbin/
   \end{scriptsize} \end{tt} \linebreak 
 

 
  \par
  
Man kann natürlich auch in ein anderes Verzeichnis kopieren, muß
dann aber in der Konfigurationsdatei den Pfad entsprechend
angeben, z.B.:
 

 \begin{tabular}{|l|}
                  \hline
                  \begin{tt} 
        
/etc/named.conf
  \end{tt} \\ 
                  \hline
                  \begin{minipage}{130mm} 
                  \begin{scriptsize} 
                  \begin{verbatim} 
        
options {
	...
	named-xfer "/bin/named-xfer";
};
  \end{verbatim} 
                  \end{scriptsize} 
                  \end{minipage} \\
                  \hline
                  \end{tabular}
			
 
  \par
  
Dabei ist wieder zu beachten, daß die benötigten Libs geladen
werden können. Der hier angegebene Pfad ist natürlich um das
Chroot-Verzeichnis gekürzt anzugeben, da {\bf BIND}
dann von dieser nichts mehr sieht, also unter
{\bf /bin} etwas anderes
versteht, als ein nicht ge-chrooteter Prozeß.
 
			
 
  \par
  
Der Startaufruf für {\bf BIND} muß nun nur noch um
den Parameter ''-t'' erweitert werden:
 
			
 
   \begin{tt} \begin{scriptsize} root@linux / \# 
/usr/sbin/named -u named -g named -t /var/named.chroot
   \end{scriptsize} \end{tt} \linebreak 
 
			
 
  \par
  
Nun sollte überprüft werden, ob Anfragen noch richtig beantwortet
werden, und ob ein Zonetransfer funktioniert.
 
 
 
  \par
  
Da (ein älteres) {\bf ndc} das pid-File in
{\bf /var/run} erwartet, und nicht in
{\bf /var/named.chroot/var/run}, kann hier ein
Symlink helfen, der vom Startscript nach dem Starten jeweils
erzeugt wird:
 

 
   \begin{tt} \begin{scriptsize} root@linux / \# 
ln -s /var/named.chroot/var/run/named.pid /var/run/
   \end{scriptsize} \end{tt} \linebreak 
 

 
  \par
  
Beim Beenden kann der Link dann einfach gelöscht werden:
 
			
 
   \begin{tt} \begin{scriptsize} root@linux / \# 
rm -f /var/run/named.pid
   \end{scriptsize} \end{tt} \linebreak 
 

 
  \par
  
Es ist zu beachten, daß {\bf ndc restart} und
{\bf ndc start} nicht mehr verwendet werden
sollten, da hier die Parameter aus unserem Startscript nicht
verwendet werden! Dann wird {\bf bind} unter
root-Rechten ohne {\bf chroot} ausgeführt! \linebreak 
Modernere {\bf ndc}-Versionen handhaben die
Verbindung anders. Es wird ein {\bf control channel}
verwendet, defaultmäßig ist das {\bf /var/run/ndc}.
Das kann über Parameter geändert werden. Ein modernes
{\bf ndc} kann aber auch über Parameter dazu
veranlaßt werden, ein pid-File zu verwenden. Diese Defaults
können beim Compilieren allerdings geändert werden. Sonst
lautet der Aufruf von {\bf ndc} wie folgt:
 
			
 
   \begin{tt} \begin{scriptsize} root@linux / \# 
ndc -c /var/named.chroot/var/run/ndc 
   \end{scriptsize} \end{tt} \linebreak 
 

 
  \par
  
Es ist wohl eine gute Idee, hierauf einen Shell-''Alias'' zu
setzen, z.B. in {\bf \~{}/.profile}:
 

 \begin{tabular}{|l|}
                  \hline
                  \begin{tt} 
        \~{}/.profile\end{tt} \\ 
                  \hline
                  \begin{minipage}{130mm} 
                  \begin{scriptsize} 
                  \begin{verbatim} 
        
alias ndc='ndc -c /var/named.chroot/var/run/ndc'
  \end{verbatim} 
                  \end{scriptsize} 
                  \end{minipage} \\
                  \hline
                  \end{tabular}

 
  \par
  
Es sollte mindestens ein {\bf reload} probiert
werden, um zu sehen, ob z.B. {\bf bind} jetzt
noch seine Konfigurationsdatei lesen kann. Beim ersten Start
funktioniert das immer, da vor dem Setzen der
{\bf chroot} Umgebung noch root-Rechte
vorhanden sind, was bei {\bf reload}
ja nicht mehr der Fall ist. Gegebenenfalls sind die Rechte zu
kontrollieren. Hierbei gilt, {\bf bind} darf ruhig
viel (alles) lesen können, aber nur die Slave-Zones schreiben
(also darf dem User nur wenig gehören - nur das
Slave-Zonen-Verzeichnis).
 
\section{Versionen} \label{d55e2349}
        
 

 
  \par
  
Da {\bf bind} leider immer wieder Sicherheitslücken 
enthält, ist es ein beliebter Angriffspunkt für Angreifer. Da zu 
vielen {\bf bind}-Versionen Sicherheitslücken 
bekannt sind, kann eine Angreiferin auf die Idee kommen, 
einfach die Version abzufragen, und dann kann sie die nun bekannten 
Sicherheitslücken ausnutzen.
 
			
 
Deshalb mag es günstig sein, die Versionsnummer nicht zu
verraten, um der Angreiferin das Leben etwas schwerer zu machen.
 

 
  \par
  
Die Version läßt sich erfahren, wenn man einen
{\bf BIND}-Server nach
''version.bind'', Type TXT, in der Klasse CHAOS fragt.
Das geschieht z.B. mit folgendem Kommando:
 

 
   \begin{tt} \begin{scriptsize} root@linux / \# 
dig @\verb+<+server\verb+>+ version.bind TXT CHAOS
   \end{scriptsize} \end{tt} \linebreak 
 

 
  \par
  
Eine Antwort sieht dann (gekürzt) so aus:
 

 
  \begin{tt} \begin{scriptsize} VERSION.BIND.\verb+  +\verb+  +\verb+  +\verb+  +\verb+  + 0S CHAOS TXT\verb+  +\verb+  +''8.1.2''\end{scriptsize} \end{tt} \linebreak
 

 
  \par
  
Man kann dazu natürlich auch {\bf nslookup}
verwenden:
 

 
   \begin{tt} \begin{scriptsize} root@linux / \# 
nslookup -class=CHAOS -query=txt version.bind.
   \end{scriptsize} \end{tt} \linebreak 
 

 
  \par
  
Neuere {\bf BIND}-Versionen kennen eine
Konfigurationsoption, um die dabei angezeigte Zeichenkette zu
setzen. Man kann sich damit dann eine Version 10.100.1000
basteln, oder auf etwas ganz anderes setzen Das kann dann so
aussehen:
 

 \begin{tabular}{|l|}
                  \hline
                  \begin{tt} 
        
/etc/named.conf
  \end{tt} \\ 
                  \hline
                  \begin{minipage}{130mm} 
                  \begin{scriptsize} 
                  \begin{verbatim} 
        
options {
	...
        version "[Secured]";   
};
  \end{verbatim} 
                  \end{scriptsize} 
                  \end{minipage} \\
                  \hline
                  \end{tabular}

  
  \par
  
Dann wird mit dem Kommando das auch angezeigt:
  

  
  \begin{tt} \begin{scriptsize} VERSION.BIND.\verb+  +\verb+  +\verb+  +\verb+  +\verb+  + 0S CHAOS TXT\verb+  +\verb+  +''[Secured]''\end{scriptsize} \end{tt} \linebreak
 

 
  \par
  
Und Rückschlüsse auf die Version sind so nicht mehr möglich.
Diese Änderung kann natürlich auch gemacht werden, in dem der RR
''version.bind'' in einer Zone gesetzt wird. Dabei können dann, wie
für jede andere Zone auch, ACL-Berechtigungen konfiguriert
werden. Diese Zone wird so konfiguriert, wie auch die Zonen der
normalen Namen der Klasse IN. Dazu benötigt man z.B. folgenden
Eintrag in der Konfigurationsdatei:
 
			
 \begin{tabular}{|l|}
                  \hline
                  \begin{tt} 
        
/etc/named.conf
  \end{tt} \\ 
                  \hline
                  \begin{minipage}{130mm} 
                  \begin{scriptsize} 
                  \begin{verbatim} 
        
zone "bind" CHAOS {
	type master;
	file "bind.zone";
	allow-query { none; };     //Zugriff verweigern
	allow-transfer { none; };  //damit AXFR auch nicht geht.
			};
  \end{verbatim} 
                  \end{scriptsize} 
                  \end{minipage} \\
                  \hline
                  \end{tabular}
 
 
  \par
  
Natürlich kann man auch Ausgewählten den Zugriff erlauben. Nun 
muß noch die Datenbank selbst angelegt werden. Sie kann folgenden
Inhalt haben:
 

 \begin{tabular}{|l|}
                  \hline
                  \begin{tt} 
        
bind.zone
 \end{tt} \\ 
                  \hline
                  \begin{minipage}{130mm} 
                  \begin{scriptsize} 
                  \begin{verbatim} 
        
bind. CHAOS SOA pri-ns.selflinux.de. admin.selflinux.de. (
	2000012501 ; Serial (Seriennummer)
	3H	   ; Refresh (Aktualisierung)
	1H	   ; Retry (neuer Versuch)
	100D	   ; Expire (ungültig nach)
	1D )	   ; min. TTL (Mindestgültigkeit)

	CHAOS   NS      dns
version CHAOS   TXT     "[Secured]"
 \end{verbatim} 
                  \end{scriptsize} 
                  \end{minipage} \\
                  \hline
                  \end{tabular}
\section{Wachstum} \label{d55e2451}
        
 

 
  \par
  
Wichtig ist vor allem, Störungen schnell zu erkennen und so
beseitigen zu können. Auch die Auslastung in Spitzenzeiten ist zu
überwachen. Wird diese zu hoch, kann man über eine Delegation von
Teilen der Domain nachdenken, oder weitere Secondaries
einsetzen. Sind cachende Server überlastet, so ist es
aufwendiger, neue einzusetzen, da diese ja bei den Clienten
konfiguriert werden müssen. Eventuell ist aber die Hardware
ausreichend erweiterbar (vielleicht hilft auch erstmal ein
Hauptspeicherausbau).
 
			
 
  \par
  
Um einen reibungslosen Betrieb zu erhalten, ist es wichtig, den
Überblick zu haben. Deshalb sollte man sich die Zeit nehmen,
Adresspläne zu pflegen, Topologiediagramme aktuell zu halten und
Änderungen mit anderen Beteiligten zu synchronisieren und
abzusprechen. Normalerweise sollte ein DNS-Admin wissen, wer für
eine bestimmte Maschine verantwortlich ist, und der weiß, wo sie
physikalisch steht. Im Idealfall erfährt der DNS-Admin auch, wenn
Maschinen aus dem Betrieb genommen werden. Leider werden dessen
IP-Adressen teilweise einfach stillschweigend für neue Maschinen
verwendet. Erstmal kein Problem. Aber in drei Jahren
vielleicht...
 
\section{Keep it running} \label{d55e2463}
        
 
 
  \par
  
Dieser goldene Satz gilt natürlich auch für den DNS-Administrator.
Läuft {\bf BIND} einmal, so muß mit nur wenig
Wartungsaufwand gerechnet werden. Hin und wieder sollte man die
Root-Server Einträge erneuern, da sich deren IP-Adressen mit der 
Zeit ändern können. Sicherheitshinweise sollten verfolgt
werden, und so ist evtl. die Software zu updaten.
Routineprüfungen schaden selbstverständlich nicht, insbesondere
ein Beobachten der Logfiles (dazu verwendet man am besten ein
Tool, wie {\bf logsurfer} oder
{\bf logmail}).  
 

	\ref{inhalt.tex}


	\end{document}
	
