[PATCH] ng_pf and l7 filtering possibility with PF
Ermal Luçi
ermal.luci at gmail.com
Tue May 29 20:18:51 UTC 2007
This is ng_pf node based on ng_ipfw code and idea.
It allows interaction of PF and netgraph.
Below are the node features and a dummy example of how to use it.
Patch is attached.
Features,
1- By default it sends any packet that matches the rule to netgraph.
Syntax: pass in from any to any netgraph 41 #41 is the hook number(it
needs to be a number)
2- You can specify how many packets will be sent to netgraph. This is
implemented as a keep state option.
Syntax: pass in from any to any netgraph 41 keep
state(max-packets-to-netgraph 4)
3- You can specify flags when adding the tag to the node.
Syntax ngctl msg pf: addtag { tagname=\"TEST\" tag=60 flags=4 }
There are 4 flags for now:
NG_PF_KILL_STATE (actually removes state from the state pool
directly from the node
NG_PF_IGNORE_STATE (it schedules the state to be removed later but
behaves as the above and is really faster and safer)
NG_PF_SKIP_FIREWALLS (skips firewalls; the way it is implemented
this really skips any firewall on freebsd at least ipfw and pf). This
is per tag setting
meaning you can specify which packet whith a specific tag should skip
reparssing the rules.
NG_PF_DROP_PACKET (really drops packet; faster than telling a rule
on PF to drop it, i don't like it personally cause is kinda magic; but
it is there)
4- The node has these messages:
NGM_PF_ADD_TAG (needs tagname, tagid, flags)
struct ng_pf_command {
char name[NG_PF_TAG_NAME_SIZE];
u_int16_t tag;
int flags;
};
NGM_PF_RMV_TAG, (needs tagname)
NGM_PF_GET_TAGS, (no arguments)
#ifdef NG_PF_DEBUG
NGM_PF_GET_STATS, (number of packets in/out)
NGM_PF_CLR_STATS,
NGM_PF_GETCLR_STATS,
#endif
NGM_PF_SET_TAGZONE,
NGM_PF_GET_TAGZONE,
NGM_PF_DEFAULT_TAGZONE (for help)
5- You can send back and forth a packet(reparse ruleset multiple
times) by resending a packet that has already passed once to netgraph
by a matching rule with a different hook number. I.e.:
....
.....
pass in on $int from any to any netgraph 41
pass in on $int tagged ONCE_TO_NETGRAPH netgraph 42
pass in on $int tagged TWICE_TO_NETGRAPH netgraph 43
....
...
For an example how to find DC++ packets with ng_bpf tag these packets
with ng_tag is available at ng_tag manual page. After that just
connect a hook to ng_pf and you're done. Surely even the rule that
sends the packet to the correct queue on PF side.
For more discussion on ng_bpf and packet matching for P2P packets follow,
http://lists.freebsd.org/pipermail/freebsd-current/2006-June/063863.html.
Sample configuration of the node.
1 - kldload ng_pf (after compiling).
2 - create a sample pf.conf file like the following:
pass out quick on $INT all tagged TRY keep state
pass out quick on $INT proto tcp from any to any port 80 netgraph 41
# or even this. It does the same thing.
pass out on $INT proto tcp from any to any port 80 netgraph 41
pass out on $INT all tagged TRY keep state
#The tag TRY is added to ng_pf list of tags to translate and the tag
is added to the #packet with ng_tag.
3 - configure netgraph part of things. I used the following commands
on my tests:
# You understand the first 2 commands :).
pfctl -e
pfctl -F all -f /etc/pf.test
# Here we configure a tag to be translated on ng_pf node. The node translates
# tagname=TRY as known by PF.
ngctl msg pf: addtag { tagname=\"TRY\" tag=52 flags=0 }
# Create a hook with a ng_tag node.
ngctl mkpeer pf: tag 41 th1
# Give a name to the hook for simplicity.
ngctl name pf:41 match
# Configure ng_tag node.
# We tell ng_tag to not touch the packets incoming/entering on hook = "th1"
ngctl msg match: sethookin { thisHook=\"th1\" ifNotMatch=\"th1\" }
# ng_tag will tag packets leaving hook="th1" with tagname=TRY.
ngctl msg match: sethookout { \
thisHook=\"th1\" \ #hookname
tag_id=24 \ # PACKET_TAG_PF_TAG.(1)
tag_len=4 \ # usually 4 bytes since we only pass a
number/tag_id.
tag_data=[ 52 ] } # the tag we want to apply packets on this hook.
{ (1) PACKET_TAG_PF_TAG = 24 is taken from sys/mbuf.h }
After this if you try to connect to port 80 of any webserver if you
check the PF
statistics on rule matches with:
pfctl -s rules -v
you'll see that packets have gone through 'match by tag' rule after
passing through netgraph.
Feedback is appriciated,
Ermali
More information about the freebsd-pf
mailing list