Filtern nach HTTP-Methoden in IPv6-Paketen mit tcpdump

Filtern nach HTTP-Methoden in IPv6-Paketen mit tcpdump

Ich verwende „tcpdump“, um den Datenverkehr zu erfassen, und möchte nach HTTP-Methoden filtern. Wenn ich IPv4-Pakete habe, verwende ich: tcpdump -s 0 -A 'tcp[((tcp[12:1] & 0xf0) >> 2):4] = 0x47455420'Zum Filtern nach HTTP-GET-Paketen.

Leider tcp[]funktioniert der Filter nicht bei IPv6-Paketen. Laut der Dokumentation

Arithmetische Ausdrücke für Transportschicht-Header wie tcp[0]funktionieren bei IPv6-Paketen nicht.

Daher suche ich nach einer anderen Möglichkeit, mit tcpdump nur HTTP-Methoden für IPv6-Verkehr zu filtern.

Ich habe versucht, nach einer Lösung zu suchen, aber es scheint, als ob sie eine Verwendung von grep beinhalten, die für meine Bedürfnisse nicht geeignet ist, da ich den gesamten gefilterten Datenverkehr direkt in eine PCAP-Datei ausgeben möchte

Antwort1

Einschränkungen tcpdumpbei IPv6 ab Version 4.99.x

Um für IPv4 den Payload-Offset im Paket zu erhalten, kann man den Payload-Offset mehr oder weniger einfach berechnen, indem man verwendetDas humanitäre Völkerrecht von IPv4+ TCP-Datenoffsetum auch IPv4-Optionen und TCP-Optionen zu berücksichtigen. Dies ist einfach genug, um intcpdumpdirekt, wenn es den BPF-Bytecode-Filter generiert (einige BPF-Dokumentationen sind verfügbar, zum BeispielDort).

Bei IPv6 kann es stattdessen eine variable (möglicherweise zwischen 0 und 9) Anzahl von Erweiterungsheadern zwischen dem festen Header und dem oberen Header geben. Das würde bedeuten, Code für möglicherweise 10 Fälle (0, 1, 2, ... 9 Erweiterungsheader) einzuschließen, um den Payload-Offset in einem Paket zu finden, vorausgesetzt, es gibt keine zusätzlichen Besonderheiten für bestimmte Fälle und es wird auch nicht versucht, einen Schutz vor fehlerhaften Paketen zu haben (was zu falsch positiven Treffern führen könnte): Ich kann nur annehmen, dass dies aufgrund der Komplexität und der mangelnden Bereitschaft, eine fehlerhafte Implementierung bereitzustellen, die solche Header ignoriert, nicht implementiert wurde.

Sogar ein einfacher Test wie dieser ip6 and tcp dst port 80berücksichtigt keine Erweiterungsheader, wie der unten generierte BPF-Code zeigt:

$ tcpdump --version 
tcpdump version 4.99.3
libpcap version 1.10.3 (with TPACKET_V3)
OpenSSL 3.0.9 30 May 2023
$ tcpdump -y EN10MB -d ip6 and tcp dst port 80
(000) ldh      [12]
(001) jeq      #0x86dd          jt 2    jf 7
(002) ldb      [20]
(003) jeq      #0x6             jt 4    jf 7
(004) ldh      [56]
(005) jeq      #0x50            jt 6    jf 7
(006) ret      #262144
(007) ret      #0

Daher kann es sein, dass Sie Verkehr verpassen.

Ab tcpdump 4.99.x scheint die einzige Stelle, an der eine angemessene Handhabung der IPv6-Erweiterungsheader vorhanden ist, am Ende der Manpage dokumentiert zu sein:

ip6 protosollte der Header-Kette folgen, tut dies aber derzeit nicht. ip6 protochainFür dieses Verhalten ist eine Angabe vorgesehen.

Tatsächlich ist tcpdump ab 4.99.x derzeit ip6 and tcpgleichwertig mit ip6 proto 6(sie erzeugen den gleichen Bytecode):

$ tcpdump -y EN10MB -d ip6 and tcp
(000) ldh      [12]
(001) jeq      #0x86dd          jt 2    jf 8
(002) ldb      [20]
(003) jeq      #0x6             jt 7    jf 4
(004) jeq      #0x2c            jt 5    jf 8
(005) ldb      [54]
(006) jeq      #0x6             jt 7    jf 8
(007) ret      #262144
(008) ret      #0

while ip6 protochain 6führt eine weitaus gründlichere Prüfung durch und ist das, was bei jedem Test erwartet werden sollte, an dem eine obere Schicht (letzter Transportheader) wie TCP beteiligt ist:

$ tcpdump -y EN10MB -d ip6 protochain 6
(000) ldh      [12]
(001) jeq      #0x86dd          jt 2    jf 35
(002) ldb      [20]
(003) ldx      #0x28
(004) jeq      #0x6             jt 32   jf 5
(005) jeq      #0x3b            jt 32   jf 6
(006) jeq      #0x0             jt 10   jf 7
(007) jeq      #0x3c            jt 10   jf 8
(008) jeq      #0x2b            jt 10   jf 9
(009) jeq      #0x2c            jt 10   jf 19
(010) ldb      [x + 14]
(011) st       M[0]
(012) ldb      [x + 15]
(013) add      #1
(014) mul      #8
(015) add      x
(016) tax      
(017) ld       M[0]
(018) ja       4
(019) jeq      #0x33            jt 20   jf 32
(020) txa      
(021) ldb      [x + 14]
(022) st       M[0]
(023) txa      
(024) add      #1
(025) tax      
(026) ldb      [x + 14]
(027) add      #2
(028) mul      #4
(029) tax      
(030) ld       M[0]
(031) ja       4
(032) add      #0
(033) jeq      #0x6             jt 34   jf 35
(034) ret      #262144
(035) ret      #0

Über den 4 Tests einschließlich jt 10und Zeilen zwischen (10) und (018) ja 4Schleife über 4 der spezifischen IPv6-Erweiterungsheader, um sie zu überspringen, während mit IPSec AH (19)umgegangen (31)wird. Ich wüsste nicht, wie man anderswo solchen Code mit dem generieren könntetcpdumpSprache (anstatt beispielsweise direktBPFCode). Die Verwendung ip6 protochain 6 and ip6 and tcp dst port 80beginnt einfach von vorne oder schlimmer noch, anstatt den gerade erhaltenen TCP-Header zu nutzen.

Die gleiche Art von Problem wird in verschiedenen Netzwerkeinrichtungen und Tools für Linux beschrieben. Beispiel:tc u32erzählt:

icmp_code VAL_MASK_8

Gehen Sie von einem Next-Header-Protokoll vom Typ ICMP oder IPv6-ICMP aus und passen Sie die Feldwerte für „Typ“ oder „Code“ an.Dies ist gefährlich, da der Code davon ausgehtminimale Headergröße für IPv4 undFehlende Erweiterungsheader für IPv6.

Dabei wird noch nicht einmal berücksichtigt, dass speziell bei HTTP bei Wiederverwendung der Verbindung die nächste HTTP-Abfrage möglicherweise nicht einmal am Anfang einer Paketgrenze steht, und dass eine solche als Daten statt als Abfrage eingebettete Abfrage möglicherweise übereinstimmt, wenn solche Daten am Anfang der Paketgrenze erscheinen.

Testen Sie den Fall „0 Extension-Header“ mit tcpdumpVersion 4.99.x

Hier ist der Test mit 0 Erweiterungsheadern, also auf der gleichen Ebene wietcpdumptut dies derzeit, mit minimaler Überprüfung:

tcpdump -n -s 0 -A 'ip6[6] == 6 and ( ip6[4:2] - ((ip6[52] & 0xf0) >> 2) >= 4 ) and ip6[40 + ((ip6[52] & 0xf0) >> 2) :4] == 0x47455420'

Dies kann wie folgt dokumentiert werden (immer noch nur für den Fall des 0-Extension-Headers, bei dem der TCP-Header immer an Position 40 beginnt):

  • Der nächste Header ist TCP

    ip6[6] == 6
    
  • IPv6Nutzlastlänge:

    ip6[4:2]
    
  • TCPDatenoffset (feste IPv6-Größe von 40 + 12 = 52) (und entsprechende Anpassung, um Bytes zu erhalten)

    (ip6[52] & 0xf0) >> 2
    
  • TCP-Nutzlastlänge = IPv6-Nutzlastlänge – TCP-Datenoffset

  • Testen Sie, ob mindestens 4 Byte TCP-Nutzlast für mindestens die Länge von „GET“ vorhanden sind.

    ip6[4:2] - ((ip6[52] & 0xf0) >> 2)  >= 4
    
  • Die in ASCII/UTF-8 kodierte 4-Byte-Zeichenfolge „GET“ kann mit dem 4-Byte-Wert 0x47455420 dargestellt werden.

  • Der TCP-Nutzlastoffset ist die feste IPv6-Headerlänge (40) + der TCP-Datenoffset

    40 + ((ip6[52] & 0xf0) >> 2)
    
  • Testen Sie, ob das erste 4-Byte-Wort ab der festen IPv6-Headerlänge (40) + Datenoffset dem Wert für die Zeichenfolge „GET“ entspricht.

    ip6[40 + ((ip6[52] & 0xf0) >> 2) :4] = 0x47455420
    

Nftablesmit Linux-Kernel >= 5.15.54 +tcpdump

Ich schlage eine einfache alternative Methode nur für Linux vor, dieNftablesund erfordert einen ausreichend aktuellen Kernel (Linux-Kernel-Version>= 5.15.54zurückportiert von5.16) sowieNftables>= 1.0.1zur Unterstützung der@ih(innerer Header/Nutzlast) Rohnutzlast, und nicht nur @th(Transportheader), weilNftables@thselbst ist viel zu eingeschränkt, um beliebige Verarbeitungen auf sinnvolle Weise durchzuführen .

Das IPv6-Datagramm wurde bereits analysiert, einschließlich aller IPv6-Erweiterungsheader, und sowohl @th- als auch @in-Zeiger sind bereits verfügbar fürNftables: Es ist keine weitere Verarbeitung erforderlich, um alle Fälle zu erhalten. Ich verlasse mich aufNftableseine Prüfung scheitern zu lassen, wenn das Paket zu kurz ist, ohne die tatsächliche TCP-Nutzlastgröße berechnen zu müssen (im Gegensatz zutcpdumpund BPF,Nftableskann keine Subtraktionen durchführen, daher gibt es keine Möglichkeit, die Größe richtig zu überprüfen).

DerNftablesDas folgende Beispiel versucht, das genaue Beispiel des OP nachzuahmen, kann dies aber nicht immer in allen Details ohne gewisse Anpassungen. Keine Richtung oder Port, erfasst eingehende Pakete vor NAT und ausgehende Pakete nach NAT (daher die gewählten Hooks und Prioritäten). Das ausgewählte Paket wird schließlichgesendet an dieAbonnierenEinrichtung:

In der zweiten Form der Anrufung (wennnflog_gruppeangegeben ist), übergibt der Linux-Kernel das Paket an nfnetlink_log, das das Protokoll über einen Netlink-Socket an die angegebene Gruppe sendet. Ein Userspace-Prozess kann die Gruppe abonnieren, um die Protokolle zu erhalten [...]

table ip6 special_log
delete table ip6 special_log

table ip6 special_log {
        chain log_to_nflog {
                log group 4242
        }

        chain ih_filter {
                meta l4proto tcp @ih,0,32 0x47455420 counter jump log_to_nflog
        }

        chain c_ingress {
                type filter hook prerouting priority -150; policy accept;
                jump ih_filter
        }
        chain c_egress {
                type filter hook postrouting priority 150; policy accept;
                jump ih_filter
        }
}

Unter LinuxAbonnierenDie Einrichtung ist als Pseudoschnittstelle verfügbar für (libpcapUnd)tcpdump:

# tcpdump -D |grep nflog
12.nflog (Linux netfilter log (NFLOG) interface) [none]

Die vonNftableskann daher wie folgt angezeigt werden (unter Wiederverwendung der gleichen NFLOG-Gruppe: 4242):

tcpdump -n -s 0 -A -i nflog:4242

Vorbehalt: Es gibt mehr Latenz als bei einer direkten Aufnahme.

Hinweis: Richtige Handhabung durchNftableseines Falles mit einem Erweiterungsheader wurde tatsächlich mit UDP (anstatt TCP) und fragmentierten Paketen (verarbeitet durch denFragmentkopfzeile) verwenden socat(in einem separaten Netzwerk-Namespace, um nf_defrag_ipv6ein Eingreifen zu verhindern), weil es viel einfacher ist, mit UDP ein fragmentiertes Paket zu generieren als mit TCP und ich keine andere Methode gefunden habe, um irgendwo einen Erweiterungsheader zu haben.

verwandte Informationen