Bacula File/Storage Connection Woes using PF

Jeremy Chadwick koitsu at freebsd.org
Wed Mar 26 02:53:17 UTC 2008


On Tue, Mar 25, 2008 at 03:53:15PM -0700, Doug Sampson wrote:
> > > Is there another way of writing rules that will enable the 
> > Bacula client to
> > > pass packets to the correct port number?
> > >   
> > Yes, make the 1st rule
> > 
> >     block log all
> > 
> > to drop both ingress and egress traffic by default.
> > 
> > Secondly get rid of the stateless rules. Use keep state 
> > everywhere, with 
> > flags S/SA if matching tcp traffic.

This isn't a reply to you (Doug), but -- do not blindly use "keep state"
everywhere!

There's been too many cases I've experienced where using "keep state"
blindly results in state-mismatch increasing at a very fast rate.  When
I implemented this mentality on our production servers, our users
started pointing out that scp's between machines would randomly get
severed mis-stream, same with ssh sessions where large TCP windows were
used (such as doing 'dmesg' over and over):

http://lists.freebsd.org/pipermail/freebsd-pf/2008-January/004050.html

The "use keep state on everything!" attitude seems to stem from people
reading the OpenBSD pf.conf documentation, which states that as of
OpenBSD 4.1, "keep state" is implicit on every rule (meaning it's done
whether you say "keep state" or not).  FreeBSD's pf isn't like this.

> I hate to bug you guys but I ain't a pf guru like you guys. I am not
> understanding the significance of the "keep state" and the "flags S/SA
> synproxy state" qualifiers. I have been copying some rules from articles
> here and there. Thus these rules are not unified in the sense that these are
> designed from the beginning to work harmoniously.

The easiest way to explain "keep state" is: with rules that use "keep
state", every time a packet matching that rule is encountered, pf keeps
track of the current TCP state and permits/denies based on the TCP
state, rather than having to reiterate through all of your rulesets over
and over.

I'll try to explain it with a very small ruleset and a couple scenarios:

  $ext_if = network interface that's got a public IP address
  4.4.4.4 = our public IP address

  pass out quick all flags S/SA keep state
  pass out quick all
  block in log all
  pass in quick on $ext_if inet proto tcp from any to 4.4.4.4 port ssh

Two scenarios:

1) When an incoming TCP packet from <any> to 4.4.4.4 on port 22 is seen,
that incoming packet is permitted (rule #4).  Outbound responses from
4.4.4.4 to <whoever sent the original incoming packet> are also
permitted (rule #1).  Note the "keep state".

pf will begin keep tracking of the TCP state from that point forward,
which means it doesn't have to reiterate through your rules to continue
passing inbound/outbound traffic for that TCP session.

2) An outbound TCP packet from 4.4.4.4 port 50345 to 12.90.124.50 port
25 is attempted.  That packet is permitted (rule #1), and the TCP
state is tracked in pf.

The *response* packets from 12.90.124.50 port 25 to 4.4.4.4 port 50345
are also permitted -- yet you see no rule for such, do you?  This is
because pf's state tracking ("keep state") is doing the pass/deny
for you.


It gets more confusing when you consider the fact that even though UDP
and ICMP are stateless protocols, pf can keep track of their state too,
though I don't know if FreeBSD pf supports that (OpenBSD pf does).

Now, about flags S/SA -- you need to understand how TCP works to really
understand what purpose this serves.

"flags" causes pf to look at only certain TCP flags (bits), and check to
see which of those bits are set or clear.  You can check against FIN,
SYn, RST, PSH, ACK, URG, ECE, and CWR.  That criteria must be matched
for the rule in question to be used.  The official docs are here, which
also describes synproxy (which I haven't used):

http://www.openbsd.org/faq/pf/filter.html#tcpflags

Let's take rule #1 in the above ruleset:

  pass out quick all flags S/SA keep state

This means pass any outbound traffic (from any IP address of ours) with
the TCP flag SYN set (but only look at the SYN and ACK flags when doing
that comparison) -- and keep track of TCP state.

This explanation should also provide you an answer to what rule #2 is
for -- permitting outbound packets which DO NOT match that criteria.
You might be wondering "so why not nuke rule #1 and just use #2?", to
which my reply would be, "see Scenario #2 -- incoming packets from
12.90.124.50 port 25 to 4.4.4.4 port 50345 would then get blocked!"


Does this make more sense to you?  :-)

-- 
| Jeremy Chadwick                                    jdc at parodius.com |
| Parodius Networking                           http://www.parodius.com/ |
| UNIX Systems Administrator                      Mountain View, CA, USA |
| Making life hard for others since 1977.                  PGP: 4BD6C0CB |



More information about the freebsd-pf mailing list