IP-Routing für Anfänger
Als Systemadministrator hat man im Idealfall mit IP-Routing nur dann zu tun, wenn man seinen Systemen eine Defaultroute setzt und dann nie wieder. Mit Wissen auf diesem Niveau kann man jahrelang in unserem Handwerk arbeiten.
Bis es mal nicht tut, oder besondere Anforderungen auch besondere Maßnahmen erfordern. Dann sieht man sofort, wo das Grundwissen fehlt. In diesem Artikel möchte ich eine - hoffentlich minimale - Menge dieses Grundwissens vermitteln. Aufgrund meines fachlichen Fokus beschränke ich mich hier auf Linux; die Theorie dahinter ist aber für alle internettauglichen Betriebssysteme identisch, so dass man sich nur an die verwendeten Tools, ihre Parameter und ihre Ausgabeformate anpassen muss.
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.
Comments
Display comments as Linear | Threaded