Hinweis:
Dieser Blogartikel ist älter als 5 Jahre – die genannten Inhalte sind eventuell überholt.
Manche Server sind mit eigenen Interfaces an mehrere Netze gleichzeitig direkt angeschlossen. Sind diese Netze auch über andere Wege verbunden, können diese Multihomed Networks zu verzwickten Situationen für den Linux-Netzwerk-Stack führen. Im Kernel lässt sich das Verhalten konfigurieren. Nachdem die Voreinstellung seit vielen Jahren relativ lax war, hat CentOS in seinen neusten Versionen die Zügel etwas angezogen.
Die zwei Netze 10.0.1/24 und 10.0.2/24 der Abbildung unten sind jeweils über einen Router miteinander verbunden und enthalten jeweils Clients, die mit Servern kommunizieren möchten. Es gibt Situationen, in denen ein Server mehrere Netzwerkkarten besitzt und jede davon an ein anderes Netz angeschlossen ist. Das ist dann notwendig, wenn der Server auf Broadcast-Meldungen reagieren will, etwa als DHCP-Server.
Solch ein Setup wird auch Multihomed Server genannt: Der Server aus Abbildung 1 hat sein Interface eth1 mit der IP-Adresse 10.0.1.10 und das Interface eth2 mit der IP-Adresse 10.0.2.20 konfiguriert. Das Default-Gateway ist der Router mit seinem Interface 10.0.2.1. Der Router kann zwischen den beiden Netzen hin- und herrouten.
Im Beispiel bootet der eingezeichnete Client neu und fragt in seinem Netzsegment per DHCP nach einer IP-Adresse, die ihm der Server auch für sein Netz zuteilt, etwa 10.0.2.99. Weiterhin teilt der Server auf gleichem Wege eine URL mit, über die der Client weitere Konfigurationen abrufen kann. Diese Adresse lautet beispielsweise , weil der Server diesen Webdienst nur im Netzsegment 10.0.1/24 anbietet. Das ist, so sollte man glauben, ja auch kein Problem für den Client, weil er ja über den Router auch Zugriff auf dieses Netz hat.
Baut der Client nun eine IP-Verbindung von 10.0.2.99 zu 10.0.1.10 auf, passiert Folgendes: Der Client stellt fest, dass die Zieladresse nicht in seinem angeschlossenen Netz 10.0.2/24 liegt. Er muss also die Pakete an den Router senden. Der nimmt sie entgegen und leitet sie in das Zielnetz 10.0.1/24 weiter. Dort erreichen sie auch den Server.
Der Server reagiert jedoch auf neueren CentOS-Systemen nicht und sendet weder Antworten noch Fehlermeldungen. Aus Sicht des Clients gibt es irgendwann einen Timeout und die aufrufende Anwendung bricht ab. Was ist also passiert?
Das Problem liegt im TCP-IP-Stack des Servers, der vor einem Dilemma steht: Der Kernel erhält IP-Pakete mit der Absenderadresse 10.0.2.99 über das Interface eth1. Das passt aber gar nicht so recht in sein Weltbild, denn solche Adressen sollte er eigentlich nur über das Interface eth2 erhalten, immerhin ist das dort direkt angeschlossene Netzwerk 10.0.2/24. Solche Pakete, die über ein unerwartetes Interface den Kernel betreten, nennt der Linux-Kernel Marsianer (engl. martians). Mit der Kernel-Option log_martians kann man sich der Superuser melden lassen, ob solche Vorfälle auftreten:
1 2 3 |
# echo 1 >/proc/sys/net/ipv4/conf/all/log_martians # dmesg | tail -f |
Das bisherige Verhalten des Linux-Kernels war, solche Pakete trotzdem zu aktzeptieren und an die Anwendung weiterzureichen. Wenn diese Antworten schickt, nehmen die Pakete auch den gleichen Weg wieder zurück. Je nach Netzumgebung könnte aber auch sein, dass ein Angreifer versucht, auf diesem Weg Kontakt zum Zielsystem aufzunehmen. Der Linux-Kernel steuert dieses Verhalten über die Option rp_filter, was für Reverse Path Filtering steht. Viele Distributionen haben hier den Wert 0 stehen, der die unerwarteten Pakete trotzdem willkommen heißt. Weil jedoch RFC 3704 von diesem Vorgehen abrät, implementiert CentOS (ebenso wie das korrespondierende Red Hat Enterprise Linux) ab Version die striktere Variante und setzen den Wert 2.
Systemverwalter, die jedoch die im Beispiel skizzierte Architektur nutzen wollen, sollten mit
1 |
# echo 2 > /proc/sys/net/ipv4/conf/all/rp_filter |
den Wert testweise für alle Interfaces setzen oder besser gleich mit dem Eintrag
1 |
# echo "net.ipv4.conf.default.rp_filter = 2" >> /etc/sysctl.conf |
persistent anlegen, sodass die Einstellung nach einem Reboot auch greift. Viel Spaß mit den Antworten an die Marsianer!