Tcpdump zeigt einen anderen Umleitungsport an, nachdem die REDIRECT-Regel in iptables hinzugefügt wurde

Tcpdump zeigt einen anderen Umleitungsport an, nachdem die REDIRECT-Regel in iptables hinzugefügt wurde

Ich versuche, den Client-Verkehr auf den NodePort eines Kubernetes-Clusters umzuleiten, der auf lauscht 192.168.1.100.30000.

Der Client muss eine Anfrage stellen, 192.168.1.100.8000daher habe ich die folgende REDIRECT-Regel in iptables hinzugefügt:

iptables -t nat -I PREROUTING -p tcp --dst 192.168.1.100 --dport 8000 -j REDIRECT --to-port 30000

Ich führe dann einen Curl aus 192.168.1.100:8000, sehe jedoch im TCPdump einen anderen Port:

# tcpdump -i lo -nnvvv host 192.168.1.100 and port 8000
tcpdump: listening on lo, link-type EN10MB (Ethernet), capture size 262144 bytes
[Interface: lo] 20:39:22.685968 IP (tos 0x0, ttl 64, id 20590, offset 0, flags [DF], proto TCP (6), length 40)
[Interface: lo]     192.168.1.100.8000 > 192.168.1.100.49816: Flags [R.], cksum 0xacda (correct), seq 0, ack 3840205844, win 0, length 0
[Interface: lo] 20:39:37.519256 IP (tos 0x0, ttl 64, id 34221, offset 0, flags [DF], proto TCP (6), length 40)

Ich würde erwarten, dass der TCPdump etwas wie

192.168.1.100.8000 > 192.168.1.100.30000

Es wird jedoch ein Fehler „Verbindung abgelehnt“ angezeigt und verursacht diesen, da kein Prozess aufgeführt ist 192.168.1.100.49816.

192.168.1.100.8000 > 192.168.1.100.49816

Ich verwende eine Testumgebung und habe daher keinen Zugriff auf Remote-Geräte. Deshalb verwende ich curlzum Testen den REDIRECT-Pfad von iptables.

Gibt es einen Grund, warum das Hinzufügen einer REDIRECT-Regel dazu führt, dass tcpdump den Datenverkehr an einen anderen Port als den angegebenen umleitet?

Bearbeiten:

Nach dem @AB-Vorschlag wurde die folgende OUTPUT-Regel hinzugefügt:

iptables -t nat -I OUTPUT -d 192.168.1.100 -p tcp --dport 8000 -j REDIRECT --to-port 30000

und curl fährt fort, die Paketanzahl für die OUTPUT-Kette steigt an (das Paket der PREROUTING REDIRECT-Kette stieg jedoch nicht an):

2       10   600 REDIRECT   tcp  --  *      *       0.0.0.0/0            192.168.1.100         tcp dpt:8000 redir ports 30000

Es wird jedoch die folgende Fehlermeldung angezeigt:

# curl -vk https://192.168.1.100:8000/v1/api
* About to connect() to 192.168.1.100 port 8000 (#0)
*   Trying 192.168.1.100...
* Connected to 192.168.1.100 (192.168.1.100) port 8000 (#0)
* Initializing NSS with certpath: sql:/etc/pki/nssdb
* NSS error -12263 (SSL_ERROR_RX_RECORD_TOO_LONG)
* SSL received a record that exceeded the maximum permissible length.
* Closing connection 0
curl: (35) SSL received a record that exceeded the maximum permissible length.

Habe außerdem versucht, ein Remotesystem-Netz hinzuzufügen. Dieses Mal erhöht sich die Paketanzahl der PREROUTING REDIRECT CHAIN ​​nach der Ausführung remotesystem curl ...(die OUTPUT CHAIN ​​erhöht sich jedoch nicht):

2       34  2040 REDIRECT   tcp  --  *      *       0.0.0.0/0            172.16.128.1         tcp dpt:8000 redir ports 30000

Fehler:

# ip netns exec remotesystem curl -vk https://192.168.1.100:8000/v1/api
* About to connect() to 192.168.1.100 port 8000 (#0)
*   Trying 192.168.1.100...
* Connection timed out
* Failed connect to 192.168.1.100:8000; Connection timed out
* Closing connection 0
curl: (7) Failed connect to 192.168.1.100:8000; Connection timed out

Antwort1

Um es klarzustellen: Der Test des OP wird vom System 192.168.1.100 zu sich selbst durchgeführt, nicht von einem Remote-System, und das ist die Ursache des Problems. Der Port wurde in diesem Fall nicht geändert, da keine NAT-Regel übereinstimmte, während er gepasst hätte, wenn er von einem Remote-System ausgeführt worden wäre.

Das folgende Schema zeigt, in welcher Reihenfolge die Operationen an einem Paket ausgeführt werden:

Paketfluss in Netfilter und allgemeinem Networking

Der Grund liegt in der Funktionsweise von NAT unter Linux:iptablessieht ein Paket in der natTabelle nur für das erste Paket eines neuen Conntrack-Flows (das sich somit im Status NEU befindet).

Diese Regel funktioniert einwandfrei, wenn sie von einem Remote-System aus erfolgt. In diesem Fall ist das erste angezeigte Paket ein eingehendes Paket:

to port 8000 --> AF_PACKET (tcpdump) --> conntrack --> nat/PREROUTING (iptables REDIRECT): to port 30000
--> routing decision --> ... --> local process receiving on port 30000

Bei allen folgenden Paketen im gleichen Fluss wird conntrack die Portänderung (oder Portumkehr für Antworten) direkt handhaben und alle iptables-Regeln in der natTabelle überspringen (wie im Schema geschrieben: natTabelle wird nur für NEWVerbindungen konsultiert). Daher (unter Überspringen des Antwortpaketteils) wird das nächste eingehende Paket stattdessen folgendes durchlaufen:

to port 8000 --> AF_PACKET (tcpdump) --> conntrack: to port 30000
--> routing decision --> ... --> local process receiving on port 30000

Bei einem Test des Systems selbst ist das erste Paket kein eingehendes Paket, sondern ein ausgehendes Paket. Dies geschieht stattdessen über die ausgehende loSchnittstelle:

local process client curl --> routing decision --> conntrack --> nat/OUTPUT (no rule here)
--> reroute check --> AF_PACKET (tcpdump) --> to port 8000

Und jetzt wird dieses Paket auf der Schnittstelle zurückgeschleift lo, es erscheint erneut als Paket, das nicht mehr das erste Paket in einer Verbindung ist, also folgt der zweite Fall wie oben: conntrack allein kümmert sich um das NAT und ruft nicht auf nat/PREROUTING. Außer dass es im Schritt davor nicht angewiesen wurde, NAT durchzuführen:

to port 8000 --> AF_PACKET (tcpdump) --> conntrack
--> routing decision --> ... -->nolocal process receiving on port8000

Da auf Port 8000 nichts lauscht, sendet das Betriebssystem ein TCP RST zurück.

Damit dies auf dem lokalen System funktioniert, REDIRECTmuss zusätzlich eine Regel in die Kette eingefügt werden nat/OUTPUT:

iptables -t nat -I OUTPUT -d 192.168.1.100 -p tcp --dport 8000 -j REDIRECT --to-port 30000

Zusätzliche Bemerkungen

  • Wenn der Fall für die Fernverwendung vorgesehen ist, testen Sie nicht vom lokalen System aus: Die vom Test durchlaufenen Regeln sind nicht dieselben. Dadurch spiegelt der Test nicht die Realität wider.

    Verwenden Sie einfach einen Netzwerk-Namespace, um ein Pocket-Remote-System zu erstellen, falls kein anderes System verfügbar ist. Beispiel, das mit einem System funktionieren sollte, das nur die nat/PREROUTINGRegel des OP hat und Folgendes tut curl http://192.168.1.100/(wofür kein DNS erforderlich ist):

    ip netns add remotesystem
    ip link add name vethremote up type veth peer netns remotesystem name eth0
    ip address add 192.0.2.1/24 dev vethremote
    ip -n remotesystem address add 192.0.2.2/24 dev eth0
    ip -n remotesystem link set eth0 up
    ip -n remotesystem route add 192.168.1.100 via 192.0.2.1
    ip netns exec remotesystem curl http://192.168.1.100:8000/
    
  • tcpdumpund NAT

    tcpdumpgeschieht in den AF_PACKETSchritten im obigen Schema: sehr früh für den Eingang und sehr spät für den Ausgang. Das bedeutet, dass im Fall eines Remote-Systems Port 30000 niemals erfasst wird, selbst wenn es funktioniert. Im Fall eines lokalen Systems nat/OUTPUTwird Port 30000 erfasst, sobald die Regel hinzugefügt wurde.

    Vertrauen Sie einfach nicht blind der beim tcpdumpNAT angezeigten Adresse/dem angezeigten Port: Es hängt vom Einzelfall ab und davon, wo die Erfassung stattfindet.

verwandte Informationen