Discussing BPF + IPFW + TAG for L7 Filtering on FreeBSD

Hello Forum,

I am conducting tests on a L7 filter setup using BPF, IPFW, and TAG, based on the resource: Tutorial_NETGRAPH_A4_Slides.pdf.

I am particularly interested in the section "BPF + IPFW + TAG = L7 Filter". During experiments on my FreeBSD system, I encountered an issue where packets do not seem to enter the rules I set up in IPFW, despite my efforts to smoothly route packets through BPF for tagging. Could this indicate that I have not correctly configured my Ethernet driver?

I welcome discussion from anyone interested or experienced in this topic. Thank you.
 
Hello Forum,

Regarding my previous inquiry, here is more detailed information.

In the presentation at Tutorial_NETGRAPH_A4_Slides.pdf, the BPF + IPFW + TAG = L7 Filter section originally used P2P TCP traffic for testing. To simplify the process, I used TCP port 80 for filtering and tag testing. Here are my configuration parameters:

Code:
ipfw add 200 allow ip from any to any
kldload ng_ipfw; kldload ng_bpf; kldload ng_tag
ngctl mkpeer ipfw: bpf 41 ipfw
ngctl name ipfw:41 bpf
ngctl mkpeer bpf: tag matched th1
ngctl name bpf:matched tag
grep MTAG_IPFW /usr/include/netinet/ip_var.h
ngctl msg tag: sethookin { thisHook="th1" ifNotMatch="th1" }
ngctl msg tag: sethookout { thisHook="th1" tag_cookie=1148380143 tag_id=412 }
ngctl msg bpf: setprogram { thisHook="matched" ifMatch="ipfw" bpf_prog_len=20 bpf_prog=[ { code=40 jt=0 jf=0 k=12 } { code=21 jt=0 jf=6 k=34525 } { code=48 jt=0 jf=0 k=20 } { code=21 jt=0 jf=15 k=6 } { code=40 jt=0 jf=0 k=54 } { code=21 jt=12 jf=0 k=80 } { code=40 jt=0 jf=0 k=56 } { code=21 jt=10 jf=11 k=80 } { code=21 jt=0 jf=10 k=2048 } { code=48 jt=0 jf=0 k=23 } { code=21 jt=0 jf=8 k=6 } { code=40 jt=0 jf=0 k=20 } { code=69 jt=6 jf=0 k=8191 } { code=177 jt=0 jf=0 k=14 } { code=72 jt=0 jf=0 k=14 } { code=21 jt=2 jf=0 k=80 } { code=72 jt=0 jf=0 k=16 } { code=21 jt=0 jf=1 k=80 } { code=6 jt=0 jf=0 k=8192 } { code=6 jt=0 jf=0 k=0 } ] }
./tcpdump2bpf.sh tcp port 80
ipfw add 100 netgraph 41 tcp from any to any 80
ipfw add 110 allow tcp from any to any tagged 412
sysctl net.inet.ip.fw.one_pass=0

In testing, using curl google.com showed that traffic indeed entered netgraph 41:
Code:
root@freebsd:~ # ipfw show
00100  172  10320 netgraph 41 log tcp from any to any 80
00110    0      0 allow log tcp from any to any tagged 412
00200 38312 6947352 allow ip from any to any
65500   97  13076 allow ip from any to any
65535   35   6617 deny ip from any to any

However, there was no traffic entering tagged 412. I haven't found a way to debug the issue with tagged 412 yet. Does anyone with relevant experience have any solutions to share?

Here is my nodes list:
Code:
There are 5 total nodes:
 Name: ipfw           Type: ipfw           ID: 00000001  Num hooks: 1
 Name: hn0            Type: ether          ID: 00000002  Num hooks: 0
 Name: bpf            Type: bpf            ID: 00000004  Num hooks: 2
 Name: ngctl5639      Type: socket         ID: 00000016  Num hooks: 0
 Name: tag            Type: tag            ID: 00000007  Num hooks: 1

Here is the info part:
Code:
root@freebsd:~ # ngctl show ipfw:
 Name: ipfw           Type: ipfw           ID: 00000001  Num hooks: 1
 Local hook     Peer name      Peer type   Peer ID        Peer hook
 ----------     ---------      ---------   -------        ---------
 41             bpf            bpf         00000004       ipfw

root@freebsd:~ # ngctl show bpf:
 Name: bpf            Type: bpf            ID: 00000004  Num hooks: 2
 Local hook     Peer name      Peer type   Peer ID        Peer hook
 ----------     ---------      ---------   -------        ---------
 matched        tag            tag         00000007       th1
 ipfw           ipfw           ipfw        00000001       41

root@freebsd:~ # ngctl show tag:
 Name: tag            Type: tag            ID: 00000007  Num hooks: 1
 Local hook     Peer name      Peer type   Peer ID        Peer hook
 ----------     ---------      ---------   -------        ---------
 th1            bpf            bpf         00000004       matched

Thanks for your assistance!
 
I'm new to netgraph but it seems like the slides are garbled. If I understand how it's supposed to work, IPFW sends packets to BPF's "ipfw" hook. BPF runs the tcpdump program on that hook and sends matches to TAG and nonmatches back to IPFW unchanged. TAG adds the 412 tag to every packet it gets and sends them back to BPF, and BPF sends them back to IPFW too. Then IPFW can use the tag to whack the packet.

There some pieces of that missing in the slides though. So maybe something like this for the sethookin/sethookout/setprogram commands would work:
Code:
# BPF runs the "tcp port 80" program on its "ipfw" hook. Matches go to TAG, nonmatches go back to IPFW.
ngctl msg dcbpf: setprogram { thisHook=\"ipfw\" ifMatch=\"matched\" ifNotMatch=\"ipfw\" \
    bpf_prog_len=20 bpf_prog=[ ...("tcp port 80" program)... ] }
# TAG sends every packet it gets back to BPF with the 412 tag added.
ngctl msg tag: sethookin { thisHook="th1" ifNotMatch="th1" }
ngctl msg tag: sethookout { thisHook="th1" tag_cookie=1148380143 tag_id=412 }
# BPF runs a 1-instruction program on its "matched" hook to send tagged packets back to IPFW too.
ngctl msg dcbpf: setprogram { thisHook=\"matched\" ifMatch=\"ipfw\" \
    bpf_prog_len=1 bpf_prog=[ { code=6 k=8192 } ] }
 
This is the content I organized based on this reference (http://www.citrin.ru/freebsd:ng_ipfw_ng_bpf).

Code:
ipfw add 200 allow ip from any to any

kldload ng_ipfw; kldload ng_bpf; kldload ng_tag

ngctl shutdown ipfw:41

ngctl mkpeer ipfw: bpf 41 filter
ngctl name ipfw:41 bpf

ngctl mkpeer bpf: tag matched tag_bad
ngctl name bpf:matched tag

#grep MTAG_IPFW /usr/include/netinet/ip_var.h

ngctl msg bpf: setprogram { thisHook=\"filter\" ifNotMatch=\"filter\" ifMatch=\"matched\" bpf_prog_len=18 bpf_prog=[ { code=0 jt=0 jf=0 k=0 } { code=48 jt=0 jf=0 k=9 } { code=21 jt=0 jf=14 k=17 } { code=40 jt=0 jf=0 k=6 } { code=69 jt=12 jf=0 k=8191 } { code=177 jt=0 jf=0 k=0 } { code=72 jt=0 jf=0 k=2 } { code=21 jt=0 jf=9 k=53 } { code=80 jt=0 jf=0 k=10 } { code=69 jt=7 jf=0 k=128 } { code=72 jt=0 jf=0 k=4 } { code=20 jt=0 jf=0 k=4 } { code=12 jt=0 jf=0 k=0 } { code=7 jt=0 jf=0 k=0 } { code=64 jt=0 jf=0 k=0 } { code=21 jt=0 jf=1 k=983041 } { code=6 jt=0 jf=0 k=65535 } { code=6 jt=0 jf=0 k=0 } ] }

ngctl msg bpf: getprogram \"filter\"

ngctl msg tag: sethookin { thisHook=\"tag_bad\" ifNotMatch=\"tag_bad\" }
ngctl msg tag: sethookout { thisHook=\"tag_bad\" tag_cookie=1148380143 tag_id=412 }

ngctl msg tag: gethookin \"tag_bad\"
ngctl msg tag: gethookout \"tag_bad\"

ngctl msg bpf: setprogram { thisHook=\"matched\" ifMatch=\"filter\" ifNotMatch=\"filter\" bpf_prog_len=1 bpf_prog=[ { code=6 k=65535 } ] }

ngctl msg bpf: getprogram \"matched\"

ipfw add 100 netgraph 41 udp from any to any 53

ipfw add 110 allow log udp from any to any tagged 412

sysctl net.inet.ip.fw.one_pass=0

ngctl msg bpf: getstats \"filter\"
ngctl msg bpf: getstats \"matched\"

ngctl msg tag: getstats \"tag_bad\"
 
Back
Top