-
Notifications
You must be signed in to change notification settings - Fork 912
Description
I'm trying to use BPF in order to filter eth/vlan/ip/tcp headers that are behind a GRE encapsulation protocol.
Consider this example packet:
00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f
0000 7c 91 69 9b d3 6d 10 ef 49 5f b1 e7 08 00 45 00
0010 00 84 00 00 00 00 fd 2f a5 fd 6a e3 9c b5 6a e3
0020 a4 d1 00 00 65 58 CA FE CA FE CA FE CA CA CA CA
0030 CA CA 81 00 00 69 08 00 45 20 00 5a a1 c5 40 00
0040 79 06 77 02 c0 a8 03 60 c0 a8 64 05 c2 27 0d 3d
0050 49 ca eb 16 b7 2c 3e 30 50 18 03 fd f1 66 00 00
0060 17 03 03 00 2d 00 00 00 00 00 01 c2 2b 47 fa 65
0070 d6 eb 3c 72 e4 4c 87 cb 4a 86 7f 87 c7 9f 9d 3b
0080 df f6 93 3f 20 48 5b b6 fc db 61 31 03 95 41 3c
0090 28 f8
If we try something "simple", that only checks for the CA:CA:CA:CA:CA:CA ethernet address, let's say: (protochain GRE && ether host CA:CA:CA:CA:CA:CA)
We'll get the following code:
dumpcap -d -f "(protochain GRE && ether host CA:CA:CA:CA:CA:CA)"
Capturing on 'wlo1'
(000) ldh [12]
(001) jeq #0x800 jt 2 jf 22
(002) ldb [23]
(003) ldxb 4*([14]&0xf)
(004) jeq #0x2f jt 20 jf 5
(005) jeq #0x3b jt 20 jf 6
(006) add #0
(007) jeq #0x33 jt 8 jf 20
(008) txa
(009) ldb [x + 14]
(010) st M[1]
(011) txa
(012) add #1
(013) tax
(014) ldb [x + 14]
(015) add #2
(016) mul #4
(017) tax
(018) ld M[1]
(019) ja 4
(020) add #0
(021) jeq #0x2f jt 56 jf 22
(022) ldh [12]
(023) jeq #0x86dd jt 24 jf 65
(024) ldb [20]
(025) ldx #0x28
(026) jeq #0x2f jt 54 jf 27
(027) jeq #0x3b jt 54 jf 28
(028) jeq #0x0 jt 32 jf 29
(029) jeq #0x3c jt 32 jf 30
(030) jeq #0x2b jt 32 jf 31
(031) jeq #0x2c jt 32 jf 41
(032) ldb [x + 14]
(033) st M[1]
(034) ldb [x + 15]
(035) add #1
(036) mul #8
(037) add x
(038) tax
(039) ld M[1]
(040) ja 26
(041) jeq #0x33 jt 42 jf 54
(042) txa
(043) ldb [x + 14]
(044) st M[1]
(045) txa
(046) add #1
(047) tax
(048) ldb [x + 14]
(049) add #2
(050) mul #4
(051) tax
(052) ld M[1]
(053) ja 26
(054) add #0
(055) jeq #0x2f jt 56 jf 65
(056) ld [8]
(057) jeq #0xcacacaca jt 58 jf 60
(058) ldh [6]
(059) jeq #0xcaca jt 64 jf 60
(060) ld [2]
(061) jeq #0xcacacaca jt 62 jf 65
(062) ldh [0]
(063) jeq #0xcaca jt 64 jf 65
(064) ret #262144
(065) ret #0
This code, unless I'm missing something, will only execute in this order:
(000) ldh [12]
(001) jeq #0x800 jt 2 jf 22 # True!
(002) ldb [23] # 0x17
(003) ldxb 4*([14]&0xf)
(004) jeq #0x2f jt 20 jf 5 # True!
(020) add #0 # do nothing ??
(021) jeq #0x2f jt 56 jf 22 # True again!
(056) ld [8] # Ups, we are not behind GRE header!!
(057) jeq #0xcacacaca jt 58 jf 60 # False :-(
(060) ld [2] # Ups, we are not behind GRE header!!
(061) jeq #0xcacacaca jt 62 jf 65 # False again....
(065) ret #0 # missmatch!
Unless I have missunderstood the behaviour of protochain, it should "virtually move" the packet pointer behind the GRE header, so we can filter there.
I'm really confused and everything I found on the internet says that filter (protochain GRE && ether host CA:CA:CA:CA:CA:CA) should work.
This have been deeply tested on Fedora 37 and replicated on Ubuntu 22
libpcap: 1.10.1Dumpcap (Wireshark) 3.6.8 (Git commit d25900c51508)- Other data that might be interesting:
Running on Linux 5.19.15-301.fc37.x86_64, with Intel(R) Core(TM) i5-8250U CPU @
1.60GHz (with SSE4.2), with 32015 MB of physical memory, with GLib 2.74.0, with
zlib 1.2.12, with libpcap 1.10.1 (with TPACKET_V3), with LC_TYPE=C, binary
plugins supported (0 loaded).
Any help would be welcomed.
Thank you in advance.