Was haben wir denn überhaupt
Auf einem internettauglichen Host konfiguriert man minimal die folgenden Informationen:
- die IP-Adresse des Hosts selbst
- die “Länge” der Netzmaske, entweder als Netzmaske in “dotted decimal notation” oder
als Prefixlänge und
- das Defaultgateway, ein im lokalen Netz (“Layer 2”) erreichbarer Host, der für uns Datenpakete in das
Internet weiterleitet.
Jedes für den Internetverkehr geeignete Interface hat eine eigene IP-Adresse, während die Defaultroute in der nur
einmal pro Host vorhandenen Routingtabelle steht.
Was man minimal sieht.
Die Routingtabelle eines Internet-Hosts ist besteht im gängigsten Fall aus zwei Einträgen:
- Einer auf das physikalische Interface zeigenden Netzwerkroute (pro Interface), über die die Systeme des lokalen
Layer-2-Netzwerksegments erreichbar werden. Das Defaultgateway, das den Übergang ins Internet anbietet, gehört zu
diesen Systemen hinzu. Diese Route bekommt man auf fast allen Systemen automatisch gesetzt, da sie aus der IP-Adresse
und der Netzmaske herleitbar ist; manche Betriebssysteme versuchen ihre Existenz zu verschleiern.
- einer auf das Defaultgateway zeigenden Defaultroute. Da dieser Fall so häufig ist, wird ihr Ziel oft von den
gängigen Tools als “default” dargestellt:
$ ip route
default via 192.168.181.254 dev eth0 proto static
192.168.181.0/24 dev eth0 proto kernel scope link src 192.168.181.98
Linux erlaubt mit Hilfe des Tools “ip” die Abfrage der Routingtabelle für ein konkretes Ziel:
$ ip route show to 192.168.181.0/24
192.168.181.0/24 dev eth0 proto kernel scope link src 192.168.181.98
$ ip route show to 192.168.181.4
$
Da man hierbei genau wissen muss, wie die Routingtabelle aussieht (weil man nur dann eine Ausgabe bekommt, wenn man
das Routingziel inklusiv Netzmaske korrekt trifft), ist das allerdings recht sinnlos - wie das zweite Kommando zeigt.
Daher gibt es das auch in “genauer”, so dass man wirklich abfragen kann, welche Route für ein bestimmtes
Ziel wirklich benutzt wird:
$ ip route list match 192.168.181.4
default via 192.168.181.254 dev eth0 proto static
192.168.181.0/24 dev eth0 proto kernel scope link src 192.168.181.98
$ ip route list match 8.8.8.8
default via 192.168.181.254 dev eth0 proto static
$
Doch bevor ich Euch erkläre, was man mit diesem Wissen machen kann, ein kleiner Exkurs in IP-Netzwerk-Berechnung und
Netzmasken.
IP-Adresse und Netzmaske
Eine IP-Adresse besteht aus Netz- und Hostanteil. Die Stelle, an der zwischen Netz- und Hostanteil übergegangen
wird, ist variabel. Ihr Platz innerhalb der Binärrepräsentation der Adresse wird durch den Prefix bestimmt:
Address: 172.16.0.10/24 10101100.00010000.00000000. 00001010
Netmask: 255.255.255.0 = 24 11111111.11111111.11111111. 00000000 (Prefix: /24)
Network: 172.16.0. 10101100.00010000.00000000. 00000000
Host: .10 00000000.00000000.00000000. 00001010
In diesem trivialen Fall ist der Prefix “/24” (“slash vierundzwanzig”). Das bedeutet, dass
die Netzmaske aus 24 Einsen besteht und mit Nullen aufgefüllt wird. In Dotted Decimal Notation ist das also
255.255.255.0.
Routing
Wenn nun ein Rechner ein Datagramm an einen anderen Rechner im Internet verschicken muss, weiß er nur dessen
IP-Adresse. Die Netzmaske des Empfängers spielt hier keine Rolle.
Mit der Empfänger-Adresse konsultiert unser Rechner nun seine Routingtabelle, die in unserem Beispiel so
aussieht:
0.0.0.0/0 via 172.16.0.1
172.16.0.0/24 dev lanw0
Dabei beachten wir, dass der Host-Anteil eines Routingtabelleneintrags immer komplett aus Nullen besteht. Auf diese
Weise sparen wir uns bei der Berechnung der Routen das Ausnullen des Hostanteils. Gute Betriebssysteme korrigieren hier
eine Falscheingabe oder akzeptieren einen solchen Eintrag gar nicht erst.
Im ersten Beispiel haben wir ein Paket für die IP-Adresse 8.8.8.8.
Wir vergleichen diese Adresse mit jedem Eintrag in unserer Routingtabelle, wobei wir uns nur für den
“vor” dem Prefixpunkt stehenden Teil der Adresse interessieren.
Im ersten Schritt
Address: 8.8.8.8 00001000.00001000.00001000. 00001000
Netmask: 255.255.255.0 = 24 11111111.11111111.11111111. 00000000
Network: 8.8.8.0 00001000.00001000.00001000. 00000000
Route: 172.16.0.0 10101100.00010000.00000000. 00000000
merken wir, dass die Route für 172.16.0.0 für unser Ziel nicht greift.
Im zweiten Schritt jedoch,
Address: 8.8.8.8 00001000.00001000.00001000.00001000
Netmask: 0.0.0.0 = 0 00000000.00000000.00000000.00000000
Network: 0.0.0.0 00000000.00000000.00000000.00000000
Route: 0.0.0.0 00000000.00000000.00000000.00000000
wird durch den Prefix /0 die Adresse komplett ausgenullt und greift. Damit geht das Paket zu 172.16.0.1, unserem
Defaultgateway.
Nun der komplexere Fall: Wir haben ein Paket für 172.16.0.8.
Address: 172.16.0.8 10101100.00010000.00000000. 00001000
Netmask: 255.255.255.0 = 24 11111111.11111111.11111111. 00000000
Address: 172.16.0.0 10101100.00010000.00000000. 00000000
Route: 172.16.0.0 10101100.00010000.00000000. 00000000
Address: 172.16.0.8 10101100.00010000.00000000.00001000
Netmask: 0.0.0.0 = 0 00000000.00000000.00000000.00000000
Network: 0.0.0.0 00000000.00000000.00000000.00000000
Route: 0.0.0.0 00000000.00000000.00000000.00000000
Hier passen jetzt beide Routen und wir müssen eine Entscheidung zwischen den beiden Routen treffen. Hier schreiben
die Internet-Standards vor, dass wir die “most specific” Route, also die mit dem längsten Prefix wählen.
172.16.0.0/24 gewinnt also und wir stellen das Paket über das LAN zu.
Der Dual Homed Host
Wenn ich jetzt einen Host mit mehr als einem Interface habe, wird die Sache interessant. Jetzt müssen wir plötzlich
nicht mehr nur nach “im LAN erreichbar” und “muss ans Defaultgateway” unterscheiden, sondern wir
haben plötzlich mehr Fälle. Mindestens müssen wir nach “im LAN 1 erreichbar”, “im LAN 2
erreichbar” oder “muss ans Defaultgateway” unterscheiden; in vielen Fällen haben wir aber auch Netze,
die über ein Gateway im “anderen” Netz erreichbar sind.
Nehmen wir beispielsweise einen Webserver, der ein Interface nach “draußen” ins Internet hat und ein
Interface nach innen zu Backends und Admins. Admins seien der Einfachheit halber in einem Netz 192.168.0.0/24
angesiedelt, das über das Gateway mit der Adresse 172.16.0.1 erreichbar ist, und der Gemeinheit halber haben wir für
den Traffic zu Datenbank-Backends etc ein Extra-Gateway mit der Adresse 172.16.0.2 hingestellt, über das das
Backend-Netzwerk 10.0.0.0/27 erreichbar ist. Dann sieht die Konfiguration beispielsweise so aus:
$ ip addr
2: ext0: mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
inet 192.0.2.10/24 brd 192.0.2.255 scope global ext0
valid_lft forever preferred_lft forever
3: int0: mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
inet 172.16.0.10/24 brd 172.16.0.255 scope global int0
valid_lft forever preferred_lft forever
$ ip route
default via 192.0.2.1 dev ext0 proto static
192.0.2.0/24 dev ext0 proto kernel scope link src 192.0.2.10
172.16.0.0/24 dev int0 proto kernel scope link src 172.16.0.10
192.168.0.0/24 via 172.16.0.1 dev int0 proto static
10.0.0.0/27 via 172.16.0.2 dev int0 proto static
Und jetzt ein paar Beispiele.
Das erste Paket ist für 8.8.8.8. Hier passt keine unserer “normalen” Routen, wie oben ist die
Defaultroute die einzige die greift und das Paket geht zum Defaultgateway raus.
Das zweite Paket ist für 10.0.0.4
Address: 10.0.0.4 00001010.00000000.00000000. 00000100
Netmask: 255.255.255.0 = 24 11111111.11111111.11111111. 00000000
Address: 10.0.0.0 00001010.00000000.00000000. 00000000
Route: 192.0.2.0/24 11000000.00000000.00000010. 00000000
Address: 10.0.0.4 00001010.00000000.00000000. 00000100
Netmask: 255.255.255.0 = 24 11111111.11111111.11111111. 00000000
Address: 10.0.0.0 00001010.00000000.00000000. 00000000
Route: 172.16.0.0/24 10101100.00010000.00000000. 00000000
Address: 10.0.0.4 00001010.00000000.00000000. 00000100
Netmask: 255.255.255.0 = 24 11111111.11111111.11111111. 00000000
Address: 10.0.0.0 00001010.00000000.00000000. 00000000
Route: 192.168.0.0/24 11000000.10101000.00000000. 00000000
Address: 10.0.0.4 00001010.00000000.00000000.000 00100
Netmask: 255.255.255.224 = 27 11111111.11111111.11111111.111 00000
Address: 10.0.0.0 00001010.00000000.00000000.000 00000
Route: 10.0.0.0 00001010.00000000.00000000.000 00000
Hier passen nur die Route für 10.0.0.0/27 und die Defaultroute, die Route mit dem längeren Prefix (27>0) gewinnt,
das Paket geht zum Gateway 172.16.0.2
Damit sind auch schon alle Fälle hier oder da erklärt. Komplizierter ist das nicht.
Noch Fragen? Bitte scheut Euch nicht, sie mir als Kommentar oder Mail vor die Füße zu werfen.
Eine dringende Bitte: Vergesst classful addressing!
... und wenn Ihr es noch nicht könnt, lernt es bitte erst gar nicht.
Die allermeisten Leerbücher (sic!) zum Thema IP erklären Euch zuerst, wie man aus den ersten beiden Bits der
IPv4-Adresse die Netzklasse (A, B oder C, oft vergessend das die Netzklassen eigentlich bis E gehen) und die
Default-Netzmaske errechnet und wie man diese Netze mit Hilfe von Mechanismen namens Subnetting und Supernetting
verkleinern oder vergrößern kann.
Die besseren dieser Leerbücher erklären Euch danach auch, dass diese Art der Adressierung seit den mittleren
1990er-Jahren durch das Classless Inter-Domain Routing (CIDR) ersetzt wurde und heute jenseits historischer Literatur
und Prüfungen (“wie lautet die Netzmaske für 85.214.68.41”) keinerlei Relevanz mehr hat.
Ich dagegen würde diese Altlast am liebsten komplett ignorieren und Euch erzählen, wie IP heute funktioniert und
Euch mit historischem Ballast in Ruhe lassen. So ganz geht das allerdings nicht, denn sonst denkt Ihr immer noch in
Ballast und Altlast und wisst nicht, welchen Teil Eures wertvollen und in mühevoller Kleinarbeit erarbeiteten Wissens
ihr am besten ganz schnell wieder vergesst.
So gibt es auch heute immer noch Leute, die alles, was mit einer /24-Netzmaske daherkommt als
“Class-C-Netz” bezeichnen, gerne damit begründend, dass es einfacher auszusprechen ist. Leider ist es
außerdem noch in dieser Allgemeinheit falsch. Denn, Class-C-Netze sind nur Netze mit einer /24-Netzmaske, deren erstes
Oktett zwischen 192 und 223 liegt. Alle anderen /24-Netze, so z.B. 172.16.0.0/24, sind Subnetze von Class-A- oder
Class-B-Netzen, die zufällig dieselbe Netzmaske haben wie ein Class-C-Netz.
Wer heute noch von Netzklassen spricht, hat es bestenfalls nicht verstanden oder ist schlimmstenfalls jemand, der
sich nicht um exakte Ausdrucksweise bemüht und die damit entstehenden Mißverständnisse billigend in kauf nimmt.
/ignore
Der Einfachheit halber und um das Niveau niedrig zu halten, habe ich die meisten “interessanten” Dinge
beim IP-Routing in diesem Artikel ignoriert.
- dynamisches Routing
- Policy Routing
- Hosts mit mehreren Routingtabellen
- mehrere IP-Adressen pro Interface
- die Komplexitäts-Zwischenstufe mit mehreren Gateways mit unterschiedlichen Netzen dahinter, aber nur einem
Interface
- “krumme” Netzmasken
- security
- link local addressing
Auch wenn ich mich in diesem Artikel hauptsächlich um IPv4 kümmere, habe ich mich bemüht, die Dinge so zu
formulieren, dass sie mit minimaler Abstraktion auch für IPv6 anwendbar sind.