*nix Documentation Project
·  Home
 +   man pages
·  Linux HOWTOs
·  FreeBSD Tips
·  *niX Forums

  man pages->OpenBSD man pages -> pf.conf (5)              



NAME    [Toc]    [Back]

     pf.conf - packet filter configuration file

DESCRIPTION    [Toc]    [Back]

     The pf(4) packet filter modifies, drops  or  passes  packets
according to
     rules or definitions specified in pf.conf.

STATEMENT ORDER    [Toc]    [Back]

     There are seven types of statements in pf.conf:

     Macros    [Toc]    [Back]
           User-defined  variables may be defined and used later,
           the configuration file.  Macros must be defined before
they are
           referenced in pf.conf.

     Tables    [Toc]    [Back]
           Tables  provide a mechanism for increasing the performance and flexibility
 of rules with large numbers of source or  destination addresses.

     Options    [Toc]    [Back]
           Options tune the behaviour of the packet filtering engine.

     Traffic Normalization (e.g. scrub)
           Traffic  normalization  protects   internal   machines
against inconsistencies
 in Internet protocols and implementations.

     Queueing    [Toc]    [Back]
           Queueing provides rule-based bandwidth control.

     Translation (Various forms of NAT)
           Translation  rules  specify  how  addresses  are to be
mapped or redirected
 to other addresses.

     Packet Filtering    [Toc]    [Back]
           Stateful and stateless packet filtering provides rulebased blocking
 or passing of packets.

     With the exception of macros and tables, the types of statements should
     be grouped and appear in pf.conf in the order  shown  above,
as this matches
  the operation of the underlying packet filtering engine.
By default
     pfctl(8) enforces this order (see set require-order  below).

MACROS    [Toc]    [Back]

     Much  like  cpp(1) or m4(1), macros can be defined that will
later be expanded
 in context.  Macro names must start  with  a  letter,
and may contain
     letters, digits and underscores.  Macro names may not be reserved words
     (for example pass, in, out).  Macros are not expanded inside

     For example,

           ext_if = "kue0"
           all_ifs = "{" $ext_if lo0 "}"
           pass out on $ext_if from any to any keep state
           pass  in  on $ext_if proto tcp from any to any port 25
keep state

TABLES    [Toc]    [Back]

     Tables are named structures which can hold a  collection  of
addresses and
     networks.   Lookups  against  tables in pf(4) are relatively
fast, making a
     single rule with tables much more  efficient,  in  terms  of
processor usage
     and  memory  consumption, than a large number of rules which
differ only in
     IP address (either created explicitly  or  automatically  by
rule expansion).

     Tables  can  be  used as the source or destination of filter
rules, scrub
     rules or translation rules such as nat or rdr (see below for
details on
     the  various  rule  types).  Tables can also be used for the
redirect address
 of nat and rdr rules and in  the  routing  options  of
filter rules,
     but only for round-robin pools.

     Tables  can  be  defined  with any of the following pfctl(8)
mechanisms.  As
     with macros, reserved words may not be used as table  names.

     manually  Persistent tables can be manually created with the
add or
               replace option of pfctl(8), before  or  after  the
ruleset has
               been loaded.

     pf.conf    Table  definitions can be placed directly in this
file, and
               loaded at the same time as other rules are loaded,
               Table  definitions  inside  pf.conf  use the table
statement, and
               are especially useful to define non-persistent tables.  The
               contents of a pre-existing table defined without a
list of addresses
 to  initialize  it  is  not  altered  when
pf.conf is loaded.
               A table initialized with the empty list, { }, will
be cleared
               on load.

     Tables may be defined with the following two attributes:

     persist  The persist flag forces  the  kernel  to  keep  the
table even when
              no  rules refer to it.  If the flag is not set, the
kernel will
              automatically remove the table when the  last  rule
referring to
              it is flushed.

     const     The const flag prevents the user from altering the
contents of
              the table once it has been created.   Without  that
flag, pfctl(8)
              can  be  used  to  add or remove addresses from the
table at any
              time, even when running with securelevel(7) = 2.

     For example,

           table <private> const { 10/8, 172.16/12, 192.168/16 }
           table <badhosts> persist
           block on fxp0 from { <private>, <badhosts> } to any

     creates a table called private, to  hold  RFC  1918  private
network blocks,
     and  a  table  called badhosts, which is initially empty.  A
filter rule is
     set up to block all traffic coming from addresses listed  in
either table.
     The  private  table cannot have its contents changed and the
badhosts table
     will exist even when no active filter  rules  reference  it.
Addresses may
     later  be  added to the badhosts table, so that traffic from
these hosts
     can be blocked by using

           # pfctl -t badhosts -Tadd

     A table can also be initialized with an address list  specified in one or
     more external files, using the following syntax:

           table   <spam>   persist   file  "/etc/spammers"  file
           block on fxp0 from <spam> to any

     The files /etc/spammers and /etc/openrelays list IP addresses, one per
     line.   Any lines beginning with a # are treated as comments
and ignored.
     In addition to being specified by IP address, hosts may also
be specified
     by  their  hostname.   When  the resolver is called to add a
hostname to a
     table, all resulting IPv4 and IPv6 addresses are placed into
the table.
     IP  addresses can also be entered in a table by specifying a
valid interface
 name or the self keyword, in which case  all  addresses
assigned to
     the interface(s) will be added to the table.

OPTIONS    [Toc]    [Back]

     pf(4) may be tuned for various situations using the set command.

     set timeout

           interval   Interval between purging expired states and
           frag        Seconds  before an unassembled fragment is
           src.track  Length of time to retain a source  tracking
entry after
                      the last state expires.

           When  a packet matches a stateful connection, the seconds to live
           for the connection will be  updated  to  that  of  the
           which corresponds to the connection state.  Each packet which
           matches this state will reset the TTL.   Tuning  these
values may improve
  the  performance of the firewall at the risk of
dropping valid
           idle connections.

                 The state after the first packet.
                 The state before the destination host ever sends
a packet.
                 The fully established state.
                 The state after the first FIN has been sent.
                 The  state  after  both FINs have been exchanged
and the connection
 is closed.  Some hosts (notably web servers
on Solaris)
                 send  TCP packets even after closing the connection.  Increasing
 tcp.finwait (and possibly  tcp.closing)  can
prevent blocking
 of such packets.
                 The state after one endpoint sends an RST.

           ICMP  and UDP are handled in a fashion similar to TCP,
but with a
           much more limited set of states:

                 The state after the first packet.
                 The state if the source host sends more than one
packet but
                 the destination host has never sent one back.
                 The state if both hosts have sent packets.
                 The state after the first packet.
                 The  state  after an ICMP error came back in response to an
                 ICMP packet.

           Other protocols are handled similarly to UDP:


           Timeout values can be reduced adaptively as the number
of state
           table entries grows.

                 When  the  number  of state entries exceeds this
value, adaptive
                 scaling begins.  All timeout values  are  scaled
linearly with
                 factor  (adaptive.end  -  number  of  states)  /
(adaptive.end -
                 When reaching this number of state entries,  all
timeout values
  become  zero, effectively purging all state
entries immediately.
  This value is used to define the scale
factor, it
                 should  not  actually  be  reached  (set a lower
state limit, see

           These values can be defined both globally and for each
rule.  When
           used  on  a  per-rule  basis, the values relate to the
number of states
           created by the rule, otherwise to the total number  of

           For example:

                 set timeout tcp.first 120
                 set timeout tcp.established 86400
                 set  timeout { adaptive.start 6000, adaptive.end
12000 }
                 set limit states 10000

           With 9000 state table entries, the timeout values  are
scaled to 50%
           (tcp.first 60, tcp.established 43200).

     set loginterface
           Enable  collection of packet and byte count statistics
for the given
           interface.  These statistics can be viewed using

                 # pfctl -s info

           In this example pf(4) collects statistics on  the  interface named

                 set loginterface dc0

           One can disable the loginterface using:

                 set loginterface none

     set limit
           Sets hard limits on the memory pools used by the packet filter.
           See pool(9) for an explanation of memory pools.

           For example,

                 set limit states 20000

           sets the maximum number of entries in the memory  pool
used by state
           table  entries  (generated  by  keep  state  rules) to
20000.  Using

                 set limit frags 20000

           sets the maximum number of entries in the memory  pool
used for
           fragment  reassembly  (generated  by  scrub  rules) to
20000.  Finally,

                 set limit src-nodes 2000

           sets the maximum number of entries in the memory  pool
used for
           tracking   source   IP  addresses  (generated  by  the
sticky-address and
           source-track options) to 2000.

           These can be combined:

                 set limit { states 20000, frags 20000, src-nodes
2000 }

     set optimization
           Optimize  the  engine for one of the following network

                 A normal network environment.  Suitable for  almost all networks.

                 A  high-latency environment (such as a satellite
                 Alias for high-latency.
                 Aggressively  expire  connections.    This   can
greatly reduce the
                 memory  usage  of  the  firewall  at the cost of
dropping idle
                 connections early.
                 Extremely conservative settings.  Avoid dropping
                 connections  at  the  expense  of greater memory
                 (possibly much greater on a  busy  network)  and
slightly increased
 processor utilization.

           For example:

                 set optimization aggressive

     set block-policy
           The block-policy option sets the default behaviour for
the packet
           block action:

           drop      Packet is silently dropped.
           return    A TCP RST is returned for blocked TCP  packets, an ICMP
                     UNREACHABLE  is  returned  for  blocked  UDP
packets, and all
                     other packets are silently dropped.

           For example:

                 set block-policy return

     set state-policy
           The state-policy option sets the default behaviour for

           if-bound     States are bound to interface.
           group-bound  States are bound to interface group (i.e.
           floating     States can match packets  on  any  interfaces (the default).

           For example:

                 set state-policy if-bound

     set require-order
           By default pfctl(8) enforces an ordering of the statement types in
           the  ruleset  to:  OPTIONS,  normalization,  QUEUEING,
           filtering.   Setting  this  option to no disables this
           There may be non-trivial and non-obvious  implications
to an out of
           order  ruleset.   Consider  carefully before disabling
the order enforcement.

     set fingerprints
           Load fingerprints of known operating systems from  the
given filename.
  By default fingerprints of known operating systems are automatically
 loaded from pf.os(5)  in  /etc  but  can  be
overridden via
           this  option.   Setting  this option may leave a small
period of time
           where the fingerprints referenced by the currently active ruleset
           are  inconsistent until the new ruleset finishes loading.

           For example:

                 set fingerprints "/etc/pf.os.devel"

     set debug
           Set the debug level to one of the following:

           none          Don't generate debug messages.
           urgent        Generate debug messages only for serious
           misc           Generate debug messages for various errors.
           loud          Generate debug messages for common  conditions.


     Traffic  normalization is used to sanitize packet content in
such a way
     that there are no ambiguities in  packet  interpretation  on
the receiving
     side.  The normalizer does IP fragment reassembly to prevent
attacks that
     confuse intrusion detection systems by  sending  overlapping
IP fragments.
     Packet normalization is invoked with the scrub directive.

     scrub has the following options:

           Clears  the dont-fragment bit from a matching IP packet.  Some operating
 systems are known to generate fragmented packets
with the
           dont-fragment bit set.  This is particularly true with
NFS.  Scrub
           will drop such fragmented dont-fragment packets unless
no-df is

           Unfortunately  some  operating  systems  also generate
their dont-
           fragment packets with a zero IP identification  field.
Clearing the
           dont-fragment  bit  on  packets  with a zero IP ID may
cause deleterious
 results if an upstream router later fragments  the
packet.  Using
  the random-id modifier (see below) is recommended
in combination
 with the no-df modifier to ensure unique IP identifiers.

     min-ttl <number>
           Enforces a minimum TTL for matching IP packets.

     max-mss <number>
           Enforces a maximum MSS for matching TCP packets.

           Replaces  the IP identification field with random values to compensate
 for predictable values generated by  many  hosts.
This option
           only  applies  to  outgoing packets that are not fragmented after the
           optional fragment reassembly.

     fragment reassemble
           Using scrub rules, fragments  can  be  reassembled  by
           In this case, fragments are buffered until they form a
           packet, and only the completed packet is passed on  to
the filter.
           The  advantage  is that filter rules have to deal only
with complete
           packets, and can ignore fragments.   The  drawback  of
caching fragments
 is the additional memory cost.  But the full reassembly
           method is the only method that  currently  works  with
NAT.  This is
           the  default behavior of a scrub rule if no fragmentation modifier
           is supplied.

     fragment crop
           The default fragment reassembly method  is  expensive,
hence the option
  to  crop  is provided.  In this case, pf(4) will
track the fragments
 and cache a small range  descriptor.   Duplicate
fragments are
           dropped and overlaps are cropped.  Thus data will only
occur once
           on the wire with ambiguities resolving  to  the  first
           Unlike the fragment reassemble modifier, fragments are
           buffered, they are passed as  soon  as  they  are  received.  The
           fragment  crop  reassembly mechanism does not yet work
with NAT.

     fragment drop-ovl
           This option is similar to the fragment  crop  modifier
except that
           all   overlapping   or  duplicate  fragments  will  be
dropped, and all
           further corresponding fragments  will  be  dropped  as

     reassemble tcp
           Statefully    normalizes   TCP   connections.    scrub
reassemble tcp rules
           may  not  have  the  direction   (in/out)   specified.
reassemble tcp performs
 the following normalizations:

           ttl       Neither side of the connection is allowed to
reduce their
                    IP TTL.  An attacker may send a  packet  such
that it reaches
  the firewall, affects the firewall state,
and expires
                    before   reaching   the   destination   host.
reassemble tcp will
                    raise  the  TTL of all packets back up to the
highest value
                    seen on the connection.
           timeout modulation
                    Modern TCP stacks will send  a  timestamp  on
every TCP packet
  and  echo  the other endpoint's timestamp
back to them.
                    Many operating systems will merely start  the
timestamp at
                    zero when first booted, and increment it several times a
                    second.  The uptime of the host  can  be  deduced by reading
                    the  timestamp and multiplying by a constant.
Also observing
 several different timestamps can be  used
to count
                    hosts  behind a NAT device.  And spoofing TCP
packets into
                    a connection  requires  knowing  or  guessing
valid timestamps.
  Timestamps merely need to be monotonically increasing
 and not derived off a guessable base
                    reassemble  tcp  will cause scrub to modulate
the TCP timestamps
 with a random number.
           extended PAWS checks
                    There is a  problem  with  TCP  on  long  fat
pipes, in that a
                    packet  might  get delayed for longer than it
takes the connection
 to wrap its  32-bit  sequence  space.
In such an occurance,
  the  old  packet would be indistinguishable from a
                    new packet and would  be  accepted  as  such.
The solution to
                    this   is  called  PAWS:  Protection  Against
Wrapped Sequence
                    numbers.  It protects against  it  by  making
sure the timestamp
  on  each  packet does not go backwards.
reassemble tcp
                    also makes sure the timestamp on  the  packet
does not go
                    forward  more  than the RFC allows.  By doing
this, pf(4)
                    artificially extends the security of TCP  sequence numbers
                    by 10 to 18 bits when the host uses appropriately randomized
 timestamps, since a blind attacker would
have to
                    guess the timestamp as well.

     For example,

           scrub in on $ext_if all fragment reassemble

QUEUEING    [Toc]    [Back]

     Packets  can  be assigned to queues for the purpose of bandwidth control.
     At least two declarations are required to configure  queues,
and later any
     packet  filtering  rule  can reference the defined queues by
name.  During
     the filtering component  of  pf.conf,  the  last  referenced
queue name is
     where  any packets from pass rules will be queued, while for
block rules
     it specifies where any resulting ICMP  or  TCP  RST  packets
should be
     queued.   The scheduler defines the algorithm used to decide
which packets
     get delayed, dropped, or sent out  immediately.   There  are
     schedulers currently supported.

     cbq   Class Based Queueing.  Queues attached to an interface
build a
           tree, thus each queue can have further  child  queues.
Each queue
           can   have   a  priority  and  a  bandwidth  assigned.
Priority mainly controls
 the time packets take to  get  sent  out,  while
bandwidth has
           primarily  effects  on  throughput.  cbq achieves both
           and sharing of link bandwidth by hierarchically structured classes.
           Each class has its own queue and is assigned its share
           bandwidth.  A child class can  borrow  bandwidth  from
its parent
           class  as  long  as excess bandwidth is available (see
the option
           borrow, below).

     priq  Priority Queueing.  Queues are flat  attached  to  the
           thus,  queues  cannot have further child queues.  Each
queue has a
           unique priority assigned, ranging from 0 to 15.  Packets in the
           queue with the highest priority are processed first.

     hfsc   Hierarchical  Fair Service Curve.  Queues attached to
an interface
           build a tree, thus each queue can have  further  child
queues.  Each
           queue  can  have  a priority and a bandwidth assigned.
Priority mainly
 controls the time packets take  to  get  sent  out,
while bandwidth
           has  primarily  effects  on throughput.  hfsc supports
both link-sharing
 and guaranteed real-time services.  It  employs  a
service curve
           based  QoS model, and its unique feature is an ability
to decouple
           delay and bandwidth allocation.

     The interfaces on which queueing should be activated are declared using
     the  altq  on  declaration.   altq on has the following keywords:

           Queueing is enabled on the named interface.

           Specifies which queueing scheduler to use.   Currently
           values are cbq for Class Based Queueing, priq for Priority Queueing
           and hfsc  for  the  Hierarchical  Fair  Service  Curve

     bandwidth <bw>
           The maximum bitrate for all queues on an interface may
be specified
           using the bandwidth keyword.  The value can be  specified as an absolute
 value or as a percentage of the interface bandwidth.  When
           using an absolute value, the suffixes b, Kb,  Mb,  and
Gb are used to
           represent  bits,  kilobits, megabits, and gigabits per
second, respectively.
  The value must not exceed  the  interface
bandwidth.  If
           bandwidth is not specified, the interface bandwidth is

     qlimit <limit>
           The maximum number of packets held in the queue.   The
default is

     tbrsize <size>
           Adjusts  the size, in bytes, of the token bucket regulator.  If not
           specified, heuristics based on the interface bandwidth
are used to
           determine the size.

     queue <list>
           Defines a list of subqueues to create on an interface.

     In the following example, the interface dc0 should queue  up
to 5 Mbit/s
     in  four  second-level  queues  using  Class Based Queueing.
Those four
     queues will be shown in a later example.

           altq on dc0 cbq bandwidth 5Mb queue { std, http, mail,
ssh }

     Once  interfaces  are  activated for queueing using the altq
directive, a
     sequence of queue directives may be defined.  The name associated with a
     queue must match a queue defined in the altq directive (e.g.
mail), or,
     except for the priq scheduler, in a  parent  queue  declaration.  The following
 keywords can be used:

     on <interface>
           Specifies the interface the queue operates on.  If not
given, it
           operates on all matching interfaces.

     bandwidth <bw>
           Specifies the maximum bitrate to be processed  by  the
queue.  This
           value  must  not  exceed the value of the parent queue
and can be
           specified as an absolute value or a percentage of  the
           queue's  bandwidth.   The priq scheduler does not support bandwidth

     priority <level>
           Between queues a priority level can be set.   For  cbq
and hfsc, the
           range  is  0  to 7 and for priq, the range is 0 to 15.
The default
           for all is 1.  Priq queues with a higher priority  are
always served
           first.  Cbq and Hfsc queues with a higher priority are
preferred in
           the case of overload.

     qlimit <limit>
           The maximum number of packets held in the queue.   The
default is

     The   scheduler   can   get   additional   parameters   with
     <parameters> ).  Parameters are as follows:

     default     Packets not matched by  another  queue  are  assigned to this
                 one.  Exactly one default queue is required.

     red          Enable  RED  (Random  Early  Detection) on this
queue.  RED drops
                 packets with a probability proportional  to  the
average queue

     rio          Enables  RIO  on  this  queue.  RIO is RED with
IN/OUT, thus running
 RED two times more than RIO  would  achieve
the same effect.
   RIO  is  currently  not supported in the
GENERIC kernel.

     ecn         Enables ECN (Explicit  Congestion  Notification)
on this queue.
                 ECN implies RED.

     The cbq scheduler supports an additional option:

     borrow       The queue can borrow bandwidth from the parent.

     The hfsc scheduler supports some additional options:

     realtime <sc>
                 The minimum required bandwidth for the queue.

     upperlimit <sc>
                 The maximum allowed bandwidth for the queue.

     linkshare <sc>
                 The bandwidth share of a backlogged queue.

     <sc> is an acronym for service curve.

     The format for service curve specifications is (m1, d,  m2).
m2 controls
     the  bandwidth assigned to the queue.  m1 and d are optional
and can be
     used to control the initial bandwidth assignment.   For  the
first d milliseconds
  the  queue gets the bandwidth given as m1, afterwards the value
     given in m2.

     Furthermore, with cbq and hfsc, child queues can  be  specified as in an
     altq  declaration,  thus  building  a tree of queues using a
part of their
     parent's bandwidth.

     Packets can be assigned to queues based on filter  rules  by
using the
     queue keyword.  Normally only one queue is specified; when a
second one
     is specified it will instead be used for packets which  have
a TOS of
     lowdelay and for TCP ACKs with no data payload.

     To  continue  the previous example, the examples below would
specify the
     four referenced queues, plus a few child  queues.   Interactive ssh(1) sessions
  get  priority  over  bulk  transfers  like scp(1) and
sftp(1).  The
     queues may then be referenced by filtering rules (see PACKET

     queue std bandwidth 10% cbq(default)
     queue   http   bandwidth  60%  priority  2  cbq(borrow  red)
{ employees, developers }
     queue  developers bandwidth 75% cbq(borrow)
     queue  employees bandwidth 15%
     queue mail bandwidth 10% priority 0 cbq(borrow ecn)
     queue  ssh  bandwidth  20%  cbq(borrow)  {  ssh_interactive,
ssh_bulk }
     queue  ssh_interactive priority 7
     queue  ssh_bulk priority 0

     block return out on dc0 inet all queue std
     pass  out  on dc0 inet proto tcp from $developerhosts to any
port 80            keep state queue developers
     pass out on dc0 inet proto tcp from  $employeehosts  to  any
port 80            keep state queue employees
     pass  out  on  dc0  inet  proto  tcp from any to any port 22
keep state queue(ssh_bulk, ssh_interactive)
     pass out on dc0 inet proto tcp  from  any  to  any  port  25
keep state queue mail

TRANSLATION    [Toc]    [Back]

     Translation  rules  modify  either the source or destination
address of the
     packets associated with a stateful connection.   A  stateful
connection is
     automatically  created to track packets matching such a rule
as long as
     they are not blocked by the filtering  section  of  pf.conf.
The translation
  engine  modifies  the specified address and/or port in
the packet, recalculates
 IP, TCP and UDP checksums as necessary, and passes it to the
     packet filter for evaluation.

     Since  translation occurs before filtering the filter engine
will see
     packets as they look after any addresses and ports have been
     Filter  rules  will  therefore  have  to filter based on the
translated address
 and port number.  Packets  that  match  a  translation
rule are only
     automatically  passed  if the pass modifier is given, otherwise they are
     still subject to block and pass rules.

     The state entry created permits pf(4) to keep track  of  the
original address
  for  traffic associated with that state and correctly
direct return
     traffic for that connection.

     Various types of translation are possible with pf:

           A binat rule specifies a bidirectional mapping between
an external
           IP netblock and an internal IP netblock.

     nat    A  nat  rule  specifies  that  IP addresses are to be
changed as the
           packet traverses the given interface.  This  technique
allows one or
           more  IP  addresses on the translating host to support
network traffic
 for a larger range of machines on an "inside" network.  Although
 in theory any IP address can be used on the inside, it is
           strongly recommended that one of  the  address  ranges
defined by RFC
           1918 be used.  These netblocks are:

  - (all of net 10, i.e., 10/8)
  - (i.e., 172.16/12)
  - (i.e., 192.168/16)

     rdr    The  packet  is redirected to another destination and
possibly a different
 port.  rdr rules can  optionally  specify  port
ranges instead
           of  single  ports.  rdr ... port 2000:2999 -> ... port
4000 redirects
           ports 2000 to 2999 (inclusive) to port 4000.  rdr  ...
           2000:2999  ->  ...  port 4000:* redirects port 2000 to
4000, 2001 to
           4001, ..., 2999 to 4999.

     In addition to modifying the address, some translation rules
may modify
     source  or  destination  ports  for tcp(4) or udp(4) connections; implicitly
     in the case of nat rules and explicitly in the case  of  rdr
rules.  Port
     numbers are never translated with a binat rule.

     For each packet processed by the translator, the translation
rules are
     evaluated in sequential order,  from  first  to  last.   The
first matching
     rule decides what action is taken.

     The  no option prefixed to a translation rule causes packets
to remain untranslated,
 much in the same way as drop quick works in  the
packet filter
     (see  below).  If no rule matches the packet it is passed to
the filter
     engine unmodified.

     Translation rules apply only to packets  that  pass  through
the specified
     interface,  and if no interface is specified, translation is
applied to
     packets on all interfaces.  For instance,  redirecting  port
80 on an external
  interface  to  an internal web server will only work
for connections
     originating from the outside.  Connections to the address of
the external
     interface  from  local  hosts  will not be redirected, since
such packets do
     not actually pass through the external interface.   Redirections cannot
     reflect  packets  back through the interface they arrive on,
they can only
     be redirected to hosts connected to different interfaces  or
to the firewall

     Note  that  redirecting external incoming connections to the
loopback address,
 as in

           rdr on ne3 inet proto tcp to port  8025  ->
port 25

     will  effectively  allow an external host to connect to daemons bound solely
 to the loopback address,  circumventing  the  traditional
blocking of
     such connections on a real interface.  Unless this effect is
desired, any
     of the local non-loopback addresses should be used as  redirection target
     instead,  which  allows external connections only to daemons
bound to this
     address or not bound to any address.


PACKET FILTERING    [Toc]    [Back]

     pf(4) has the ability to block and pass packets based on attributes of
     their  layer  3  (see  ip(4)  and  ip6(4))  and layer 4 (see
icmp(4), icmp6(4),
     tcp(4), udp(4)) headers.  In addition, packets may  also  be
assigned to
     queues for the purpose of bandwidth control.

     For  each  packet processed by the packet filter, the filter
rules are
     evaluated in sequential order, from first to last.  The last
     rule decides what action is taken.

     The following actions can be used in the filter:

           The  packet is blocked.  There are a number of ways in
which a block
           rule can behave when blocking a packet.   The  default
behaviour is
           to drop packets silently, however this can be overridden or made
           explicit either globally, by setting the  block-policy
option, or on
           a per-rule basis with one of the following options:

           drop  The packet is silently dropped.
                 This  applies only to tcp(4) packets, and issues
                 which closes the connection.
                 This causes ICMP messages  to  be  returned  for
packets which
                 match  the rule.  By default this is an ICMP UNREACHABLE message,
 however this can be overridden by specifying a message
                 as a code or number.
                 This  causes a TCP RST to be returned for tcp(4)
packets and
                 an ICMP UNREACHABLE for UDP and other packets.

           Options returning packets have no effect if pf(4)  operates on a

     pass  The packet is passed.

     If no rule matches the packet, the default action is pass.

     To  block  everything  by default and only pass packets that
match explicit
     rules, one uses

           block all

     as the first filter rule.

     See FILTER EXAMPLES below.

PARAMETERS    [Toc]    [Back]

     The rule parameters specify the packets to which a rule  applies.  A packet
  always  comes in on, or goes out through, one interface.
Most parameters
 are optional.  If a parameter is  specified,  the  rule
only applies to
     packets with matching attributes.  Certain parameters can be
expressed as
     lists, in which case pfctl(8) generates all needed rule combinations.

     in or out
           This rule applies to incoming or outgoing packets.  If
neither in
           nor out are specified, the rule will match packets  in
both directions.

     log    In addition to the action specified, a log message is
           All packets for that connection are logged, unless the
keep state,
           modulate  state  or  synproxy state options are specified, in which
           case only the packet that  establishes  the  state  is
logged.  (See
           keep  state, modulate state and synproxy state below).
The logged
           packets are sent to the pflog(4) interface.  This  interface is monitored
  by  the  pflogd(8) logging daemon, which dumps
the logged
           packets to the file /var/log/pflog in  pcap(3)  binary

           Used with keep state, modulate state or synproxy state
rules to
           force logging of all packets  for  a  connection.   As
with log, packets
 are logged to pflog(4).

           If  a packet matches a rule which has the quick option
set, this
           rule is considered the last matching rule, and evaluation of subsequent
 rules is skipped.

     on <interface>
           This rule applies only to packets coming in on, or going out
           through, this particular interface.  It is also possible to simply
           give  the  interface  driver name, like ppp or fxp, to
make the rule
           match packets flowing through a group of interfaces.

     <af>  This rule applies only to packets of this address family.  Supported
 values are inet and inet6.

     proto <protocol>
           This  rule  applies  only to packets of this protocol.
Common protocols
 are icmp(4), icmp6(4), tcp(4), and udp(4).  For a
list of all
           the protocol name to number mappings used by pfctl(8),
see the file

     from <source> port  <source>  os  <source>  to  <dest>  port
           This  rule  applies only to packets with the specified
source and
           destination addresses and ports.

           Addresses can be specified in CIDR notation  (matching
           as  symbolic  host names or interface names, or as any
of the following

           any           Any address.
           no-route       Any  address  which  is  not  currently
           <table>        Any  address  that  matches  the  given

           Interface names can have modifiers appended:

           :network      Translates to the network(s) attached to
the interface.

           :broadcast     Translates to the interface's broadcast
           :peer         Translates to the point to point  interface's peer address(es).

           :0            Do not include interface aliases.

           Host names may also have the :0 option appended to restrict the
           name resolution to the first of each v4 and v6 address

           Host name resolution and interface to address translation are done
           at ruleset load-time.  When the address of  an  interface (or host
           name)  changes  (under DHCP or PPP, for instance), the
ruleset must
           be reloaded for the change to be reflected in the kernel.  Surrounding
  the  interface name (and optional modifiers)
in parentheses
           changes this behaviour.  When the  interface  name  is
surrounded by
           parentheses, the rule is automatically updated whenever the interface
 changes its address.  The ruleset does  not  need
to be reloaded.
  This is especially useful with nat.

           Ports  can  be  specified either by number or by name.
For example,
           port 80 can be specified as www.  For a  list  of  all
port name to
           number   mappings  used  by  pfctl(8),  see  the  file

           Ports and ranges of ports are specified by using these

                 =       (equal)
                 !=      (unequal)
                 <       (less than)
                 <=      (less than or equal)
                 >       (greater than)
                 >=      (greater than or equal)
                 :       (range including boundaries)
                 ><      (range excluding boundaries)
                 <>      (except range)

           ><, <> and : are binary operators (they take two arguments).  For

           port 2000:2004
                       means `all ports >=  2000  and  <=  2004',
hence ports
                       2000, 2001, 2002, 2003 and 2004.

           port 2000 >< 2004
                       means `all ports > 2000 and < 2004', hence
ports 2001,
                       2002 and 2003.

           port 2000 <> 2004
                       means `all ports < 2000 or > 2004',  hence
ports 1-1999
                       and 2005-65535.

           The  operating system of the source host can be specified in the
           case of TCP rules  with  the  OS  modifier.   See  the
           FINGERPRINTING section for more information.

           The  host, port and OS specifications are optional, as
in the following

                 pass in all
                 pass in from any to any
                 pass in proto tcp from any port <= 1024 to any
                 pass in proto tcp from any to any port 25
                 pass in proto tcp from  port  >  1024
to ! port != ssh
                 pass  in  proto  tcp from any os "OpenBSD" flags

     all   This is equivalent to "from any to any".

     group <group>
           Similar to user, this rule only applies to packets  of
sockets owned
           by the specified group.

     user <user>
           This  rule only applies to packets of sockets owned by
the specified
           user.  For outgoing  connections  initiated  from  the
firewall, this
           is  the user that opened the connection.  For incoming
           to the firewall itself, this is the user that  listens
on the destination
  port.   For  forwarded  connections, where the
firewall is not
           a connection endpoint, the user and group are unknown.

           All  packets,  both outgoing and incoming, of one connection are associated
 with the same user and group.  Only  TCP  and
UDP packets
           can  be  associated  with  users;  for other protocols
these parameters
           are ignored.

           User and group refer to the effective (as  opposed  to
the real) IDs,
           in  case the socket is created by a setuid/setgid process.  User and
           group IDs are stored when a socket is created; when  a
process creates
  a  listening  socket  as  root (for instance, by
binding to a
           privileged port) and subsequently changes  to  another
user ID (to
           drop privileges), the credentials will remain root.

           User  and group IDs can be specified as either numbers
or names.
           The syntax is similar to the one for ports.  The value
           matches packets of forwarded connections.  unknown can
only be used
           with the operators = and !=.   Other  constructs  like
user >= unknown
           are  invalid.  Forwarded packets with unknown user and
group ID
           match  only  rules  that  explicitly  compare  against
unknown with the
           operators  =  or  !=.  For instance user >= 0 does not
match forwarded
           packets.  The following example allows  only  selected
users to open
           outgoing connections:

                 block out proto { tcp, udp } all
                 pass     out    proto   {   tcp,   udp   }   all
user { < 1000, dhartmei } keep state

     flags <a>/<b> | /<b>
           This rule only applies to TCP packets  that  have  the
flags <a> set
           out  of  set  <b>.  Flags not specified in <b> are ignored.  The flags
           are: (F)IN, (S)YN, (R)ST, (P)USH, (A)CK, (U)RG, (E)CE,
and C(W)R.

           flags  S/S   Flag SYN is set.  The other flags are ignored.

           flags S/SA  Out of SYN and ACK,  exactly  SYN  may  be
set.  SYN,
                       SYN+PSH  and  SYN+RST  match, but SYN+ACK,
                       do not.  This is more restrictive than the
previous example.

           flags /SFRA
                       If  the first set is not specified, it defaults to none.
                       All of SYN, FIN, RST and ACK must  be  unset.

     icmp-type <type> code <code>

     icmp6-type <type> code <code>
           This  rule only applies to ICMP or ICMPv6 packets with
the specified
           type and code.  This parameter is only valid for rules
that cover
           protocols  ICMP  or  ICMP6.  The protocol and the ICMP
type indicator
           (icmp-type or icmp6-type) must match.

           By default,  packets  which  contain  IP  options  are
blocked.  When
           allow-opts  is specified for a pass rule, packets that
pass the filter
 based on that rule (last matching) do so  even  if
they contain
           IP  options.   For  packets that match state, the rule
that initially
           created the state is used.   The  implicit  pass  rule
that is used
           when  a packet does not match any rules does not allow
IP options.

     label <string>
           Adds a label (name) to the rule, which can be used  to
identify the
           rule.   For  instance,  pfctl -s labels shows per-rule
statistics for
           rules that have labels.

           The following macros can be used in labels:

                 $if       The interface.
                 $srcaddr  The source IP address.
                 $dstaddr  The destination IP address.
                 $srcport  The source port specification.
                 $dstport  The destination port specification.
                 $proto    The protocol name.
                 $nr       The rule number.

           For example:

                 ips = "{, }"
                 pass   in   proto   tcp   from   any   to   $ips
port > 1023 label "$dstaddr:$dstport"

           expands to

                 pass  in  inet  proto  tcp  from  any to
port > 1023 label ">1023"
                 pass in inet  proto  tcp  from  any  to
port > 1023 label ">1023"

           The macro expansion for the label directive occurs only at configuration
 file parse time, not during runtime.

     queue <queue> | (<queue>, <queue>)
           Packets matching this rule will  be  assigned  to  the
specified queue.
           If  two  queues are given, packets which have a tos of
lowdelay and
           TCP ACKs with no data payload will be assigned to  the
second one.
           See QUEUEING for setup details.

           For example:

                 pass in proto tcp to port 25 queue mail
                 pass  in  proto  tcp  to port 22 queue(ssh_bulk,

     tag <string>
           Packets matching this rule will  be  tagged  with  the
           string.   The  tag acts as an internal marker that can
be used to
           identify these packets later on.  This  can  be  used,
for example, to
           provide  trust  between interfaces and to determine if
packets have
           been  processed  by  translation  rules.    Tags   are
"sticky", meaning
           that the packet will be tagged even if the rule is not
the last
           matching rule.  Further matching rules can replace the
tag with a
           new  one but will not remove a previously applied tag.
A packet is
           only ever assigned one tag at a time.  pass rules that
use the tag
           keyword  must  also  use keep state, modulate state or
synproxy state.
           Packet tagging can be done during nat, rdr,  or  binat
rules in addition
  to  filter  rules.  Tags take the same macros as
labels (see

     tagged <string>
           Used with filter rules to specify  that  packets  must
already be
           tagged  with the given tag in order to match the rule.
Inverse tag
           matching can also be done by specifying the ! operator
before the
           tagged keyword.

     probability <number>
           A  probability  attribute  can  be attached to a rule,
with a value set
           between 0 and 1, bounds not included.  In  that  case,
the rule will
           be  honoured  using  the given probability value only.
For example,
           the following rule will  drop  20%  of  incoming  ICMP

                 block in proto icmp probability 20%

ROUTING    [Toc]    [Back]

     If  a  packet  matches  a  rule with a route option set, the
packet filter
     will route the packet according to the type of route option.
When such a
     rule  creates state, the route option is also applied to all
     matching the same connection.

           The fastroute option does a  normal  route  lookup  to
find the next
           hop for the packet.

           The route-to option routes the packet to the specified
           with an optional address for the  next  hop.   When  a
route-to rule
           creates  state, only packets that pass in the same direction as the
           filter rule specifies will  be  routed  in  this  way.
Packets passing
           in  the  opposite direction (replies) are not affected
and are routed

           The reply-to option is similar to route-to, but routes
packets that
           pass in the opposite direction (replies) to the specified interface.
  Opposite direction is only defined in the  context of a state
           entry,  and reply-to is useful only in rules that create state.  It
           can be used on systems with multiple external  connections to route
           all  outgoing  packets of a connection through the interface the incoming
 connection arrived through  (symmetric  routing

           The  dup-to  option  creates a duplicate of the packet
and routes it
           like route-to.  The original packet gets routed as  it

POOL OPTIONS    [Toc]    [Back]

     For  nat  and  rdr  rules,  (as  well  as  for the route-to,
reply-to and dup-to
     rule options) for which there is a  single  redirection  address which has a
     subnet  mask  smaller than 32 for IPv4 or 128 for IPv6 (more
than one IP
     address), a variety of different methods for assigning  this
address can
     be used:

           The  bitmask option applies the network portion of the
           address to the address to  be  modified  (source  with
nat, destination
           with rdr).

           The  random option selects an address at random within
the defined
           block of addresses.

           The source-hash option uses a hash of the  source  address to determine
  the redirection address, ensuring that the redirection address
           is always the same for a given  source.   An  optional
key can be
           specified  after  this  keyword  either in hex or as a
string; by default
 pfctl(8) randomly generates a  key  for  sourcehash every time
           the ruleset is reloaded.

           The  round-robin  option loops through the redirection

           When more than one redirection address  is  specified,
round-robin is
           the only permitted pool type.

           With  nat rules, the static-port option prevents pf(4)
from modifying
 the source port on TCP and UDP packets.

     Additionally, the sticky-address option can be specified  to
help ensure
     that multiple connections from the same source are mapped to
the same
     redirection address.  This  option  can  be  used  with  the
random and round-
     robin pool options.  Note that by default these associations
are destroyed
 as soon as there are no longer states which refer to
them; in order
  to  make  the  mappings last beyond the lifetime of the
states, increase
     the  global  options  with  set  timeout  source-track   See
     OPTIONS for more ways to control the source tracking.


     pf(4)  is a stateful packet filter, which means it can track
the state of
     a connection.  Instead of passing all traffic  to  port  25,
for instance,
     it is possible to pass only the initial packet, and then begin to keep
     state.  Subsequent traffic will flow because the  filter  is
aware of the

     If  a  packet matches a pass ... keep state rule, the filter
creates a
     state for this connection and automatically  lets  pass  all
     packets of that connection.

     Before  any  rules  are evaluated, the filter checks whether
the packet
     matches any state.  If it does, the packet is passed without
     of any rules.

     States  are  removed  after  the connection is closed or has
timed out.

     This has several advantages.  Comparing a packet to a  state
     checking  its sequence numbers.  If the sequence numbers are
outside the
     narrow windows of expected values, the  packet  is  dropped.
This prevents
     spoofing  attacks,  such  as  when an attacker sends packets
with a fake
     source address/port but does not know the  connection's  sequence numbers.

     Also,  looking  up  states is usually faster than evaluating
rules.  If
     there are 50 rules, all of them are  evaluated  sequentially
in O(n).  Even
     with 50000 states, only 16 comparisons are needed to match a
state, since
     states are stored  in  a  binary  search  tree  that  allows
searches in O(log2

     For instance:

           block all
           pass  out  proto  tcp  from any to any flags S/SA keep
           pass in  proto tcp from any to any port 25 flags  S/SA
keep state

     This  ruleset  blocks  everything by default.  Only outgoing
connections and
     incoming connections to port 25 are  allowed.   The  initial
packet of each
     connection  has the SYN flag set, will be passed and creates
state.  All
     further packets of these  connections  are  passed  if  they
match a state.

     By  default,  packets coming in and out of any interface can
match a state,
     but it is also possible to change that behaviour by  assigning states to a
     single interface or a group of interfaces.

     The  default  policy is specified by the state-policy global
option, but
     this can be adjusted on a per-rule basis by  adding  one  of
the if-bound,
     group-bound  or  floating keywords to the keep state option.
For example,
     if a rule is defined as:

           pass out on  ppp  from  any  to  10.12/16  keep  state

     A  state  created on ppp0 would match packets an all PPP interfaces, but
     not packets flowing through fxp0 or any other interface.

     Keeping rules floating is the more flexible option when  the
firewall is
     in  a  dynamic  routing environment.  However, this has some
security implications
 since a state created by one trusted  network  could
allow potentially
 hostile packets coming in from other interfaces.

     Specifying  flags  S/SA restricts state creation to the initial SYN packet
     of the TCP handshake.  One can also be less restrictive, and
allow state
     creation  from  intermediate  (non-SYN)  packets.  This will
cause pf(4) to
     synchronize to existing connections,  for  instance  if  one
flushes the
     state table.

     For  UDP, which is stateless by nature, keep state will create state as
     well.  UDP packets are matched to states using only host addresses and

     ICMP messages fall into two categories: ICMP error messages,
which always
     refer to a TCP or UDP packet, are matched  against  the  referred to connection.
   If  one keeps state on a TCP connection, and an ICMP
source quench
     message referring to this TCP connection arrives, it will be
matched to

 Similar pages
Name OS Title
pfopen Tru64 Open a packet filter file
ppp.Filter HP-UX PPP packet filter specification file format
PPP.FILTER HP-UX PPP packet filter specification file format
ppp.filter HP-UX PPP packet filter specification file format
ipfstat FreeBSD reports on packet filter statistics and filter list
ifaccess.conf Tru64 Interface access filter configuration file
ldapfilter.conf Linux configuration file for LDAP get filter routines
pf OpenBSD packet filter
pfil_add_hook FreeBSD packet filter interface
pfil FreeBSD packet filter interface
Copyright © 2004-2005 DeniX Solutions SRL
newsletter delivery service