2

I'm trying to get a raw BPF bytecode packet filter working on FreeBSD using a combination of ipfw with ng_ipfw, ng_bpf and ng_tag.

However none of the documentation or presentations I can find include any complete working examples. The ng_tag man page only shows the bpf_prog code for passing a non-matched packet back thru ng_bpf but not how to generate the correct hooks for the whole netgraph.

#!/bin/sh
cookie=41
tag=412
mtag_ipfw=1148380143        # IPFW-tagged cookie from <netinet/ip_var.h>

prog=$(./bpfgen | ./bytecode_to_ngbpf)  # generate BPF code here

ngctl shutdown ipfw:$cookie

ngctl -f- <<-__END__
  mkpeer ipfw: bpf $cookie filter
  name ipfw:$cookie CLASSIFIER
  msg CLASSIFIER: setprogram { thisHook="filter" ifMatch="match" ifNotMatch="notmatch" $prog }
  mkpeer CLASSIFIER: tag match tag_bad
  name CLASSIFIER:match TAGGER
  connect CLASSIFIER: TAGGER: notmatch tag_good
  msg CLASSIFIER: setprogram { thisHook="match" ifMatch="ipfw" bpf_prog_len=1 bpf_prog=[ { code=6 k=8192 } ] }
  msg CLASSIFIER: setprogram { thisHook="notmatch" ifMatch="ipfw" bpf_prog_len=1 bpf_prog=[ { code=6 k=8192 } ] }
  msg TAGGER: sethookin { thisHook="tag_bad" ifNotMatch="tag_bad" }
  msg TAGGER: sethookout { thisHook="tag_bad" tag_cookie=$mtag_ipfw tag_id=$tag }
  msg TAGGER: sethookin { thisHook="tag_good" ifNotMatch="tag_good" }
  msg TAGGER: sethookout { thisHook="tag_good" tag_cookie=$mtag_ipfw }
__END__

ipfw add 2000 netgraph $cookie udp from any to any
ipfw add 2010 allow log udp from any to any tagged $tag

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

This is my best guess, but all that happens is that any packet matching the ipfw rule that drops stuff into netgraph gets dropped.

The intent was to have inbound packets that match the BPF program get tagged with the MTAG_IPFW cookie and the desired tag, and that packets that don't match only get tagged with the former, and the packets that are being returned from the ng_tag module both get forwarded back upstream to the ng_ipfw module via the single instruction program ret 8192 (code=6, k=8192).

Can anyone spot what's wrong, or point me at a complete online example of how to correctly tag a packet this way?

1

After finding a non-tagging example (in Russian!) I've since managed to fix this myself, using a simplified version of the ngctl commands in my question that just returns non-matching packets directly back to ipfw:

ngctl -f- <<-__END__
  mkpeer ipfw: bpf $cookie filter
  name ipfw:$cookie CLASSIFIER
  mkpeer CLASSIFIER: tag matched tag_bad
  name CLASSIFIER:matched TAGGER
  msg CLASSIFIER: setprogram { thisHook="filter" ifNotMatch="filter" ifMatch="matched" $prog }
  msg TAGGER: sethookin { thisHook="tag_bad" ifNotMatch="tag_bad" }
  msg TAGGER: sethookout { thisHook="tag_bad" tag_cookie=$mtag_ipfw tag_id=$tag }
  msg CLASSIFIER: setprogram { thisHook="matched" ifMatch="filter" ifNotMatch="filter" bpf_prog_len=1 bpf_prog=[ { code=6 k=65535 } ] }
__END__

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.