OpenBSD Journal

What's new with PF in 4.1?

Contributed by merdely on from the PFantastic-PFun dept.

Each release since 3.0 has included exciting updates to PF. OpenBSD 4.1 is no different. From enabling keep state and flags S/SA by default, to further synchronizing pfctl command line options with what can be done inside pf.conf, to greater logging flexability and improved anchor support, the PF development team continues to expand PF's usability and functionality. Read on for more information about each of the PF updates.

keep state now default
The default action with pass rules is to keep state. To prevent keeping state on a rule, use no state: "pass on $vpn_if all no state". To apply options like max, max-src-conn-rate and max-src-states, you must explicitly specify keep state.
flags S/SA now default
For stateful TCP connections, S/SA are the default flags checked. From the man page, "out of SYN and ACK, exactly SYN may be set." To override this behavior and not check TCP flags, use "flags any".
The ruleset optimiser can be enabled in pf.conf(5)
set ruleset-optimization basic is the default behavior for pf: duplicate rules are removed, rules that are a subset of another rule are removed, multiple rules are combined into a table when advantageous and rules are reordered to improve performance. Other options besides "basic" are "none" and "profile". See pf.conf(5) for more information. pfctl(8) command line options can override what is specified in pf.conf (pfctl -o none).
pfctl(8) can now expire table entries
pfctl -t badssh -T expire 86400 will expire table entries either 86400 seconds old or 86400 seconds since the last time its statistics were cleared.
hoststated(8) is a NEW load balancing daemon at layers 3 & 7
hoststated does load balancing by keeping pf tables and rdr rules up to date. Rulesets are managed through the rdr-anchor "hoststated/*" anchor. See hoststated.conf(5) for configuration information and hoststatectl(8) for control information.
pflog(4) is clonable
After creating additional pflog interfaces (using ifconfig), rules can specify which pflog interface to use: "pass out log to pflog1 on $ext_if to port smtp". This will log traffic sent to SMTP servers to a different log interface than the default. pflogd(8) and spamlogd(8) (spamlogd -l pflog1) can now be told which pflog interface to work with.
pfsync(4) is clonable as well
This enables pfsync0 to only exist if needed.
Anchors can be loaded inline in the main pf.conf(5)
Previously, anchors were loaded from external files (load anchor foo from "/etc/pf-foo.conf") or through pfctl(8), ftp-proxy(8) or authpf(8). Filter anchors can now be loaded inline within a brace delimited block (from pf.conf(5):
           anchor "external" on egress {
                   block
                   anchor out {
                           pass proto tcp from any to port { 25, 80, 443 }
                   }
                   pass in proto tcp to any port 22
           }
Anchors can also be recursively printed with pfctl(8): pfctl -a 'authpf/*' -sr (which prints the authpf ruleset recursively). Rules inside anchors can have their counters reset.
pf(4) can select between multiple routing tables
The route(8) command (and the routing daemons) can be told which routing table to modify: route -n -T1 add -inet 10.8.8.0/24 10.1.1.1. Rules can be written to take advantage of specific routing tables: pass in on $ext_if from $companyA rtable 1.

To take advantage of these and all of the other great improvements in 4.1, make sure you buy a CD set (and make a donation!).

(Comments are closed)


Comments
  1. By Anonymous Pilot (85.214.71.55) on

    I have been looking forward to these features.
    Will buy my 4.1 CD set very soon!
    Keep the nice work up, Theo!

  2. By Chris Snell (chrissnell) chris.snell@gmail.com on http://chrissnell.com

    <B><i>pf(4) can select between multiple routing tables</B></i>

    Would someone be so kind as to explain this feature in greater detail? Specifically, what kind of situations would you use it in?

    thanks,

    Chris

    Comments
    1. By Philip Olsson (212.162.184.234) olsson@puffy.nu on

      > <B><i>pf(4) can select between multiple routing tables</B></i>
      >
      > Would someone be so kind as to explain this feature in greater detail? Specifically, what kind of situations would you use it in?
      >

      For when you want private networks over a shared infrastructure. Compare to Cisco VRF.

      I wonder if/when ospfd/bgpd will be able to use this for running seperate instances per routing table.

      Comments
      1. By sthen (85.158.44.149) on

        > I wonder if/when ospfd/bgpd will be able to use this for running seperate instances per routing table.

        I haven't tried it yet, but you should be able to do this with bgpd(8) - run a couple of daemons with -f to specify alternative configuration files, use 'listen on' to bind to a specific address, and 'rtable' to choose the routing table.

  3. By Anonymous Coward (81.57.42.108) on

    Wouldn't "scrub all" be a good candidate for the "sane defaults" overhaull (like "flags S/SA" and "keep state") ?

  4. By Anonymous Coward (66.146.142.146) on

    Is bandwidth control per IP doable in pf now? It's been doable on Linux for a while, and the only workaround I found is to use delay pools on Squid (which is a bit of a pain).

    Would be nice to have this done in pf which usually is capable of pretty much everything.

    Comments
    1. By jim fear (24.64.192.72) on

      > Is bandwidth control per IP doable in pf now? It's been doable on Linux for a while, and the only workaround I found is to use delay pools on Squid (which is a bit of a pain).
      >
      > Would be nice to have this done in pf which usually is capable of pretty much everything.

      I think you can do that with queing can't you?

    2. By Anonymous Coward (206.109.19.119) on

      > Is bandwidth control per IP doable in pf now? It's been doable on Linux for a while, and the only workaround I found is to use delay pools on Squid (which is a bit of a pain).
      >
      > Would be nice to have this done in pf which usually is capable of pretty much everything.

      PF has been capable of this since 3.3. I suggest picking up a copy of Jeremy Reed's OpenBSD Packet Filter Book at lulu if the manpages don't spell it out. This has several examples of queues (Chapter 12) for protocols as well as subnets and single IP addresses. Besides, a percentage of book sales go to the project.

      Comments
      1. By Lars Hansson (203.65.245.11) lars@uet.net.ph on

        > PF has been capable of this since 3.3.

        That's not what he means. What he mean is to specify a subnet, say 192.168.0.0/24, and then have pf *automatically* apply a certain bandwidth *per IP address*. The only way to do that now is to manually create one queue per IP address. AFAIK pf can't do this right now and I havent heard anyone working on implementing it.

        Comments
        1. By Matt Van Mater (69.255.1.181) on

          This is only really necessary if you care about giving every unique IP a equal share of the bandwidth. Personally I would just add them to an abusers table and let them fight it out amongst themselves to share the bandwidth.

          If you wanted a more 'equal' treatment of your abusers, a motivated admin with just a little scripting experience and a few hours could do this without a huge level of effort:

          Create base ruleset template
          --create 'abusers parent queue' and define $max_bandwidth, put a placeholder in there for <insert bad hosts>

          Then write a little script that
          --reads in an $infile of bad user ips, store them in array @bad_ips
          --counts total number of @bad_ips and store in $total_ips
          --calculates $single_host_percent = (1 / $total_ips) (make sure to round down)
          --make sure $single_host_percent * $total_ips is near 100% (i am not sure if PF will barf if total % isn't 100 so you may have to put some padding in to reach 100)
          --for each @bad_ips
          ----create queue statement for each bad ip and set aside the percentage you found above
          ----insert queue statement created above in copy of ruleset template file before <insert bad hosts> line
          --after last bad host is read from $infile, remove the <insert bad hosts> line from copy of ruleset template
          --executes pfctl -f /path/to/new/ruleset
          --(consider flushing state table, but that will hurt other nice users)

          Write another tiny wrapper script to
          --add and remove entries from $infile
          --execute script above after each add/remove

          Yes I am sure I am missing some things, and the above is crappy, but you get the idea. You can get creative and use the new table expiration features to only put people in the penalty box for a short while, use pftop to automatically add top talkers above a certain threshold into the $infile and execute the main script to rate limit them, etc...

          good times :)

    3. By Anonymous Coward (24.37.242.64) on

      > Is bandwidth control per IP doable in pf now? It's been doable on Linux for a while, and the only workaround I found is to use delay pools on Squid (which is a bit of a pain).
      >
      > Would be nice to have this done in pf which usually is capable of pretty much everything.

      Using authpf is one way that I can think of, based on individual IP address.

  5. By Marc (194.245.32.131) on

    is it a good idea, to keep states away from the $vpn_if, as the text says? what are the downsides of this? or what are the downsides of keeping states on the $vpn_if?

    Comments
    1. By Joel (198.166.35.222) enabled@myrealbox.com on

      > is it a good idea, to keep states away from the $vpn_if, as the text says? what are the downsides of this? or what are the downsides of keeping states on the $vpn_if?

      There's a danger that if you're using IPsec (or I guess OpenVPN too) and you have "pass out on enc0 all keep state" and then the IPsec flows (which tell the kernel what traffic to send down the IPsec connection) are removed for some reason, that your private traffic will now be routed normally. In most cases that would result in that traffic being sent to the Internet in the clear.

      Best practice will now be to include "keep state (if-bound)" on enc0 interfaces, or do like the article says and don't keep state at all on that interface.




      .joel

      Comments
      1. By Marc (84.62.37.61) on

        > Best practice will now be to include "keep state (if-bound)" on enc0 interfaces, or do like the article says and don't keep state at all on that interface.
        what does that if-bound exactly mean?

        i tried to not keep state at all on the vpn-interfaces, but then some applications actually stopped working at all, so i actually need states on the $vpn_ifs.

Latest Articles

Credits

Copyright © - Daniel Hartmeier. All rights reserved. Articles and comments are copyright their respective authors, submission implies license to publish on this web site. Contents of the archive prior to as well as images and HTML templates were copied from the fabulous original deadly.org with Jose's and Jim's kind permission. This journal runs as CGI with httpd(8) on OpenBSD, the source code is BSD licensed. undeadly \Un*dead"ly\, a. Not subject to death; immortal. [Obs.]