packetcap / go-pcap

Packet capture library and tools in native go
Apache License 2.0
26 stars 7 forks source link

Using BPF filter with netmask does not capture any packets. #50

Closed Snshadow closed 6 months ago

Snshadow commented 6 months ago

Using BPF filter with netmask does not capture any packets. In tcpdumps filter with netmask in handled correctly.

test@test:~/GitProject/go-pcap$ sudo tcpdump -i any "net 127.0.0.0/8"
tcpdump: data link type LINUX_SLL2
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on any, link-type LINUX_SLL2 (Linux cooked v2), snapshot length 262144 bytes
10:43:01.006039 lo    In  IP localhost.54190 > localhost.43791: Flags [P.], seq 3506288800:3506288844, ack 401878399, win 14838, options [nop,nop,TS val 3060264020 ecr 3060262360], length 44
10:43:01.006079 lo    In  IP localhost.43791 > localhost.54190: Flags [.], ack 44, win 11256, options [nop,nop,TS val 3060264020 ecr 3060264020], length 0
10:43:01.020768 lo    In  IP localhost.54190 > localhost.43791: Flags [P.], seq 44:89, ack 1, win 14838, options [nop,nop,TS val 3060264035 ecr 3060264020], length 45
10:43:01.020807 lo    In  IP localhost.43791 > localhost.54190: Flags [.], ack 89, win 11256, options [nop,nop,TS val 3060264035 ecr 3060264035], length 0
10:43:01.311493 lo    In  IP localhost.40273 > localhost.40802: Flags [P.], seq 631682537:631682585, ack 3573312487, win 24572, options [nop,nop,TS val 3060264326 ecr 3060262589], length 48
10:43:01.311525 lo    In  IP localhost.40802 > localhost.40273: Flags [.], ack 48, win 22004, options [nop,nop,TS val 3060264326 ecr 3060264326], length 0
^C
6 packets captured
12 packets received by filter
0 packets dropped by kernel

Looking into the test cases in https://github.com/packetcap/go-pcap/blob/master/filter/compile_cases_test.go#L1125, the test from https://github.com/packetcap/go-pcap/blob/master/filter/compile_test.go#L166-L178 passes with "net 192.168.0.0/24" without any issue, making it look like it should work.

Expected Behavior

Actual Behavior

Steps to Reproduce the Problem

  1. Run sample binary pcap with "net 127.0.0.0/8" as parameter and it captures nothing.

Specifications

deitch commented 6 months ago

The test cases are correct for what they do, they test that the instructions for a netmasked net are what are expected. The problem is expectation doesn't seem to work in eBPF, so obviously something subtle is missing.

For example, here are the eBPF instructions for ip net 127.0.0.0

[]golang.org/x/net/bpf.Instruction len: 8, cap: 12, [
        golang.org/x/net/bpf.LoadAbsolute {Off: 12, Size: 2},
        golang.org/x/net/bpf.JumpIf {Cond: JumpEqual (0), Val: 2048, SkipTrue: 0, SkipFalse: 5},
        golang.org/x/net/bpf.LoadAbsolute {Off: 26, Size: 4},
        golang.org/x/net/bpf.JumpIf {Cond: JumpEqual (0), Val: 2130706432, SkipTrue: 2, SkipFalse: 0},
        golang.org/x/net/bpf.LoadAbsolute {Off: 30, Size: 4},
        golang.org/x/net/bpf.JumpIf {Cond: JumpEqual (0), Val: 2130706432, SkipTrue: 0, SkipFalse: 1},
        golang.org/x/net/bpf.RetConstant {Val: 262144},
        golang.org/x/net/bpf.RetConstant {Val: 0},
]

And for ip net 127.0.0.0/24:

[]golang.org/x/net/bpf.Instruction len: 10, cap: 16, [
        golang.org/x/net/bpf.LoadAbsolute {Off: 12, Size: 2},
        golang.org/x/net/bpf.JumpIf {Cond: JumpEqual (0), Val: 2048, SkipTrue: 0, SkipFalse: 7},
        golang.org/x/net/bpf.LoadAbsolute {Off: 26, Size: 4},
        golang.org/x/net/bpf.ALUOpConstant {Op: ALUOpAdd (0), Val: 4294967040},
        golang.org/x/net/bpf.JumpIf {Cond: JumpEqual (0), Val: 2130706432, SkipTrue: 3, SkipFalse: 0},
        golang.org/x/net/bpf.LoadAbsolute {Off: 30, Size: 4},
        golang.org/x/net/bpf.ALUOpConstant {Op: ALUOpAdd (0), Val: 4294967040},
        golang.org/x/net/bpf.JumpIf {Cond: JumpEqual (0), Val: 2130706432, SkipTrue: 0, SkipFalse: 1},
        golang.org/x/net/bpf.RetConstant {Val: 262144},
        golang.org/x/net/bpf.RetConstant {Val: 0},
]

First 3 steps are identical: load the protocol (at offset 12) and see that it matches "IP", then load src IP4 address (at offset 26).

After that it varies:

Both then move on to repeat the same thing with the destination address (offset 30).

I suspect something about the math with the CIDR compare process is off.

The hex of 127.0.0.0 is 0x7f000000. So it should load that in. We then apply the netmask of 0xffffff00, so we should be left with 0x7f000000. And then we compare it.

So it all looks like it should work.

deitch commented 6 months ago

@Snshadow check out the branch in #51, see if it fixes it. My tests show it does.

Snshadow commented 6 months ago

Working as intended for me as well.

with "net 127.0.0.0/8" ``` test@test:~/GitProject/go-pcap$ sudo ./dist/pcap-linux-amd64 "net 127.0.0.0/8" capturing from interface INFO[0000] mmap buffer created at 0x7dce0a1f7000 with size 131072 iface= promiscuous=false snaplen=1600 syscalls=false timeout=0s 0: IP packet From src [127 0 0 1] to dst [127 0 0 1] 0: TCP packet From src port 46656 to dst port 42129 0: PACKET LAYER 0: Ethernet 0: PACKET LAYER 1: IPv4 0: PACKET LAYER 2: TCP 0: PACKET LAYER 3: Payload 0: packet size 0, first bytes [0 0 0 0 0 0 0 0 0 0 0 0 8 0 69 0 0 96 221 110 64 0 64 6 95 39 127 0 0 1 127 0 0 1 182 64 164 145 193 83 182 14 223 248 215 201 128 24 95 252] 1: IP packet From src [127 0 0 1] to dst [127 0 0 1] 1: TCP packet From src port 46656 to dst port 42129 1: PACKET LAYER 0: Ethernet 1: PACKET LAYER 1: IPv4 1: PACKET LAYER 2: TCP 1: PACKET LAYER 3: Payload 1: packet size 0, first bytes [0 0 0 0 0 0 0 0 0 0 0 0 8 0 69 0 0 96 221 110 64 0 64 6 95 39 127 0 0 1 127 0 0 1 182 64 164 145 193 83 182 14 223 248 215 201 128 24 95 252] 2: IP packet From src [127 0 0 1] to dst [127 0 0 1] 2: TCP packet From src port 46656 to dst port 42129 2: PACKET LAYER 0: Ethernet 2: PACKET LAYER 1: IPv4 2: PACKET LAYER 2: TCP 2: PACKET LAYER 3: Payload 2: packet size 0, first bytes [0 0 0 0 0 0 0 0 0 0 0 0 8 0 69 0 0 96 221 111 64 0 64 6 95 38 127 0 0 1 127 0 0 1 182 64 164 145 193 83 182 58 223 248 215 201 128 24 95 252] 3: IP packet From src [127 0 0 1] to dst [127 0 0 1] 3: TCP packet From src port 46656 to dst port 42129 3: PACKET LAYER 0: Ethernet 3: PACKET LAYER 1: IPv4 3: PACKET LAYER 2: TCP 3: PACKET LAYER 3: Payload 3: packet size 0, first bytes [0 0 0 0 0 0 0 0 0 0 0 0 8 0 69 0 0 96 221 111 64 0 64 6 95 38 127 0 0 1 127 0 0 1 182 64 164 145 193 83 182 58 223 248 215 201 128 24 95 252] 4: IP packet From src [127 0 0 1] to dst [127 0 0 1] 4: TCP packet From src port 42129 to dst port 46656 4: PACKET LAYER 0: Ethernet 4: PACKET LAYER 1: IPv4 4: PACKET LAYER 2: TCP 4: packet size 0, first bytes [0 0 0 0 0 0 0 0 0 0 0 0 8 0 69 0 0 52 75 60 64 0 64 6 241 133 127 0 0 1 127 0 0 1 164 145 182 64 223 248 215 201 193 83 182 102 128 16 2 0] 5: IP packet From src [127 0 0 1] to dst [127 0 0 1] 5: TCP packet From src port 42129 to dst port 46656 5: PACKET LAYER 0: Ethernet 5: PACKET LAYER 1: IPv4 5: PACKET LAYER 2: TCP 5: packet size 0, first bytes [0 0 0 0 0 0 0 0 0 0 0 0 8 0 69 0 0 52 75 60 64 0 64 6 241 133 127 0 0 1 127 0 0 1 164 145 182 64 223 248 215 201 193 83 182 102 128 16 2 0] 6: IP packet From src [127 0 0 1] to dst [127 0 0 1] 6: TCP packet From src port 42129 to dst port 46656 6: PACKET LAYER 0: Ethernet 6: PACKET LAYER 1: IPv4 6: PACKET LAYER 2: TCP 6: PACKET LAYER 3: Payload 6: packet size 0, first bytes [0 0 0 0 0 0 0 0 0 0 0 0 8 0 69 0 0 100 75 61 64 0 64 6 241 84 127 0 0 1 127 0 0 1 164 145 182 64 223 248 215 201 193 83 182 102 128 24 2 0] 7: IP packet From src [127 0 0 1] to dst [127 0 0 1] 7: TCP packet From src port 42129 to dst port 46656 7: PACKET LAYER 0: Ethernet 7: PACKET LAYER 1: IPv4 7: PACKET LAYER 2: TCP 7: PACKET LAYER 3: Payload 7: packet size 0, first bytes [0 0 0 0 0 0 0 0 0 0 0 0 8 0 69 0 0 100 75 61 64 0 64 6 241 84 127 0 0 1 127 0 0 1 164 145 182 64 223 248 215 201 193 83 182 102 128 24 2 0] 8: IP packet From src [127 0 0 1] to dst [127 0 0 1] 8: TCP packet From src port 46656 to dst port 42129 8: PACKET LAYER 0: Ethernet 8: PACKET LAYER 1: IPv4 8: PACKET LAYER 2: TCP 8: packet size 0, first bytes [0 0 0 0 0 0 0 0 0 0 0 0 8 0 69 0 0 52 221 112 64 0 64 6 95 81 127 0 0 1 127 0 0 1 182 64 164 145 193 83 182 102 223 248 215 249 128 16 95 252] 9: IP packet From src [127 0 0 1] to dst [127 0 0 1] 9: TCP packet From src port 46656 to dst port 42129 9: PACKET LAYER 0: Ethernet 9: PACKET LAYER 1: IPv4 9: PACKET LAYER 2: TCP 9: packet size 0, first bytes [0 0 0 0 0 0 0 0 0 0 0 0 8 0 69 0 0 52 221 112 64 0 64 6 95 81 127 0 0 1 127 0 0 1 182 64 164 145 193 83 182 102 223 248 215 249 128 16 95 252] ^C ```
with "net 192.168.0.0/16" ``` test@test:~/GitProject/go-pcap$ sudo ./dist/pcap-linux-amd64 "net 192.168.0.0/16" capturing from interface INFO[0000] mmap buffer created at 0x713a9253c000 with size 131072 iface= promiscuous=false snaplen=1600 syscalls=false timeout=0s 0: IP packet From src [192 168 46 130] to dst [192 168 46 2] 0: TCP packet From src port 22 to dst port 62491 0: PACKET LAYER 0: Ethernet 0: PACKET LAYER 1: IPv4 0: PACKET LAYER 2: TCP 0: PACKET LAYER 3: Payload 0: packet size 0, first bytes [0 80 86 232 71 85 0 12 41 168 86 216 8 0 69 8 0 124 14 57 64 0 64 6 78 102 192 168 46 130 192 168 46 2 0 22 244 27 76 30 149 42 61 15 171 224 80 24 255 255] 1: IP packet From src [192 168 46 2] to dst [192 168 46 130] 1: TCP packet From src port 62491 to dst port 22 1: PACKET LAYER 0: Ethernet 1: PACKET LAYER 1: IPv4 1: PACKET LAYER 2: TCP 1: packet size 0, first bytes [0 12 41 168 86 216 0 80 86 232 71 85 8 0 69 0 0 40 18 71 0 0 128 6 74 180 192 168 46 2 192 168 46 130 244 27 0 22 61 15 171 224 76 30 149 126 80 16 250 240] 2: IP packet From src [192 168 46 2] to dst [192 168 46 130] 2: TCP packet From src port 62491 to dst port 22 2: PACKET LAYER 0: Ethernet 2: PACKET LAYER 1: IPv4 2: PACKET LAYER 2: TCP 2: PACKET LAYER 3: Payload 2: packet size 0, first bytes [0 12 41 168 86 216 0 80 86 232 71 85 8 0 69 0 0 124 19 62 0 0 128 6 73 105 192 168 46 2 192 168 46 130 244 27 0 22 61 15 171 224 76 30 149 126 80 24 250 240] 3: IP packet From src [192 168 46 2] to dst [192 168 46 130] 3: TCP packet From src port 62491 to dst port 22 3: PACKET LAYER 0: Ethernet 3: PACKET LAYER 1: IPv4 3: PACKET LAYER 2: TCP 3: PACKET LAYER 3: Payload 3: packet size 0, first bytes [0 12 41 168 86 216 0 80 86 232 71 85 8 0 69 0 0 124 19 66 0 0 128 6 73 101 192 168 46 2 192 168 46 130 244 27 0 22 61 15 172 52 76 30 149 126 80 24 250 240] 4: IP packet From src [192 168 46 130] to dst [192 168 46 2] 4: TCP packet From src port 22 to dst port 62491 4: PACKET LAYER 0: Ethernet 4: PACKET LAYER 1: IPv4 4: PACKET LAYER 2: TCP 4: packet size 0, first bytes [0 80 86 232 71 85 0 12 41 168 86 216 8 0 69 8 0 40 14 58 64 0 64 6 78 185 192 168 46 130 192 168 46 2 0 22 244 27 76 30 149 126 61 15 172 136 80 16 255 255] 5: IP packet From src [192 168 46 130] to dst [192 168 46 2] 5: TCP packet From src port 22 to dst port 62491 5: PACKET LAYER 0: Ethernet 5: PACKET LAYER 1: IPv4 5: PACKET LAYER 2: TCP 5: PACKET LAYER 3: Payload 5: packet size 0, first bytes [0 80 86 232 71 85 0 12 41 168 86 216 8 0 69 8 0 124 14 59 64 0 64 6 78 100 192 168 46 130 192 168 46 2 0 22 244 27 76 30 149 126 61 15 172 136 80 24 255 255] 6: IP packet From src [192 168 46 2] to dst [192 168 46 130] 6: TCP packet From src port 62491 to dst port 22 6: PACKET LAYER 0: Ethernet 6: PACKET LAYER 1: IPv4 6: PACKET LAYER 2: TCP 6: packet size 0, first bytes [0 12 41 168 86 216 0 80 86 232 71 85 8 0 69 0 0 40 19 105 0 0 128 6 73 146 192 168 46 2 192 168 46 130 244 27 0 22 61 15 172 136 76 30 149 210 80 16 250 240] ^C ```

Thank you for taking your time for fixing this.

deitch commented 6 months ago

Amazing what a one-letter typo can do. And because it is just one letter difference to another similarly-typed constant in the same package, linters didn't catch it either.