Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 22 Jan 2010 14:35:17 -0800
From:      Doug Hardie <>
To:        Erik Norgaard <>
Cc:        freebsd-questions - <>
Subject:   Re: pf rules
Message-ID:  <>
In-Reply-To: <>
References:  <> <> <> <>

Next in thread | Previous in thread | Raw E-Mail | Index | Archive | Help

On 22 January 2010, at 03:14, Erik Norgaard wrote:

> Doug Hardie wrote:
>> On 22 January 2010, at 01:45, Erik Norgaard wrote:
>>> To debug pf rules:
>>> - always add direction to the rule, pass or block, add interface to =
>>> rules except default policy, keep state on all pass rules
>>> - group your rules per direction, then per interface
>>> - add log to all rules and watch pflog to see which rule blocks or
>>> passes traffic.
>>> - use keyword quick for any decisive rule
>>> - check the parsing of your ruleset, pfctl -sr
>>> then come back and ask for help.
>> Where do you find the rule information in the pflog output from =
tcpdump? =20
> a snip:
> alpha# tcpdump -n -e -i pflog0
> tcpdump: WARNING: pflog0: no IPv4 address assigned
> tcpdump: verbose output suppressed, use -v or -vv for full protocol =
> listening on pflog0, link-type PFLOG (OpenBSD pflog file), capture =
size 96 bytes
> 11:55:20.910140 rule 81/0(match): block in on vr1: =
>  tcp 44 [bad hdr length 0 - too short, < 20]
> rule 81 blocks. Now, problem is that your rules may be more compact, =
you'll find the rule with pfctl -sr. Now admittedly, I got:
> pass in quick on vr1 inet proto udp from to <local_ip> =
port =3D secret_service keep state
> ofcourse, that rule didn't block. But two lines down I found:
> block return in log quick on vr1 inet from to <local_ip>
> This makes sence, so why the offset 2? The first line of the output =
from pfctl -sr is
> scrub all fragment reassemble
> that shouldn't count as a rule. And then, if pflog starts counting =
with 0 while vi counts from 1 that explains it.
> Yet another reason to check the rules as parsed using pfctl -sr.
> Anyway, not trying to cut corners is the first step, then add log so =
you can see whats going on, use quick to avoid some packet fall through =
and being matched by a different rule than intended, organizes your =
rules so you can easily separate things out.
> My rules are grouped together like this:
> # default policy
> block all
> block in log <general condition>
> pass  in quick some packets keep state
> block in log quick <general condition>
> block out log <general condition>
> pass  out quick some packets keep state
> block out log quick <general condition>
> # Default policy catch all should never apply
> block log all
> the conditions for the pass rules should match those of the first =
block and then be more specific, say, only apply to one port. Doing so, =
the pf rule parser will optimize the ruleset.
> Even if I know that a given rule can only match packets on the vr0 =
interface, I explicitly state the interface. It makes it clear what's =
going on.
> Once the ruleset is debugged and working you can remove the log =

Thanks.  That is really helpful.  The key is that the rule information =
is in the link layer.  I never guessed that.  Now I see it just fine.  =
This approach sure beats monitoring the statistics and the input and =
trying to correlate them.  That was the approach I was using.

Want to link to this message? Use this URL: <>