Linux Source Routing, starkes Endsystemmodell / starkes Hostmodell?

11

Kann ein Multihomed-Linux-Computer ein echtes Strong ES-Modell implementieren ?

Spezifischer Anwendungsfall

Ich habe ein System mit fünf verschiedenen Schnittstellen, die jeweils mit demselben Subnetz verbunden sind, also dasselbe Gateway zum Internet.

  • Ich möchte jede Schnittstelle separat an demselben Port abhören und sicherstellen, dass Pakete immer an derselben Schnittstelle ausgehen, an der sie eingegangen sind, und sicherstellen, dass Pakete, die versuchen, an die "falsche" Schnittstelle zu gelangen, verworfen werden.
  • Ich möchte in der Lage sein, an jede Schnittstelle zu binden und ausgehende Verbindungen zu Internetzielen herzustellen, die immer von derselben Quell-IP stammen, an die ich gebunden bin. Zum Beispiel,
    curl --interface interface_ip http://ipecho.net/plain
    sollte immer die gleiche IP-Adresse anzeigen, an die ich gebunden bin --interface.
  • Statische Routen können aufgrund der Verwendung von DHCP auf einer dieser Schnittstellen problematisch sein.

RFC 1122

Aus RFC 1122 - Anforderungen für Internet-Hosts - Kommunikationsschichten, Abschnitt 3.3.4.2 - Multihoming-Anforderungen :

Internet-Host-Implementierer haben zwei verschiedene konzeptionelle Modelle für Multihoming verwendet, die in der folgenden Diskussion kurz zusammengefasst werden. Dieses Dokument bezieht sich nicht darauf, welches Modell bevorzugt wird. Jeder scheint einen Platz zu haben. Diese Ambivalenz spiegelt sich in den optionalen Punkten (A) und (B) wider.

  •   Starkes ES-Modell

      Das Strong ES-Modell (End System, dh Host) betont die Unterscheidung zwischen Host und Gateway (ES / IS) und würde daher in den obigen Punkten (A) und (B) MUSS anstelle von MAI verwenden. Es neigt dazu, einen Multihomed-Host als eine Reihe logischer Hosts innerhalb desselben physischen Hosts zu modellieren.

      In Bezug auf (A) stellen Befürworter des Strong ES-Modells fest, dass automatische Internet-Routing-Mechanismen ein Datagramm nicht an eine physische Schnittstelle weiterleiten konnten, die nicht der Zieladresse entsprach.

      Unter dem Strong ES-Modell ist die Routenberechnung für ein ausgehendes Datagramm die Zuordnung:

         route(src IP addr, dest IP addr, TOS) -> gateway
    

    Hier wird die Quelladresse als Parameter angegeben, um ein Gateway auszuwählen, das direkt über die entsprechende physikalische Schnittstelle erreichbar ist. Beachten Sie, dass dieses Modell logischerweise erfordert, dass im Allgemeinen mindestens ein Standardgateway und vorzugsweise mehrere Standardwerte für jede IP-Quelladresse vorhanden sind.


  •   Schwaches ES-Modell

      Diese Ansicht hebt die ES / IS-Unterscheidung hervor und würde daher in den Punkten (A) und (B) MUSS NICHT für MAI ersetzen. Dieses Modell ist möglicherweise das natürlichere für Hosts, die Gateway-Routing-Protokolle abhören, und ist für Hosts mit eingebetteter Gateway-Funktionalität erforderlich.

      Das schwache ES-Modell kann dazu führen, dass der Umleitungsmechanismus fehlschlägt. Wenn ein Datagramm über eine physische Schnittstelle gesendet wird, die nicht der Zieladresse entspricht, erkennt das First-Hop-Gateway nicht, wann eine Umleitung gesendet werden muss. Wenn der Host hingegen über eingebettete Gateway-Funktionen verfügt, verfügt er über Routing-Informationen, ohne Redirects abzuhören.

      Im Weak ES-Modell ist die Routenberechnung für ein ausgehendes Datagramm die Zuordnung:

         route(dest IP addr, TOS) -> gateway, interface
    

  • Linux ist standardmäßig ein schwaches ES-Modell, während FreeBSD und andere Unix-Varianten als starke ES-Systeme fungieren. Gibt es eine Möglichkeit, es eher wie ein starkes ES-System zu verhalten?

    Welche sysctlKonfiguration oder Konfiguration zur Kompilierungszeit müsste festgelegt werden, damit sie sich standardmäßig wie ein Strong ES verhält, ohne spezifische Routing-Regeln für eine neue Schnittstelle hinzuzufügen, die Sie hinzufügen? Ich weiß, dass wir eine strikte Filterung der Quellrouten durchführen können net.ipv4.conf.default.rp_filter = 1, aber es scheint viel mehr zu geben. Wie kann ich standardmäßig quellenbasiertes Routing durchführen?

    Wille
    quelle
    1
    Warum für die engen Wähler? Dies scheint mir direkt zum Thema zu gehören. Wenn nicht, wo wäre es zum Thema?
    Will

    Antworten:

    8

    Das Hinzufügen von Firewall-Regeln reicht für diese nicht aus. Sie möchten, dass das System den Datenverkehr so ​​weiterleitet, als ob es zwei unabhängige Systeme wären, die zufällig dieselbe Hardware und dieselben Prozesse gemeinsam nutzen: Genau das ist das Strong ES-Modell.

    Wenn Sie unter Linux ein starkes ES-Modell anstreben, benötigen Sie zunächst die folgenden sysctl-Einstellungen:

    net.ipv4.conf.all.arp_filter=1 
    net.ipv4.conf.all.arp_ignore=1 # or even 2
    net.ipv4.conf.all.arp_announce=2
    

    Durch diese Einstellungen verhält sich ARP beim Strong ES-Modell entsprechend, dh wenn eine ARP-Anforderung empfangen wird, antwortet nur die Schnittstelle mit der genau angeforderten Adresse, und nur dann, wenn tatsächlich Datenverkehr an die Ursprungsadresse über diese spezifische Adresse gesendet wird Schnittstelle.

    Da Sie dann fünf Schnittstellen haben, die sich in Bezug auf das Routing unterschiedlich verhalten sollen, müssen Sie fünf benutzerdefinierte Routing-Tabellen einrichten. Sie könnten Zahlen verwenden, um sie zu identifizieren, aber im Allgemeinen ist es klarer, Namen für sie anzugeben. Wählen Sie also Zahlen für jeden von ihnen zwischen 1 und 252 und einige geeignete Namen. (Die Nummern 0, 253, 254 und 255 sind reserviert.)

    Nehmen wir zum Beispiel 100 = rtable0, 101 = rtable1, 102 = rtable2, 103 = rtable3 und 104 = rtable4. Fügen Sie diese Nummern und Namen am Ende der /etc/iproute2/rt_tablesDatei hinzu:

    # ...default stuff above...
    100    rtable0
    101    rtable1
    102    rtable2
    103    rtable3
    104    rtable4
    

    Füllen Sie dann jede benutzerdefinierte Routing-Tabelle mit einem minimalen Satz von Routeneinträgen, die für jede Schnittstelle geeignet sind. (Ich ersetze tatsächliche Werte durch hoffentlich beschreibend benannte Umgebungsvariablennamen.)

    ip route add $ETH0_NET dev eth0 proto static src $ETH0_IP table rtable0
    ip route add default via $ETH0_GW dev eth0 proto static src $ETH0_IP table rtable0
    
    ip route add $ETH1_NET dev eth1 proto static src $ETH1_IP table rtable1
    ip route add default via $ETH1_GW dev eth1 proto static src $ETH1_IP table rtable1
    
    # ... and so on, for all 5 interfaces
    

    Fügen Sie abschließend erweiterte Routing-Regeln hinzu, die die Quelladresse jedes Pakets überprüfen, und wählen Sie die Routing-Tabelle aus, die entsprechend verwendet werden soll:

    ip rule add from $ETH0_IP table rtable0
    ip rule add from $ETH1_IP table rtable1
    #...
    

    Um all diese Konfigurationen beim Neustart dauerhaft zu erhalten, müssen Sie möglicherweise benutzerdefinierte Startskripte (oder möglicherweise ifup-preoder ifup-postSkripte) schreiben, die den Konventionen Ihrer Linux-Distribution entsprechen.

    Für eine zusätzliche Versicherung können Sie iptables-Regeln pro Schnittstelle hinzufügen, um eingehende Pakete, die möglicherweise auf der falschen Schnittstelle empfangen werden, stillschweigend zu verwerfen. Wenn alles in Ordnung ist, sollten die Paketzahlen für diese Nullen bleiben: Wenn sie zunehmen, haben Sie möglicherweise etwas in der Konfiguration übersehen.

    iptables -A INPUT -m addrtype --dst-type UNICAST -i eth0 ! -d $ETH0_IP -j DROP
    iptables -A INPUT -m addrtype --dst-type UNICAST -i eth1 ! -d $ETH1_IP -j DROP
    # ... and so on for each interface
    

    Hinweis: Ich habe einmal ein solches Setup implementiert, das auf einer alten Internetdiskussion von Rick Jones und anderen Netzwerkgurus basiert. Sie sagten umschrieben: "Obwohl all dies eindeutig notwendig ist , um ein starkes Host-Modell-Verhalten unter Linux zu erreichen, kann ich nicht garantieren, dass es für alle möglichen Anwendungsfälle ausreicht ." Es hat bei mir einwandfrei funktioniert; Es kann für Sie ausreichen oder auch nicht, je nachdem, wofür Sie es verwenden werden.

    Warnung: Stellen Sie sicher, dass Sie beim Einrichten dieser Konfiguration über einen lokalen oder Remote-Konsolenzugriff auf das System verfügen. Es ist äußerst wahrscheinlich, dass diese Einrichtung Ihren Netzwerkzugriff vollständig durcheinander bringt, solange sie nur zur Hälfte abgeschlossen ist.

    Während es möglich wäre, N Schnittstellen nur mit (N-1) benutzerdefinierten Routing-Tabellen einzurichten, ist es meine persönliche Präferenz, die gesamte Routing-Konfiguration bei Verwendung des erweiterten Routings in benutzerdefinierte Tabellen zu verschieben. Wenn das System im Wesentlichen leer ist route -noder ip route showim Wesentlichen leer ist, ist dies ein sehr großer Hinweis darauf, dass etwas ganz Besonderes vor sich geht. Als ich ein solches System einrichtete, richtete ich jedoch auch einen permanenten Hinweis ein, dass das /etc/motderweiterte Routing in Kraft ist und wo sich die Skripte befinden, die es eingerichtet haben.

    telcoM
    quelle
    Wäre es möglich und / oder nützlich, Netzwerk-Namespaces zu verwenden, um dies (teilweise) zu ersetzen oder "stärker" zu machen?
    Jörg W Mittag
    1
    Das wäre eine subtil andere Sache. Ein starkes Host-Modell bedeutet im Wesentlichen nur "keine Abkürzungen": Eine Antwort auf eine eingehende Verbindung wird über dieselbe Schnittstelle gesendet, über die die Verbindung eingegangen ist, obwohl die Routing-Tabelle möglicherweise angibt, dass es eine direktere Route über eine andere Schnittstelle geben könnte - und Eine Verbindung wird nur auf der Schnittstelle akzeptiert, die tatsächlich die Ziel-IP-Adresse hat. Netzwerk-Namespaces erreichen möglicherweise dasselbe, jedoch auf Kosten der Duplizierung von Serviceprozessen für jeden Namespace.
    TelcoM
    Anstatt mehrere iptablesBefehle auszugeben, kann man diese magischen Nftables mit einem Liner verwenden nft add rule inet filter input fib daddr . iif type != { local, broadcast, multicast } drop. Dies ist nicht wirklich das Thema der ursprünglichen Frage, dachte, es ging um das Gateway, dh die Ausgabekette
    ZAB
    1

    Es gibt eine weitere Option, die mehr Kontrolle über die ARP-Behandlung ermöglicht. Schau es dir an arp_ignore.

    Hauke ​​Laging
    quelle
    Vielen Dank! Aber das hätte nicht viel mit dem eigentlichen Quell-Routing von Paketen zu tun, oder?
    Will
    Bei @Will arp_filtergeht es um Quellrouting . arp_ignoregeht es nur um Quell- und Zieladressen.
    Hauke ​​Laging
    Ah, verstanden! So eine Kombination aus arp_filter, arp_ignoreund rp_filterkonnte den Trick tun? Im Idealfall möchte ich, dass sich jede Schnittstelle so verhält, als ob sie sich auf verschiedenen Computern befindet, und immer nur über dieselbe Schnittstelle antwortet, auf der ein Paket eingegangen ist.
    Will
    @Will Hast du es versucht arp_filter, macht es nicht was du willst? Wenn ja, fügen Sie Ihrer Frage einige Details zur Situation hinzu. In Ihrem letzten Kommentar verwechseln Sie die Perspektive: Bei ARP geht es darum, wo ein Paket eingeht. Beim Routing geht es darum, wo es ausgeht. Was Sie wahrscheinlich meinen, ist, dass Sie möchten, dass Pakete nur auf diesen Schnittstellen akzeptiert werden, über die die Antwort gesendet wird. Sollte arp_filterdas aber tun.
    Hauke ​​Laging
    1
    @ Will Oh, ich habe deine Frage falsch verstanden. Ich habe gesehen, arp_filteraber du hast es erwähnt rp_filter.
    Hauke ​​Laging