home | help
PF.CONF(5)		       File Formats Manual		      PF.CONF(5)

NAME
     pf.conf -- packet filter configuration file

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

STATEMENT ORDER
     There are seven types of statements in pf.conf:

     Macros
	   User-defined variables may be defined and used later, simplifying the
	   configuration file.	Macros must be defined before  they  are  refer-
	   enced in pf.conf.

     Tables
	   Tables  provide a mechanism for increasing the performance and flexi-
	   bility of rules with large  numbers	of  source  or	destination  ad-
	   dresses.

     Options
	   Options tune the behaviour of the packet filtering engine.

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

     Queueing
	   Queueing provides rule-based bandwidth control.

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

     Packet Filtering
	   Packet filtering provides rule-based 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
     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 quotes.

     For example,

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

TABLES
     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, atomically.  Table
	       definitions inside pf.conf use the table statement, and are espe-
	       cially useful to define non-persistent tables.  The contents of a
	       pre-existing table defined without a list of  addresses	to  ini-
	       tialize	it  is not altered when pf.conf is loaded.  A table ini-
	       tialized 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 auto-
	      matically 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 204.92.77.111

     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 "/etc/openrelays"
	   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 ta-
     ble, 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, a valid interface group or the self keyword, in which  case	all  ad-
     dresses assigned to the interface(s) will be added to the table.

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

     set timeout

	   interval   Interval between purging expired states and fragments.
	   frag       Seconds before an unassembled fragment is expired.
	   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  proto.modifier  which
	   corresponds	to the connection state.  Each packet which matches this
	   state will reset the TTL.  Tuning these values may improve  the  per-
	   formance  of  the firewall at the risk of dropping valid idle connec-
	   tions.

	   tcp.first
		 The state after the first packet.
	   tcp.opening
		 The state before the destination host ever sends a packet.
	   tcp.established
		 The fully established state.
	   tcp.closing
		 The state after the first FIN has been sent.
	   tcp.finwait
		 The state after both FINs have been exchanged and  the  connec-
		 tion  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.
	   tcp.closed
		 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:

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

	   Other protocols are handled similarly to UDP:

	   other.first
	   other.single
	   other.multiple

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

	   adaptive.start
		 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  -
		 adaptive.start).
	   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 below).

	   Adaptive  timeouts  are  enabled  by  default, with an adaptive.start
	   value equal to 60% of the state  limit,  and  an  adaptive.end  value
	   equal  to  120%  of the state limit.  They can be disabled by setting
	   both adaptive.start and adaptive.end to 0.

	   The adaptive timeout 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
	   states.

	   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 dc0:

		 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
	   zone(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 pass rules which do not specify no state)
	   to 20000.  Using

		 set limit frags 20000

	   sets  the maximum number of entries in the memory pool used for frag-
	   ment reassembly (generated by scrub rules) to 20000.  Using

		 set limit src-nodes 2000

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

		 set limit tables 1000
		 set limit table-entries 100000

	   sets limits on the memory pools used by tables.  The first limits the
	   number of tables that can exist to 1000.  The second limits the over-
	   all number of addresses that can be stored in tables to 100000.

	   Various limits can be combined on a single line:

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

     set ruleset-optimization
	   none      Disable  the ruleset optimizer.  This is the default behav-
		     iour.
	   basic     Enable basic ruleset optimization, which does  four  things
		     to improve the performance of ruleset evaluations:

		     1.   remove duplicate rules
		     2.   remove rules that are a subset of another rule
		     3.   combine multiple rules into a table when advantageous
		     4.   re-order the rules to improve evaluation performance

	   profile   Uses  the currently loaded ruleset as a feedback profile to
		     tailor the ordering of quick rules to actual network  traf-
		     fic.

	   It  is  important  to note that the ruleset optimizer will modify the
	   ruleset to improve performance.  A side effect of the ruleset modifi-
	   cation is that per-rule accounting  statistics  will  have  different
	   meanings  than  before.   If  per-rule  accounting  is  important for
	   billing purposes or whatnot, either the ruleset optimizer should  not
	   be  used  or  a  label field should be added to all of the accounting
	   rules to act as optimization barriers.

	   Optimization can also be set as a command-line argument to  pfctl(8),
	   overriding the settings in pf.conf.

     set optimization
	   Optimize  state  timeouts  for  one of the following network environ-
	   ments:

	   normal
		 A normal network environment.	Suitable  for  almost  all  net-
		 works.
	   high-latency
		 A high-latency environment (such as a satellite connection).
	   satellite
		 Alias for high-latency.
	   aggressive
		 Aggressively  expire  connections.  This can greatly reduce the
		 memory usage of the firewall at the cost of dropping idle  con-
		 nections early.
	   conservative
		 Extremely  conservative  settings.   Avoid  dropping legitimate
		 connections at the expense of greater memory utilization  (pos-
		 sibly	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 UN-
		     REACHABLE 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 states:

	   if-bound	States are bound to interface.
	   floating	States	can  match  packets  on  any interfaces (the de-
			fault).

	   For example:

		 set state-policy if-bound

     set hostid
	   The 32-bit hostid identifies this firewall's state table  entries  to
	   other  firewalls  in  a  pfsync(4)  failover cluster.  By default the
	   hostid is set to a pseudo-random value, however it may  be  desirable
	   to  manually  configure  it,  for example to more easily identify the
	   source of state table entries.

		 set hostid 1

	   The hostid may be specified in either decimal or hexadecimal.

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

     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 fin-
	   gerprints referenced by the currently active ruleset are inconsistent
	   until the new ruleset finishes loading.

	   For example:

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

     set skip on <ifspec>
	   List interfaces for which packets should not  be  filtered.	 Packets
	   passing  in	or  out  on such interfaces are passed as if pf was dis-
	   abled, i.e. pf does not process them in any way.  This can be  useful
	   on  loopback  and  other virtual interfaces, when packet filtering is
	   not desired and can have unexpected effects.  For example:

		 set skip on lo0

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

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

TRAFFIC NORMALIZATION
     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:

     no-df
	   Clears the dont-fragment bit from a matching IP packet.  Some operat-
	   ing	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 spec-
	   ified.

	   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 delete-
	   rious results if an upstream router later fragments the packet.   Us-
	   ing	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.

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

     fragment reassemble
	   Using scrub rules, fragments can be reassembled by normalization.  In
	   this  case, fragments are buffered until they form a complete packet,
	   and only the completed packet is passed on to the filter.  The advan-
	   tage 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  occurrence.   Unlike  the
	   fragment  reassemble  modifier,  fragments are not 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 well.

     reassemble tcp
	   Statefully  normalizes  TCP	connections.  scrub reassemble tcp rules
	   may not have the direction (in/out) specified.  reassemble  tcp  per-
	   forms 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.
	   timestamp 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  time-
		    stamp 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  time.   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 con-
		    nection to wrap its 32-bit sequence space.	In such  an  oc-
		    currence,  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  time-
		    stamp  on each packet does not go backwards.  reassemble tcp
		    also makes sure the timestamp on the packet does not go for-
		    ward more than the RFC allows.  By doing this, pf(4) artifi-
		    cially extends the security of TCP sequence numbers by 10 to
		    18 bits when the host uses	appropriately  randomized  time-
		    stamps, since a blind attacker would have to guess the time-
		    stamp as well.

     For example,

	   scrub in on $ext_if all fragment reassemble

     The  no  option  prefixed to a scrub rule causes matching packets to remain
     unscrubbed, much in the same way as drop quick works in the  packet  filter
     (see below).  This mechanism should be used when it is necessary to exclude
     specific packets from broader scrub rules.

QUEUEING/ALTQ
     The  ALTQ	system	is  currently not available in the GENERIC kernel nor as
     loadable modules.	In order to use the herein after called queueing options
     one has to use a custom built kernel.  Please refer  to  altq(4)  to  learn
     about the related kernel options.

     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 three 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 partitioning and  sharing	of  link
	   bandwidth  by  hierarchically structured classes.  Each class has its
	   own queue and is assigned its share of 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 interface, 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:

     <interface>
	   Queueing is enabled on the named interface.

     <scheduler>
	   Specifies which queueing scheduler to use.  Currently supported  val-
	   ues	are cbq for Class Based Queueing, priq for Priority Queueing and
	   hfsc for the Hierarchical Fair Service Curve scheduler.

     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 ab-
	   solute value or as a percentage of the interface bandwidth.	When us-
	   ing an absolute value, the suffixes b, Kb, Mb, and  Gb  are	used  to
	   represent  bits, kilobits, megabits, and gigabits per second, respec-
	   tively.  The value must  not  exceed  the  interface  bandwidth.   If
	   bandwidth is not specified, the interface bandwidth is used (but take
	   note  that  some interfaces do not know their bandwidth, or can adapt
	   their bandwidth rates).

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

     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  se-
     quence  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, ex-
     cept 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 op-
	   erates 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 speci-
	   fied as an absolute value or a percentage of the parent queue's band-
	   width.   If	not  specified,  defaults  to 100% of the parent queue's
	   bandwidth.  The priq scheduler does not support bandwidth  specifica-
	   tion.

     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 50.

     The    scheduler	can   get   additional	 parameters   with   <scheduler>
     (<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
		 length.

     rio	 Enables  RIO  on this queue.  RIO is RED with IN/OUT, thus run-
		 ning 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 speci-
     fied  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 FILTERING" below).

     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 bandwidth 50% priority 7 cbq(borrow)
     queue  ssh_bulk bandwidth 50% priority 0 cbq(borrow)

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

TRANSLATION
     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  en-
     gine 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  pack-
     ets  as they look after any addresses and ports have been translated.  Fil-
     ter 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:

     binat
	   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 rec-
	   ommended that one of the address ranges defined by RFC 1918 be  used.
	   These netblocks are:

	   10.0.0.0 - 10.255.255.255 (all of net 10, i.e., 10/8)
	   172.16.0.0 - 172.31.255.255 (i.e., 172.16/12)
	   192.168.0.0 - 192.168.255.255 (i.e., 192.168/16)

     rdr   The	packet	is redirected to another destination and possibly a dif-
	   ferent 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 ... port 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  num-
     bers are never translated with a binat rule.

     Evaluation  order	of the translation rules is dependent on the type of the
     translation rules and of the direction of a packet.  binat rules are always
     evaluated first.  Then either the rdr rules are  evaluated  on  an  inbound
     packet  or the nat rules on an outbound packet.  Rules of the same type are
     evaluated in the same order in which they appear in the ruleset.  The first
     matching rule decides what action is taken.

     The no option prefixed to a translation rule causes packets to  remain  un-
     translated,  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  en-
     gine unmodified.

     Translation rules apply only to packets that pass through the specified in-
     terface,  and if no interface is specified, translation is applied to pack-
     ets on all interfaces.  For instance, redirecting port 80	on  an	external
     interface	to  an internal web server will only work for connections origi-
     nating from the outside.  Connections to the address of the external inter-
     face from local hosts will not be redirected, since such packets do not ac-
     tually pass through the external interface.   Redirections  cannot  reflect
     packets  back  through the interface they arrive on, they can only be redi-
     rected to hosts connected to different interfaces or to  the  firewall  it-
     self.

     Note  that  redirecting  external	incoming connections to the loopback ad-
     dress, as in

	   rdr on ne3 inet proto tcp to port spamd -> 127.0.0.1 port smtp

     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.

     See "TRANSLATION EXAMPLES" below.

PACKET FILTERING
     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 evalu-
     ated  in  sequential order, from first to last.  The last matching rule de-
     cides what action is taken.  If no rule matches the packet, the default ac-
     tion is to pass the packet.

     The following actions can be used in the filter:

     block
	   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  ex-
	   plicit  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.
	   return-rst
		 This applies only to tcp(4) packets, and issues a TCP RST which
		 closes the connection.
	   return-icmp
	   return-icmp6
		 This causes ICMP messages to  be  returned  for  packets  which
		 match	the  rule.   By default this is an ICMP UNREACHABLE mes-
		 sage, however this can be overridden by specifying a message as
		 a code or number.
	   return
		 This causes a TCP RST to be returned for tcp(4) packets and  an
		 ICMP UNREACHABLE for UDP and other packets.

	   Options  returning ICMP packets currently have no effect if pf(4) op-
	   erates on a if_bridge(4), as the code to support this feature has not
	   yet been implemented.

	   The simplest mechanism to block everything by default and  only  pass
	   packets that match explicit rules is specify a first filter rule of:

		 block all

     pass  The	packet is passed; state is created state unless the no state op-
	   tion is specified.

     By default pf(4) filters  packets	statefully;  the  first  time  a  packet
     matches  a  pass rule, a state entry is created; for subsequent packets the
     filter checks whether the packet matches any state.  If it does, the packet
     is passed without evaluation of any rules.  After the connection is  closed
     or times out, the state entry is automatically removed.

     This  has several advantages.  For TCP connections, comparing a packet to a
     state involves checking its sequence numbers, as well as TCP timestamps  if
     a scrub reassemble tcp rule applies to the connection.  If these values 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  num-
     bers.  Similarly, pf(4) knows how to match ICMP replies to states.  For ex-
     ample,

	   pass out inet proto icmp all icmp-type echoreq

     allows echo requests (such as those created by ping(8)) out statefully, and
     matches incoming echo replies correctly to states.

     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 n).

     Furthermore,  correct  handling  of ICMP error messages is critical to many
     protocols, particularly TCP.  pf(4) matches ICMP error messages to the cor-
     rect connection, checks them against connection parameters, and passes them
     if appropriate.  For example if an ICMP source quench message referring  to
     a	stateful TCP connection arrives, it will be matched to the state and get
     passed.

     Finally, state tracking is required for nat, binat and rdr rules, in  order
     to  track	address and port translations and reverse the translation on re-
     turning packets.

     pf(4) will also create state for  other  protocols  which	are  effectively
     stateless by nature.  UDP packets are matched to states using only host ad-
     dresses and ports, and other protocols are matched to states using only the
     host addresses.

     If  stateless filtering of individual packets is desired, the no state key-
     word can be used to specify that state will not be created if this  is  the
     last  matching  rule.  A number of parameters can also be set to affect how
     pf(4) handles state tracking.  See "STATEFUL TRACKING  OPTIONS"  below  for
     further details.

PARAMETERS
     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 pack-
     ets 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 generated.
	   Only the packet that establishes the state is logged, unless  the  no
	   state option is specified.  The logged packets are sent to a pflog(4)
	   interface,  by  default  pflog0.   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 format.

     log (all)
	   Used  to  force logging of all packets for a connection.  This is not
	   necessary when no state is explicitly specified.  As with log,  pack-
	   ets are logged to pflog(4).

     log (user)
	   Logs the Unix user ID of the user that owns the socket and the PID of
	   the process that has the socket open where the packet is sourced from
	   or  destined to (depending on which socket is local).  This is in ad-
	   dition to the normal information logged.

	   Due to the problems described in the  BUGS  section	only  the  first
	   packet  logged  via	log  (all,  user) will have the user credentials
	   logged when using stateful matching.

     log (to <interface>)
	   Send logs to the specified pflog(4) interface instead of pflog0.

     quick
	   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 or interface group.  For  more  information
	   on interface groups, see the group keyword in ifconfig(8).

     <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
	   /etc/protocols.

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

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

	   any		   Any address.
	   route <label>   Any address whose associated route has label <label>.
			   See route(4) and route(8).
	   no-route	   Any address which is not currently routable.
	   urpf-failed	   Any	source address that fails a unicast reverse path
			   forwarding (URPF) check, i.e. packets coming in on an
			   interface other than that which holds the route  back
			   to the packet's source address.
	   <table>	   Any address that matches the given table.

	   Interface names can have modifiers appended:

	   :network	 Translates to the network(s) attached to the interface.
	   :broadcast	 Translates to the interface's broadcast address(es).
	   :peer	 Translates  to  the point to point interface's peer ad-
			 dress(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 found.

	   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  re-
	   loaded 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  ad-
	   dress.  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 num-
	   ber mappings used by pfctl(8), see the file /etc/services.

	   Ports and ranges of ports are specified by using these operators:

		 =	 (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 instance:

	   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 "OPERATING SYSTEM
	   FINGERPRINTING" section for more information.

	   The host, port and OS specifications are optional, as in the  follow-
	   ing examples:

		 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 10.0.0.0/8 port > 1024 \
		       to ! 10.1.2.3 port != ssh
		 pass in proto tcp from any os "OpenBSD"
		 pass in proto tcp from route "DTAG"

     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.

	   The use of group or user in debug.mpsafenet=1 environments may result
	   in a deadlock.  Please see the "BUGS" section for details.

     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 connections to the
	   firewall itself, this is the user that  listens  on	the  destination
	   port.  For forwarded connections, where the firewall is not a connec-
	   tion endpoint, the user and group are unknown.

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

	   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  privi-
	   leges), 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	unknown  matches
	   packets  of forwarded connections.  unknown can only be used with the
	   operators = and !=.	Other constructs like user >=  unknown	are  in-
	   valid.   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 connec-
	   tions:

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

     flags <a> /<b> | /<b> | any
	   This rule only applies to TCP packets that have the flags <a> set out
	   of  set  <b>.   Flags not specified in <b> are ignored.  For stateful
	   connections, the default is	flags  S/SA.   To  indicate  that  flags
	   should  not	be  checkd  at	all,  specify flags any.  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  This is the default  setting  for  stateful  connections.
		       Out of SYN and ACK, exactly SYN may be set.  SYN, SYN+PSH
		       and  SYN+RST  match, but SYN+ACK, ACK and ACK+RST 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.

	   Because  flags  S/SA is applied by default (unless no state is speci-
	   fied), only the initial SYN packet of a TCP handshake will  create  a
	   state  for  a TCP connection.  It is possible to be less restrictive,
	   and allow state creation  from  intermediate  (non-SYN)  packets,  by
	   specifying flags any.  This will cause pf(4) to synchronize to exist-
	   ing	connections,  for instance if one flushes the state table.  How-
	   ever, states created from such intermediate packets	may  be  missing
	   connection  details	such  as  the TCP window scaling factor.  States
	   which modify the packet flow, such as those affected by nat, binat or
	   rdr rules, modulate or  synproxy  state  options,  or  scrubbed  with
	   reassemble  tcp  will also not be recoverable from intermediate pack-
	   ets.  Such connections will stall and time out.

     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.   Text  names for ICMP types and codes are listed in
	   icmp(4) and icmp6(4).  This parameter is only valid	for  rules  that
	   cover  protocols ICMP or ICMP6.  The protocol and the ICMP type indi-
	   cator (icmp-type or icmp6-type) must match.

     tos <string> | <number>
	   This rule applies to packets with the specified TOS	bits  set.   TOS
	   may	be  given as one of lowdelay, throughput, reliability, or as ei-
	   ther hex or decimal.

	   For example, the following rules are identical:

		 pass all tos lowdelay
		 pass all tos 0x10
		 pass all tos 16

     allow-opts
	   By default, IPv4 packets with IP options or IPv6 packets with routing
	   extension headers 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 or routing  extension
	   headers.   For packets that match state, the rule that initially cre-
	   ated 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 = "{ 1.2.3.4, 1.2.3.5 }"
		 pass in proto tcp from any to $ips \
		       port > 1023 label "$dstaddr:$dstport"

	   expands to

		 pass in inet proto tcp from any to 1.2.3.4 \
		       port > 1023 label "1.2.3.4:>1023"
		 pass in inet proto tcp from any to 1.2.3.5 \
		       port > 1023 label "1.2.3.5:>1023"

	   The macro expansion for the label directive occurs only at configura-
	   tion 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/ALTQ" for setup details.

	   For example:

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

     tag <string>
	   Packets  matching this rule will be tagged with the specified 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.  Packet tagging can be done during nat, rdr, or  binat  rules
	   in  addition  to  filter  rules.  Tags take the same macros as labels
	   (see above).

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

     rtable <number>
	   Used to select an alternate routing table  for  the	routing  lookup.
	   Only  effective before the route lookup happened, i.e. when filtering
	   inbound.

     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 packets:

		 block in proto icmp probability 20%

ROUTING
     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 packets matching the
     same connection.

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

     route-to
	   The route-to option routes the packet to the specified interface 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  nor-
	   mally.

     reply-to
	   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 out-
	   going packets of a connection through the interface the incoming con-
	   nection arrived through (symmetric routing enforcement).

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

POOL OPTIONS
     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 ad-
     dress), a variety of different methods for assigning this	address  can  be
     used:

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

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

     source-hash
	   The source-hash option uses a hash of the source address to determine
	   the redirection address, ensuring that the redirection address is al-
	   ways  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 source-hash every time the ruleset is
	   reloaded.

     round-robin
	   The round-robin option loops through the redirection address(es).

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

     static-port
	   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 redi-
     rection  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 "STATEFUL TRACKING OPTIONS" for
     more ways to control the source tracking.

STATE MODULATION
     Much of the security derived from TCP is attributable to how well the  ini-
     tial  sequence  numbers  (ISNs) are chosen.  Some popular stack implementa-
     tions choose very poor ISNs and thus are normally susceptible to  ISN  pre-
     diction  exploits.   By applying a modulate state rule to a TCP connection,
     pf(4) will create a high quality random sequence number for each connection
     endpoint.

     The modulate state directive implicitly keeps state on the rule and is only
     applicable to TCP connections.

     For instance:

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

     Note that modulated connections will not recover when the	state  table  is
     lost  (firewall  reboot, flushing the state table, etc...).  pf(4) will not
     be able to infer a connection again after the state table flushes the  con-
     nection's	modulator.   When  the state is lost, the connection may be left
     dangling until the respective endpoints time out  the  connection.   It  is
     possible  on  a  fast local network for the endpoints to start an ACK storm
     while trying to resynchronize after the loss of the modulator.  The default
     flags settings (or a more strict equivalent) should  be  used  on	modulate
     state rules to prevent ACK storms.

     Note  that  alternative  methods are available to prevent loss of the state
     table and allow for firewall failover.  See carp(4) and pfsync(4) for  fur-
     ther information.

SYN PROXY
     By  default,  pf(4)  passes packets that are part of a tcp(4) handshake be-
     tween the endpoints.  The synproxy state option can be used to cause  pf(4)
     itself  to complete the handshake with the active endpoint, perform a hand-
     shake with the passive endpoint, and then forward packets between the  end-
     points.

     No  packets are sent to the passive endpoint before the active endpoint has
     completed the handshake, hence so-called SYN floods with spoofed source ad-
     dresses will not reach the passive endpoint, as the sender  can't	complete
     the handshake.

     The  proxy is transparent to both endpoints, they each see a single connec-
     tion from/to the other endpoint.  pf(4)  chooses  random  initial	sequence
     numbers  for  both  handshakes.  Once the handshakes are completed, the se-
     quence number modulators (see previous section) are used to translate  fur-
     ther packets of the connection.  synproxy state includes modulate state.

     Rules with synproxy will not work if pf(4) operates on a if_bridge(4).

     Example:

	   pass in proto tcp from any to any port www synproxy state

STATEFUL TRACKING OPTIONS
     A	number	of options related to stateful tracking can be applied on a per-
     rule basis.  keep state, modulate state and synproxy  state  support  these
     options,  and keep state must be specified explicitly to apply options to a
     rule.

     max <number>
	   Limits the number of concurrent states the  rule  may  create.   When
	   this  limit	is reached, further packets matching the rule that would
	   create state are dropped, until existing states time out.
     no-sync
	   Prevent state changes for states created by this rule from  appearing
	   on the pfsync(4) interface.
     <timeout> <seconds>
	   Changes the timeout values used for states created by this rule.  For
	   a list of all valid timeout names, see "OPTIONS" above.
     sloppy
	   Uses  a  sloppy  TCP  connection tracker that does not check sequence
	   numbers at all, which makes insertion and ICMP teardown  attacks  way
	   easier.  This is intended to be used in situations where one does not
	   see	all  packets  of a connection, i.e. in asymmetric routing situa-
	   tions.  Cannot be used with modulate or synproxy state.

     Multiple options can be specified, separated by commas:

	   pass in proto tcp from any to any \
		 port www keep state \
		 (max 100, source-track rule, max-src-nodes 75, \
		 max-src-states 3, tcp.established 60, tcp.closing 5)

     When the source-track keyword is specified, the number of states per source
     IP is tracked.

     source-track rule
	   The maximum number of states created by this rule is limited  by  the
	   rule's  max-src-nodes and max-src-states options.  Only state entries
	   created by this particular rule count toward the rule's limits.
     source-track global
	   The number of states created by all rules that  use	this  option  is
	   limited.    Each   rule   can  specify  different  max-src-nodes  and
	   max-src-states options, however state entries created by any partici-
	   pating rule count towards each individual rule's limits.

     The following limits can be set:

     max-src-nodes <number>
	   Limits the maximum number of source addresses  which  can  simultane-
	   ously have state table entries.
     max-src-states <number>
	   Limits the maximum number of simultaneous state entries that a single
	   source address can create with this rule.

     For  stateful  TCP  connections, limits on established connections (connec-
     tions which have completed the TCP 3-way handshake) can  also  be	enforced
     per source IP.

     max-src-conn <number>
	   Limits  the maximum number of simultaneous TCP connections which have
	   completed the 3-way handshake that a single host can make.
     max-src-conn-rate <number> / <seconds>
	   Limit the rate of new connections over a time interval.  The  connec-
	   tion rate is an approximation calculated as a moving average.

     Because  the  3-way  handshake ensures that the source address is not being
     spoofed, more aggressive action can be taken based on these  limits.   With
     the  overload <table> state option, source IP addresses which hit either of
     the limits on established connections will be added  to  the  named  table.
     This  table  can  be used in the ruleset to block further activity from the
     offending host, redirect it to a tarpit process, or restrict its bandwidth.

     The optional flush keyword kills all states created by  the  matching  rule
     which originate from the host which exceeds these limits.	The global modi-
     fier  to  the flush command kills all states originating from the offending
     host, regardless of which rule created the state.

     For example, the following rules will protect the webserver  against  hosts
     making  more  than  100 connections in 10 seconds.  Any host which connects
     faster than this rate will have its address added to the <bad_hosts>  table
     and  have all states originating from it flushed.	Any new packets arriving
     from this host will be dropped unconditionally by the block rule.

	   block quick from <bad_hosts>
	   pass in on $ext_if proto tcp to $webserver port www keep state \
		   (max-src-conn-rate 100/10, overload <bad_hosts> flush global)

OPERATING SYSTEM FINGERPRINTING
     Passive OS Fingerprinting is a mechanism to inspect nuances of a  TCP  con-
     nection's initial SYN packet and guess at the host's operating system.  Un-
     fortunately  these nuances are easily spoofed by an attacker so the finger-
     print is not useful in making security decisions.	But the  fingerprint  is
     typically accurate enough to make policy decisions upon.

     The fingerprints may be specified by operating system class, by version, or
     by  subtype/patchlevel.   The class of an operating system is typically the
     vendor or genre and would be OpenBSD for the pf(4)  firewall  itself.   The
     version  of the oldest available OpenBSD release on the main FTP site would
     be 2.6 and the fingerprint would be written

	   "OpenBSD 2.6"

     The subtype of an operating system is typically used to describe the patch-
     level if that patch led to changes in the TCP stack behavior.  In the  case
     of  OpenBSD,  the	only subtype is for a fingerprint that was normalized by
     the no-df scrub option and would be specified as

	   "OpenBSD 3.3 no-df"

     Fingerprints for most popular operating systems are provided  by  pf.os(5).
     Once  pf(4)  is  running, a complete list of known operating system finger-
     prints may be listed by running:

	   # pfctl -so

     Filter rules can enforce policy at any level of operating system specifica-
     tion assuming a fingerprint is present.  Policy could limit traffic to  ap-
     proved  operating systems or even ban traffic from hosts that aren't at the
     latest service pack.

     The unknown class can also be used as  the  fingerprint  which  will  match
     packets for which no operating system fingerprint is known.

     Examples:

	   pass  out proto tcp from any os OpenBSD
	   block out proto tcp from any os Doors
	   block out proto tcp from any os "Doors PT"
	   block out proto tcp from any os "Doors PT SP3"
	   block out from any os "unknown"
	   pass on lo0 proto tcp from any os "OpenBSD 3.3 lo0"

     Operating	system	fingerprinting	is  limited  only to the TCP SYN packet.
     This means that it will not work on other protocols and will  not	match  a
     currently established connection.

     Caveat:  operating  system  fingerprints are occasionally wrong.  There are
     three problems: an attacker can trivially craft his packets  to  appear  as
     any operating system he chooses; an operating system patch could change the
     stack  behavior and no fingerprints will match it until the database is up-
     dated; and multiple operating systems may have the same fingerprint.

BLOCKING SPOOFED TRAFFIC
     "Spoofing" is the faking of IP addresses, typically for malicious purposes.
     The antispoof directive expands to a set of filter rules which  will  block
     all  traffic with a source IP from the network(s) directly connected to the
     specified interface(s) from entering the system through  any  other  inter-
     face.

     For example, the line

	   antispoof for lo0

     expands to

	   block drop in on ! lo0 inet from 127.0.0.1/8 to any
	   block drop in on ! lo0 inet6 from ::1 to any

     For  non-loopback	interfaces, there are additional rules to block incoming
     packets with a source IP address identical to the interface's  IP(s).   For
     example,  assuming  the  interface  wi0 had an IP address of 10.0.0.1 and a
     netmask of 255.255.255.0, the line

	   antispoof for wi0 inet

     expands to

	   block drop in on ! wi0 inet from 10.0.0.0/24 to any
	   block drop in inet from 10.0.0.1 to any

     Caveat: Rules created by the antispoof  directive	interfere  with  packets
     sent  over  loopback  interfaces to local addresses.  One should pass these
     explicitly.

FRAGMENT HANDLING
     The size of IP datagrams (packets) can be	significantly  larger  than  the
     maximum transmission unit (MTU) of the network.  In cases when it is neces-
     sary or more efficient to send such large packets, the large packet will be
     fragmented into many smaller packets that will each fit onto the wire.  Un-
     fortunately  for a firewalling device, only the first logical fragment will
     contain the necessary header information for the  subprotocol  that  allows
     pf(4) to filter on things such as TCP ports or to perform NAT.

     Besides  the  use	of  scrub  rules as described in "TRAFFIC NORMALIZATION"
     above, there are three options for handling fragments in the packet filter.

     One alternative is to filter individual fragments with filter rules.  If no
     scrub rule applies to a fragment, it is passed to the filter.  Filter rules
     with matching IP header parameters decide whether the fragment is passed or
     blocked, in the same way as complete packets  are	filtered.   Without  re-
     assembly,	fragments  can	only  be  filtered  based  on  IP  header fields
     (source/destination address, protocol), since subprotocol header fields are
     not available (TCP/UDP port numbers, ICMP code/type).  The fragment  option
     can  be  used  to restrict filter rules to apply only to fragments, but not
     complete packets.	Filter rules without the fragment option still apply  to
     fragments, if they only specify IP header fields.	For instance, the rule

	   pass in proto tcp from any to any port 80

     never  applies  to a fragment, even if the fragment is part of a TCP packet
     with destination port 80, because without reassembly  this  information  is
     not  available  for  each	fragment.  This also means that fragments cannot
     create new or match existing state table entries, which makes stateful fil-
     tering and address translation (NAT, redirection) for fragments impossible.

     It's also possible to  reassemble	only  certain  fragments  by  specifying
     source or destination addresses or protocols as parameters in scrub rules.

     In  most  cases,  the benefits of reassembly outweigh the additional memory
     cost, and it's recommended to use scrub rules to reassemble  all  fragments
     via the fragment reassemble modifier.

     The  memory  allocated  for fragment caching can be limited using pfctl(8).
     Once this limit is reached, fragments that would  have  to  be  cached  are
     dropped  until  other  entries time out.  The timeout value can also be ad-
     justed.

     Currently, only IPv4 fragments are supported and IPv6 fragments are blocked
     unconditionally.

ANCHORS
     Besides the main ruleset, pfctl(8) can load rulesets into anchor attachment
     points.  An anchor is a container that can hold rules, address tables,  and
     other anchors.

     An anchor has a name which specifies the path where pfctl(8) can be used to
     access  the anchor to perform operations on it, such as attaching child an-
     chors to it or loading rules into it.  Anchors may be nested,  with  compo-
     nents  separated  by `/' characters, similar to how file system hierarchies
     are laid out.  The main ruleset is actually the default anchor,  so  filter
     and translation rules, for example, may also be contained in any anchor.

     An anchor can reference another anchor attachment point using the following
     kinds of rules:

     nat-anchor <name>
	   Evaluates the nat rules in the specified anchor.

     rdr-anchor <name>
	   Evaluates the rdr rules in the specified anchor.

     binat-anchor <name>
	   Evaluates the binat rules in the specified anchor.

     anchor <name>
	   Evaluates the filter rules in the specified anchor.

     load anchor <name> from <file>
	   Loads the rules from the specified file into the anchor name.

     When evaluation of the main ruleset reaches an anchor rule, pf(4) will pro-
     ceed to evaluate all rules specified in that anchor.

     Matching  filter and translation rules marked with the quick option are fi-
     nal and abort the evaluation of the rules in other  anchors  and  the  main
     ruleset.	If  the  anchor  itself is marked with the quick option, ruleset
     evaluation will terminate when the  anchor  is  exited  if  the  packet  is
     matched by any rule within the anchor.

     anchor  rules  are  evaluated relative to the anchor in which they are con-
     tained.  For example, all anchor rules specified in the main  ruleset  will
     reference	anchor attachment points underneath the main ruleset, and anchor
     rules specified in a file loaded from a load anchor rule will  be	attached
     under that anchor point.

     Rules may be contained in anchor attachment points which do not contain any
     rules when the main ruleset is loaded, and later such anchors can be manip-
     ulated  through  pfctl(8)	without  reloading the main ruleset or other an-
     chors.  For example,

	   ext_if = "kue0"
	   block on $ext_if all
	   anchor spam
	   pass out on $ext_if all
	   pass in on $ext_if proto tcp from any \
		 to $ext_if port smtp

     blocks all packets on the external interface by default, then evaluates all
     rules in the anchor named "spam", and finally passes all  outgoing  connec-
     tions and incoming connections to port 25.

	   # echo "block in quick from 1.2.3.4 to any" | \
		 pfctl -a spam -f -

     This  loads  a single rule into the anchor, which blocks all packets from a
     specific address.

     The anchor can also be populated by adding a load	anchor	rule  after  the
     anchor rule:

	   anchor spam
	   load anchor spam from "/etc/pf-spam.conf"

     When  pfctl(8) loads pf.conf, it will also load all the rules from the file
     /etc/pf-spam.conf into the anchor.

     Optionally, anchor rules can specify the parameter's direction,  interface,
     address family, protocol and source/destination address/port using the same
     syntax  as filter rules.  When parameters are used, the anchor rule is only
     evaluated for matching packets.  This allows conditional evaluation of  an-
     chors, like:

	   block on $ext_if all
	   anchor spam proto tcp from any to any port smtp
	   pass out on $ext_if all
	   pass in on $ext_if proto tcp from any to $ext_if port smtp

     The rules inside anchor spam are only evaluated for tcp packets with desti-
     nation port 25.  Hence,

	   # echo "block in quick from 1.2.3.4 to any" | \
		 pfctl -a spam -f -

     will only block connections from 1.2.3.4 to port 25.

     Anchors may end with the asterisk (`*') character, which signifies that all
     anchors  attached at that point should be evaluated in the alphabetical or-
     dering of their anchor name.  For example,

	   anchor "spam/*"

     will evaluate each rule in each anchor attached to the spam  anchor.   Note
     that  it  will only evaluate anchors that are directly attached to the spam
     anchor, and will not descend to evaluate anchors recursively.

     Since anchors are evaluated relative to the anchor in which they  are  con-
     tained,  there is a mechanism for accessing the parent and ancestor anchors
     of a given anchor.  Similar to file system path name resolution, if the se-
     quence ".." appears as an anchor path component, the parent anchor  of  the
     current  anchor  in  the  path evaluation at that point will become the new
     current anchor.  As an example, consider the following:

	   # echo ' anchor "spam/allowed" ' | pfctl -f -
	   # echo -e ' anchor "../banned" \n pass' | \
		 pfctl -a spam/allowed -f -

     Evaluation of the main ruleset will  lead	into  the  spam/allowed  anchor,
     which will evaluate the rules in the spam/banned anchor, if any, before fi-
     nally evaluating the pass rule.

     Filter rule anchors can also be loaded inline in the ruleset within a brace
     ('{'  '}')  delimited  block.   Brace delimited blocks may contain rules or
     other brace-delimited blocks.  When anchors are loaded this way the  anchor
     name becomes optional.

	   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
	   }

     Since  the parser specification for anchor names is a string, any reference
     to an anchor name containing `/' characters will require double quote (`"')
     characters around the anchor name.

TRANSLATION EXAMPLES
     This example maps incoming requests on port 80 to port  8080,  on	which  a
     daemon  is running (because, for example, it is not run as root, and there-
     fore lacks permission to bind to port 80).

     # use a macro for the interface name, so it can be changed easily
     ext_if = "ne3"

     # map daemon on 8080 to appear to be on 80
     rdr on $ext_if proto tcp from any to any port 80 -> 127.0.0.1 port 8080

     If the pass modifier is given, packets matching the  translation  rule  are
     passed without inspecting the filter rules:

     rdr pass on $ext_if proto tcp from any to any port 80 -> 127.0.0.1 \
	   port 8080

     In  the  example  below, vlan12 is configured as 192.168.168.1; the machine
     translates all packets coming from 192.168.168.0/24 to  204.92.77.111  when
     they are going out any interface except vlan12.  This has the net effect of
     making traffic from the 192.168.168.0/24 network appear as though it is the
     Internet  routable  address  204.92.77.111 to nodes behind any interface on
     the router except for the nodes on vlan12.  (Thus, 192.168.168.1  can  talk
     to the 192.168.168.0/24 nodes.)

     nat on ! vlan12 from 192.168.168.0/24 to any -> 204.92.77.111

     In  the example below, the machine sits between a fake internal 144.19.74.*
     network, and a routable external IP of 204.92.77.100.  The no nat rule  ex-
     cludes protocol AH from being translated.

     # NO NAT
     no nat on $ext_if proto ah from 144.19.74.0/24 to any
     nat on $ext_if from 144.19.74.0/24 to any -> 204.92.77.100

     In  the  example  below,  packets bound for one specific server, as well as
     those generated by the sysadmins are not  proxied;  all  other  connections
     are.

     # NO RDR
     no rdr on $int_if proto { tcp, udp } from any to $server port 80
     no rdr on $int_if proto { tcp, udp } from $sysadmins to any port 80
     rdr on $int_if proto { tcp, udp } from any to any port 80 -> 127.0.0.1 \
	   port 80

     This longer example uses both a NAT and a redirection.  The external inter-
     face  has	the  address  157.161.48.183.  On localhost, we are running ftp-
     proxy(8), waiting for FTP sessions to  be	redirected  to	it.   The  three
     mandatory	anchors  for ftp-proxy(8) are omitted from this example; see the
     ftp-proxy(8) manpage.

     # NAT
     # Translate outgoing packets' source addresses (any protocol).
     # In this case, any address but the gateway's external address is mapped.
     nat on $ext_if inet from ! ($ext_if) to any -> ($ext_if)

     # NAT PROXYING
     # Map outgoing packets' source port to an assigned proxy port instead of
     # an arbitrary port.
     # In this case, proxy outgoing isakmp with port 500 on the gateway.
     nat on $ext_if inet proto udp from any port = isakmp to any -> ($ext_if) \
	   port 500

     # BINAT
     # Translate outgoing packets' source address (any protocol).
     # Translate incoming packets' destination address to an internal machine
     # (bidirectional).
     binat on $ext_if from 10.1.2.150 to any -> $ext_if

     # RDR
     # Translate incoming packets' destination addresses.
     # As an example, redirect a TCP and UDP port to an internal machine.
     rdr on $ext_if inet proto tcp from any to ($ext_if) port 8080 \
	   -> 10.1.2.151 port 22
     rdr on $ext_if inet proto udp from any to ($ext_if) port 8080 \
	   -> 10.1.2.151 port 53

     # RDR
     # Translate outgoing ftp control connections to send them to localhost
     # for proxying with ftp-proxy(8) running on port 8021.
     rdr on $int_if proto tcp from any to any port 21 -> 127.0.0.1 port 8021

     In this example, a NAT gateway is set up to  translate  internal  addresses
     using  a  pool of public addresses (192.0.2.16/28) and to redirect incoming
     web server connections to a group of web servers on the internal network.

     # NAT LOAD BALANCE
     # Translate outgoing packets' source addresses using an address pool.
     # A given source address is always translated to the same pool address by
     # using the source-hash keyword.
     nat on $ext_if inet from any to any -> 192.0.2.16/28 source-hash

     # RDR ROUND ROBIN
     # Translate incoming web server connections to a group of web servers on
     # the internal network.
     rdr on $ext_if proto tcp from any to any port 80 \
	   -> { 10.1.2.155, 10.1.2.160, 10.1.2.161 } round-robin

FILTER EXAMPLES
     # The external interface is kue0
     # (157.161.48.183, the only routable address)
     # and the private network is 10.0.0.0/8, for which we are doing NAT.

     # use a macro for the interface name, so it can be changed easily
     ext_if = "kue0"

     # normalize all incoming traffic
     scrub in on $ext_if all fragment reassemble

     # block and log everything by default
     block return log on $ext_if all

     # block anything coming from source we have no back routes for
     block in from no-route to any

     # block packets whose ingress interface does not match the one in
     # the route back to their source address
     block in from urpf-failed to any

     # block and log outgoing packets that do not have our address as source,
     # they are either spoofed or something is misconfigured (NAT disabled,
     # for instance), we want to be nice and do not send out garbage.
     block out log quick on $ext_if from ! 157.161.48.183 to any

     # silently drop broadcasts (cable modem noise)
     block in quick on $ext_if from any to 255.255.255.255

     # block and log incoming packets from reserved address space and invalid
     # addresses, they are either spoofed or misconfigured, we cannot reply to
     # them anyway (hence, no return-rst).
     block in log quick on $ext_if from { 10.0.0.0/8, 172.16.0.0/12, \
	   192.168.0.0/16, 255.255.255.255/32 } to any

     # ICMP

     # pass out/in certain ICMP queries and keep state (ping)
     # state matching is done on host addresses and ICMP id (not type/code),
     # so replies (like 0/0 for 8/0) will match queries
     # ICMP error messages (which always refer to a TCP/UDP packet) are
     # handled by the TCP/UDP states
     pass on $ext_if inet proto icmp all icmp-type 8 code 0

     # UDP

     # pass out all UDP connections and keep state
     pass out on $ext_if proto udp all

     # pass in certain UDP connections and keep state (DNS)
     pass in on $ext_if proto udp from any to any port domain

     # TCP

     # pass out all TCP connections and modulate state
     pass out on $ext_if proto tcp all modulate state

     # pass in certain TCP connections and keep state (SSH, SMTP, DNS, IDENT)
     pass in on $ext_if proto tcp from any to any port { ssh, smtp, domain, \
	   auth }

     # Do not allow Windows 9x SMTP connections since they are typically
     # a viral worm. Alternately we could limit these OSes to 1 connection each.
     block in on $ext_if proto tcp from any os {"Windows 95", "Windows 98"} \
	   to any port smtp

     # IPv6
     # pass in/out all IPv6 traffic: note that we have to enable this in two
     # different ways, on both our physical interface and our tunnel
     pass quick on gif0 inet6
     pass quick on $ext_if proto ipv6

     # Packet Tagging

     # three interfaces: $int_if, $ext_if, and $wifi_if (wireless). NAT is
     # being done on $ext_if for all outgoing packets. tag packets in on
     # $int_if and pass those tagged packets out on $ext_if.  all other
     # outgoing packets (i.e., packets from the wireless network) are only
     # permitted to access port 80.

     pass in on $int_if from any to any tag INTNET
     pass in on $wifi_if from any to any

     block out on $ext_if from any to any
     pass out quick on $ext_if tagged INTNET
     pass out on $ext_if proto tcp from any to any port 80

     # tag incoming packets as they are redirected to spamd(8). use the tag
     # to pass those packets through the packet filter.

     rdr on $ext_if inet proto tcp from <spammers> to port smtp \
	     tag SPAMD -> 127.0.0.1 port spamd

     block in on $ext_if
     pass in on $ext_if inet proto tcp tagged SPAMD

GRAMMAR
     Syntax for pf.conf in BNF:

     line	    = ( option | pf-rule | nat-rule | binat-rule | rdr-rule |
		      antispoof-rule | altq-rule | queue-rule | trans-anchors |
		      anchor-rule | anchor-close | load-anchor | table-rule | )

     option	    = "set" ( [ "timeout" ( timeout | "{" timeout-list "}" ) ] |
		      [ "ruleset-optimization" [ "none" | "basic" | "profile" ]] |
		      [ "optimization" [ "default" | "normal" |
		      "high-latency" | "satellite" |
		      "aggressive" | "conservative" ] ]
		      [ "limit" ( limit-item | "{" limit-list "}" ) ] |
		      [ "loginterface" ( interface-name | "none" ) ] |
		      [ "block-policy" ( "drop" | "return" ) ] |
		      [ "state-policy" ( "if-bound" | "floating" ) ]
		      [ "require-order" ( "yes" | "no" ) ]
		      [ "fingerprints" filename ] |
		      [ "skip on" ( interface-name | "{" interface-list "}" ) ] |
		      [ "debug" ( "none" | "urgent" | "misc" | "loud" ) ] )

     pf-rule	    = action [ ( "in" | "out" ) ]
		      [ "log" [ "(" logopts ")"] ] [ "quick" ]
		      [ "on" ifspec ] [ "fastroute" | route ] [ af ] [ protospec ]
		      hosts [ filteropt-list ]

     logopts	    = logopt [ "," logopts ]
     logopt	    = "all" | "user" | "to" interface-name

     filteropt-list = filteropt-list filteropt | filteropt
     filteropt	    = user | group | flags | icmp-type | icmp6-type | tos |
		      ( "no" | "keep" | "modulate" | "synproxy" ) "state"
		      [ "(" state-opts ")" ] |
		      "fragment" | "no-df" | "min-ttl" number |
		      "max-mss" number | "random-id" | "reassemble tcp" |
		      fragmentation | "allow-opts" |
		      "label" string | "tag" string | [ ! ] "tagged" string |
		      "queue" ( string | "(" string [ [ "," ] string ] ")" ) |
		      "rtable" number | "probability" number"%"

     nat-rule	    = [ "no" ] "nat" [ "pass" [ "log" [ "(" logopts ")" ] ] ]
		      [ "on" ifspec ] [ af ]
		      [ protospec ] hosts [ "tag" string ] [ "tagged" string ]
		      [ "->" ( redirhost | "{" redirhost-list "}" )
		      [ portspec ] [ pooltype ] [ "static-port" ] ]

     binat-rule     = [ "no" ] "binat" [ "pass" [ "log" [ "(" logopts ")" ] ] ]
		      [ "on" interface-name ] [ af ]
		      [ "proto" ( proto-name | proto-number ) ]
		      "from" address [ "/" mask-bits ] "to" ipspec
		      [ "tag" string ] [ "tagged" string ]
		      [ "->" address [ "/" mask-bits ] ]

     rdr-rule	    = [ "no" ] "rdr" [ "pass" [ "log" [ "(" logopts ")" ] ] ]
		      [ "on" ifspec ] [ af ]
		      [ protospec ] hosts [ "tag" string ] [ "tagged" string ]
		      [ "->" ( redirhost | "{" redirhost-list "}" )
		      [ portspec ] [ pooltype ] ]

     antispoof-rule = "antispoof" [ "log" ] [ "quick" ]
		      "for" ( interface-name | "{" interface-list "}" )
		      [ af ] [ "label" string ]

     table-rule     = "table" "<" string ">" [ tableopts-list ]
     tableopts-list = tableopts-list tableopts | tableopts
     tableopts	    = "persist" | "const" | "file" string |
		      "{" [ tableaddr-list ] "}"
     tableaddr-list = tableaddr-list [ "," ] tableaddr-spec | tableaddr-spec
     tableaddr-spec = [ "!" ] tableaddr [ "/" mask-bits ]
     tableaddr	    = hostname | ipv4-dotted-quad | ipv6-coloned-hex |
		      interface-name | "self"

     altq-rule	    = "altq on" interface-name queueopts-list
		      "queue" subqueue
     queue-rule     = "queue" string [ "on" interface-name ] queueopts-list
		      subqueue

     anchor-rule    = "anchor" [ string ] [ ( "in" | "out" ) ] [ "on" ifspec ]
		      [ af ] [ protospec ] [ hosts ] [ "{" ]

     anchor-close   = "}"

     trans-anchors  = ( "nat-anchor" | "rdr-anchor" | "binat-anchor" ) string
		      [ "on" ifspec ] [ af ] [ "proto" ] [ protospec ] [ hosts ]

     load-anchor    = "load anchor" string "from" filename

     queueopts-list = queueopts-list queueopts | queueopts
     queueopts	    = [ "bandwidth" bandwidth-spec ] |
		      [ "qlimit" number ] | [ "tbrsize" number ] |
		      [ "priority" number ] | [ schedulers ]
     schedulers     = ( cbq-def | priq-def | hfsc-def )
     bandwidth-spec = "number" ( "b" | "Kb" | "Mb" | "Gb" | "%" )

     action	    = "pass" | "block" [ return ] | [ "no" ] "scrub"
     return	    = "drop" | "return" | "return-rst" [ "( ttl" number ")" ] |
		      "return-icmp" [ "(" icmpcode [ [ "," ] icmp6code ] ")" ] |
		      "return-icmp6" [ "(" icmp6code ")" ]
     icmpcode	    = ( icmp-code-name | icmp-code-number )
     icmp6code	    = ( icmp6-code-name | icmp6-code-number )

     ifspec	    = ( [ "!" ] interface-name ) | "{" interface-list "}"
     interface-list = [ "!" ] interface-name [ [ "," ] interface-list ]
     route	    = ( "route-to" | "reply-to" | "dup-to" )
		      ( routehost | "{" routehost-list "}" )
		      [ pooltype ]
     af 	    = "inet" | "inet6"

     protospec	    = "proto" ( proto-name | proto-number |
		      "{" proto-list "}" )
     proto-list     = ( proto-name | proto-number ) [ [ "," ] proto-list ]

     hosts	    = "all" |
		      "from" ( "any" | "no-route" | "urpf-failed" | "self" | host |
		      "{" host-list "}" | "route" string ) [ port ] [ os ]
		      "to"   ( "any" | "no-route" | "self" | host |
		      "{" host-list "}" | "route" string ) [ port ]

     ipspec	    = "any" | host | "{" host-list "}"
     host	    = [ "!" ] ( address [ "/" mask-bits ] | "<" string ">" )
     redirhost	    = address [ "/" mask-bits ]
     routehost	    = "(" interface-name [ address [ "/" mask-bits ] ] ")"
     address	    = ( interface-name | "(" interface-name ")" | hostname |
		      ipv4-dotted-quad | ipv6-coloned-hex )
     host-list	    = host [ [ "," ] host-list ]
     redirhost-list = redirhost [ [ "," ] redirhost-list ]
     routehost-list = routehost [ [ "," ] routehost-list ]

     port	    = "port" ( unary-op | binary-op | "{" op-list "}" )
     portspec	    = "port" ( number | name ) [ ":" ( "*" | number | name ) ]
     os 	    = "os"  ( os-name | "{" os-list "}" )
     user	    = "user" ( unary-op | binary-op | "{" op-list "}" )
     group	    = "group" ( unary-op | binary-op | "{" op-list "}" )

     unary-op	    = [ "=" | "!=" | "<" | "<=" | ">" | ">=" ]
		      ( name | number )
     binary-op	    = number ( "<>" | "><" | ":" ) number
     op-list	    = ( unary-op | binary-op ) [ [ "," ] op-list ]

     os-name	    = operating-system-name
     os-list	    = os-name [ [ "," ] os-list ]

     flags	    = "flags" ( [ flag-set ] "/"  flag-set | "any" )
     flag-set	    = [ "F" ] [ "S" ] [ "R" ] [ "P" ] [ "A" ] [ "U" ] [ "E" ]
		      [ "W" ]

     icmp-type	    = "icmp-type" ( icmp-type-code | "{" icmp-list "}" )
     icmp6-type     = "icmp6-type" ( icmp-type-code | "{" icmp-list "}" )
     icmp-type-code = ( icmp-type-name | icmp-type-number )
		      [ "code" ( icmp-code-name | icmp-code-number ) ]
     icmp-list	    = icmp-type-code [ [ "," ] icmp-list ]

     tos	    = "tos" ( "lowdelay" | "throughput" | "reliability" |
		      [ "0x" ] number )

     state-opts     = state-opt [ [ "," ] state-opts ]
     state-opt	    = ( "max" number | "no-sync" | timeout | sloppy |
		      "source-track" [ ( "rule" | "global" ) ] |
		      "max-src-nodes" number | "max-src-states" number |
		      "max-src-conn" number |
		      "max-src-conn-rate" number "/" number |
		      "overload" "<" string ">" [ "flush" ] |
		      "if-bound" | "floating" )

     fragmentation  = [ "fragment reassemble" | "fragment crop" |
		      "fragment drop-ovl" ]

     timeout-list   = timeout [ [ "," ] timeout-list ]
     timeout	    = ( "tcp.first" | "tcp.opening" | "tcp.established" |
		      "tcp.closing" | "tcp.finwait" | "tcp.closed" |
		      "udp.first" | "udp.single" | "udp.multiple" |
		      "icmp.first" | "icmp.error" |
		      "other.first" | "other.single" | "other.multiple" |
		      "frag" | "interval" | "src.track" |
		      "adaptive.start" | "adaptive.end" ) number

     limit-list     = limit-item [ [ "," ] limit-list ]
     limit-item     = ( "states" | "frags" | "src-nodes" ) number

     pooltype	    = ( "bitmask" | "random" |
		      "source-hash" [ ( hex-key | string-key ) ] |
		      "round-robin" ) [ sticky-address ]

     subqueue	    = string | "{" queue-list "}"
     queue-list     = string [ [ "," ] string ]
     cbq-def	    = "cbq" [ "(" cbq-opt [ [ "," ] cbq-opt ] ")" ]
     priq-def	    = "priq" [ "(" priq-opt [ [ "," ] priq-opt ] ")" ]
     hfsc-def	    = "hfsc" [ "(" hfsc-opt [ [ "," ] hfsc-opt ] ")" ]
     cbq-opt	    = ( "default" | "borrow" | "red" | "ecn" | "rio" )
     priq-opt	    = ( "default" | "red" | "ecn" | "rio" )
     hfsc-opt	    = ( "default" | "red" | "ecn" | "rio" |
		      linkshare-sc | realtime-sc | upperlimit-sc )
     linkshare-sc   = "linkshare" sc-spec
     realtime-sc    = "realtime" sc-spec
     upperlimit-sc  = "upperlimit" sc-spec
     sc-spec	    = ( bandwidth-spec |
		      "(" bandwidth-spec number bandwidth-spec ")" )

FILES
     /etc/hosts 	     Host name database.
     /etc/pf.conf	     Default location of the ruleset file.
     /etc/pf.os 	     Default location of OS fingerprints.
     /etc/protocols	     Protocol name database.
     /etc/services	     Service name database.
     /usr/share/examples/pf  Example rulesets.

BUGS
     Due to a lock order reversal (LOR) with the socket layer, the  use  of  the
     group  and  user  filter parameter in conjuction with a Giant-free netstack
     can  result  in  a  deadlock.   A	workaround  is	 available   under   the
     debug.pfugidhack  sysctl which is automatically enabled when a user / group
     rule is added or log (user) is specified.

     Route labels are not supported by the FreeBSD route(4) system.  Rules  with
     a route label do not match any traffic.

SEE ALSO
     altq(4),  carp(4),  icmp(4),  icmp6(4),  ip(4),  ip6(4),  pf(4), pfsync(4),
     route(4), tcp(4), udp(4), hosts(5),  pf.os(5),  protocols(5),  services(5),
     ftp-proxy(8), pfctl(8), pflogd(8), route(8)

HISTORY
     The pf.conf file format first appeared in OpenBSD 3.0.

FreeBSD 8.2			  June 10, 2008 		      PF.CONF(5)

home | help