Skip site navigation (1)Skip section navigation (2)

FreeBSD Manual Pages

  
 
  

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

     Ethernet Filtering
	   Ethernet  filtering provides rule-based blocking or passing of Ether-
	   net packets.

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

     Comments  can  be put anywhere in the file using a hash mark (`#'), and ex-
     tend to the end of the current line.

     Additional configuration files can be included with  the  include	keyword,
     for example:

	   include "/etc/pf/sub.filter.conf"

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.  Ranges of network addresses used in macros
     that will be expanded in lists later on must be quoted with additional sim-
     ple 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

	   usr_lan_range = "'192.0.2.0/24'"
	   srv_lan_range = "'198.51.100.0 - 198.51.100.255'"
	   nat_ranges = "{" $usr_lan_range $srv_lan_range "}"
	   nat on $ext_if from $nat_ranges to any -> ($ext_if)

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 and in the routing options of filter rules, but not for bitmask
     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 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.

     counters  The counters flag enables per-address packet  and  byte	counters
	       which  can  be  displayed  with pfctl(8).  Note that this feature
	       carries significant memory overhead for large tables.

     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  after  the  second packet but before both endpoints
		 have acknowledged the connection.
	   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.

	   SCTP  timeout  are  handled	similar  to TCP, but with its own set of
	   states:

	   sctp.first
		 The state after the first packet.
	   sctp.opening
		 The state before the destination host ever sends a packet.
	   sctp.established
		 The fully established state.
	   sctp.closing
		 The state after the first SHUTDOWN chunk has been sent.
	   sctp.closed
		 The state after SHUTDOWN_ACK has been exchanged and the connec-
		 tion is closed.

	   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 60000, adaptive.end 120000 }
		 set limit states 100000

	   With 90000 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 or interface group.  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.

	   Limits can be set on the following:

	   states	  Set  the  maximum number of entries in the memory pool
			  used by state table entries (those generated	by  pass
			  rules  which do not specify no state).  The default is
			  100000.

	   src-nodes	  Set the maximum number of entries in the  memory  pool
			  used	for  tracking  source IP addresses (generated by
			  the sticky-address and src.track  options).	The  de-
			  fault is 10000.

	   table-entries  Set  the number of addresses that can be stored in ta-
			  bles.  The default is 200000.

	   anchors	  Set the number of anchors that can exist.  The default
			  is 512.

	   eth-anchors	  Set the number of anchors that can exist.  The default
			  is 512.

	   Multiple limits can be combined on a single line:

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

     set ruleset-optimization
	   none      Disable the ruleset optimizer.
	   basic     Enable basic ruleset optimization.  This is the default be-
		     haviour.  Basic ruleset optimization 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 reassemble yes | no [no-df]
	   The reassemble option is used to enable or disable the reassembly  of
	   fragmented  packets,  and  can be set to yes or no.	If no-df is also
	   specified, fragments with the "dont-fragment" bit set are reassembled
	   too, instead of being dropped; the reassembled packet will  have  the
	   "dont-fragment" bit cleared.  The default value is no.

	   This  option  is  ignored  if  there  are  pre-FreeBSD 14 scrub rules
	   present.

     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 SCTP
		     ABORT chunk is returned for blocked SCTP packets,	an  ICMP
		     UNREACHABLE  is  returned	for blocked UDP packets, and all
		     other packets are silently dropped.

	   The default value is drop.

	   For example:

		 set block-policy return

     set fail-policy
	   The fail-policy option sets the behaviour of rules which should  pass
	   a  packet  but were unable to do so.  This might happen when a nat or
	   route-to rule uses an empty table as list of targets  or  if  a  rule
	   fails  to  create  state or source node.  The following block actions
	   are possible:

	   drop      Incoming packet is silently dropped.
	   return    Incoming packet is dropped and TCP RST is returned for  TCP
		     packets,  an  SCTP ABORT chunk is returned for blocked SCTP
		     packets, an ICMP UNREACHABLE is returned for  UDP	packets,
		     and no response is sent for other packets.

	   For example:

		 set fail-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 syncookies never | always | adaptive
	   When syncookies are active, pf will answer each incoming TCP SYN with
	   a syncookie SYNACK, without allocating any resources.  Upon reception
	   of the client's ACK in response to  the  syncookie  SYNACK,	pf  will
	   evaluate the ruleset and create state if the ruleset permits it, com-
	   plete  the  three way handshake with the target host and continue the
	   connection with synproxy in place.  This allows pf  to  be  resilient
	   against  large  synflood  attacks  which  would  run  the state table
	   against its limits otherwise.  Due to the blind answers to every  in-
	   coming SYN syncookies share the caveats of synproxy, namely seemingly
	   accepting connections that will be dropped later on.

	   never     pf will never send syncookie SYNACKs (the default).
	   always    pf will always send syncookie SYNACKs.
	   adaptive  pf  will  enable  syncookie mode when a given percentage of
		     the state table is used up by half-open TCP connections, as
		     in, those that saw the initial SYN but  didn't  finish  the
		     three way handshake.  The thresholds for entering and leav-
		     ing syncookie mode can be specified using

			   set syncookies adaptive (start 25%, end 12%)

     set state-defaults
	   The	state-defaults	option sets the state options for states created
	   from rules without an explicit keep state.  For example:

		 set state-defaults no-sync

     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.   The  default  location  for
	   fingerprints is /etc/pf.os.

	   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.

     set keepcounters
	   Preserve  rule  counters  across rule updates.  Usually rule counters
	   are reset to zero on every update of the ruleset.  With  keepcounters
	   set	pf will attempt to find matching rules between old and new rule-
	   sets and preserve the rule counters.

ETHERNET FILTERING
     pf(4) has the ability to block and pass  packets  based  on  attributes  of
     their Ethernet (layer 2) header.

     Each  time  a packet processed by the packet filter comes in on or goes out
     through an interface, the filter rules are evaluated in  sequential  order,
     from  first  to last.  The last matching rule decides what action is taken.
     If no rule matches the packet, the default action is  to  pass  the  packet
     without creating a state.

     The following actions can be used in the filter:

     block
	   The	packet is blocked.  Unlike for layer 3 traffic the packet is al-
	   ways silently dropped.

     pass  The packet is passed; no state is created for layer 2 traffic.

   Parameters applicable to layer 2 rules
     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.  The matching for some parameters can be in-
     verted with the ! operator.  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.

     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 <ifspec>
	   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).  any  will
	   match any existing interface except loopback ones.

     bridge-to <interface>
	   Packets  matching  this rule will be sent out of the specified inter-
	   face without further processing.

     proto <protocol>
	   This rule applies only to packets of this protocol.	Note that Ether-
	   net protocol numbers are different  from  those  used  in  ip(4)  and
	   ip6(4).

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

     queue <queue>
	   Packets matching this rule will be assigned to the  specified  queue.
	   See "QUEUEING" for setup details.

     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.

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

TRAFFIC NORMALIZATION
     Traffic normalization is a broad umbrella term for aspects  of  the  packet
     filter  which  deal with verifying packets, packet fragments, spoofed traf-
     fic, and other irregularities.

   Scrub
     Scrub involves sanitising packet content in such a way that  there  are  no
     ambiguities  in packet interpretation on the receiving side.  It is invoked
     with the scrub option, added to filter rules.

     Parameters are specified enclosed in parentheses.	At least one of the fol-
     lowing parameters must be specified:

     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>
	   Reduces  the  maximum  segment size (MSS) on TCP SYN packets to be no
	   greater than number.  This is sometimes required in	scenarios  where
	   the	two  endpoints of a TCP connection are not able to carry similar
	   sized packets and the resulting mismatch can lead to packet	fragmen-
	   tation or loss.  Note that setting the MSS this way can have undesir-
	   able  effects,  such as interfering with the OS detection features of
	   pf(4).

     set-tos <string> | <number>
	   Enforces a TOS for matching IP packets.  TOS may be given as  one  of
	   critical, inetcontrol, lowdelay, netcontrol, throughput, reliability,
	   or  one  of	the DiffServ Code Points: ef, va, af11 ... af43, cs0 ...
	   cs7; or as either hex or decimal.

     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.

     reassemble tcp
	   Statefully  normalizes  TCP connections.  reassemble tcp performs the
	   following normalizations:

	   ttl	    Neither side of the connection is allowed to reduce their IP
		    TTL.  An attacker may send a packet such that it reaches the
		    firewall, affects the firewall  state,  and  expires  before
		    reaching  the  destination	host.  reassemble tcp will raise
		    the TTL of all packets back up to the highest value seen  on
		    the connection.
	   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,

	   match in all scrub (no-df random-id max-mss 1440)

   Scrub ruleset (pre-FreeBSD 14)
     In order to maintain compatibility with older  releases  of  FreeBSD  scrub
     rules  can  also  be specified in their own ruleset.  In such case they are
     invoked with the scrub directive.	If there are such rules present they de-
     termine packet reassembly behaviour.  When no such rules  are  present  the
     option set reassembly takes precedence.  The scrub rules can take all para-
     meters  specified above for a scrub option of filter rules and 2 more para-
     meters controlling 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.   This  is  the default behaviour unless no
	   fragment reassemble is specified.

     no fragment reassemble
	   Do not reassemble fragments.

     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.

     scrub rules in the scrub ruleset are  evaluated  for  every  packet  before
     stateful  filtering.  This means excessive usage of them will cause perfor-
     mance penalty.  scrub reassemble tcp rules  must  not  have  the  direction
     (in/out) specified.

QUEUEING with 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 pri-
	   marily affects throughput.  hfsc supports both link-sharing and guar-
	   anteed 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  5Mbps  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

QUEUEING with dummynet
     Queueing can also be done with dummynet(4).  Queues and pipes can	be  cre-
     ated with dnctl(8).

     Packets  can  be  assigned to queues and pipes using dnqueue and dnpipe re-
     spectively.

     Both dnqueue and dnpipe take either a single pipe or queue  number  or  two
     numbers as arguments.  The first pipe or queue number will be used to shape
     the  traffic  in  the  rule direction, the second will be used to shape the
     traffic in the reverse direction.	If the rule does not specify a direction
     the first packet to create state will be shaped according to the first num-
     ber, and the response traffic according to the second.

     If the dummynet(4) module is not loaded any traffic sent into  a  queue  or
     pipe will be dropped.

TRANSLATION
     Translation  options  modify  either  the source or destination address and
     port of the packets associated with a stateful connection.  pf(4)	modifies
     the  specified  address and/or port in the packet and recalculates IP, TCP,
     and UDP checksums as necessary.

     If specified on a match rule, subsequent rules will  see  packets	as  they
     look  after any addresses and ports have been translated.	These rules will
     therefore have to filter based on the translated address and port number.

     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:

     af-to
	   Translation between different address families (NAT64) is handled us-
	   ing	af-to  rules.	Because address family translation overrides the
	   routing table, it's only possible to use af-to on inbound rules,  and
	   a  source  address of the resulting translation must always be speci-
	   fied.

	   The optional second argument is the host or subnet the  original  ad-
	   dresses  are translated into for the destination.  The lowest bits of
	   the original destination address form the host part of the new desti-
	   nation address according to the specified subnet.  It is possible  to
	   embed  a  complete  IPv4 address into an IPv6 address using a network
	   prefix of /96 or smaller.

	   When a destination address is not specified, it is assumed  that  the
	   host  part  is  32-bit long.  For IPv6 to IPv4 translation this would
	   mean using only the lower 32 bits of the  original  IPv6  destination
	   address.   For  IPv4  to  IPv6 translation the destination subnet de-
	   faults to the subnet of the new IPv6 source	address  with  a  prefix
	   length  of /96.  See RFC 6052 Section 2.2 for details on how the pre-
	   fix determines the destination address encoding.

	   For example, the following rules are identical:

		 pass in inet af-to inet6 from 2001:db8::1 to 2001:db8::/96
		 pass in inet af-to inet6 from 2001:db8::1

	   In the above example the matching IPv4 packets will	be  modified  to
	   have  a  source address of 2001:db8::1 and a destination address will
	   get prefixed with 2001:db8::/96, e.g. 198.51.100.100 will  be  trans-
	   lated to 2001:db8::c633:6464.

	   In the reverse case the following rules are identical:

		 pass in inet6 from any to 64:ff9b::/96 af-to inet \
			from 198.51.100.1 to 0.0.0.0/0
		 pass in inet6 from any to 64:ff9b::/96 af-to inet \
			from 198.51.100.1

	   The	destination  IPv4  address  is assumed to be embedded inside the
	   original IPv6 destination address, e.g.  64:ff9b::c633:6464	will  be
	   translated to 198.51.100.100.

	   The	current implementation will only extract IPv4 addresses from the
	   IPv6 addresses with a prefix length of /96 and greater.

     binat-to
	   A binat-to rule specifies a bidirectional mapping between an external
	   IP netblock and an internal IP netblock.  It expands to  an	outbound
	   nat-to rule and an inbound rdr-to rule.

     nat-to
	   A  nat-to option 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.0.0.0, i.e., 10.0.0.0/8)
		 172.16.0.0 - 172.31.255.255 (i.e., 172.16.0.0/12)
		 192.168.0.0 - 192.168.255.255 (i.e., 192.168.0.0/16)

	   nat-to  is usually applied outbound.  If applied inbound, nat-to to a
	   local IP address is not supported.

     rdr-to
	   The packet is redirected to another destination and possibly  a  dif-
	   ferent  port.   rdr-to  can optionally specify port ranges instead of
	   single ports.  For instance:

		 match in ... port 2000:2999 rdr-to ... port 4000
	   redirects ports 2000 to 2999 (inclusive) to port 4000.

		 qmatch in ... port 2000:2999 rdr-to ... port 4000:*
	   redirects port 2000 to 4000, 2001 to 4001, ..., 2999 to 4999.

     rdr-to is usually applied inbound.  If applied outbound, rdr-to to a  local
     IP  address  is  not supported.  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-to options and both im-
     plicitly and explicitly in the case of rdr-to ones.  A  rdr-to  option  may
     cause  the source port to be modified if doing so avoids a conflict with an
     existing connection.  A random source port in the range 50001-65535 is cho-
     sen in this case.	Port numbers are never translated with	a  binat-to  op-
     tion.

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

	   pass in on egress proto tcp from any to any port smtp \
		 rdr-to 127.0.0.1 port spamd

     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.

   NAT ruleset (pre-FreeBSD 15)
     In order to maintain compatibility with older releases of FreeBSD NAT rules
     can also be specified in their own ruleset.  A stateful connection is auto-
     matically created to track packets matching such a rule as long as they are
     not blocked by the filtering section of pf.conf.  Since translation  occurs
     before  filtering the filter engine will see packets as they look after any
     addresses and ports have been translated.	Filter rules will therefore have
     to filter based on the translated address and port  number.   Packets  that
     match a translation rule are only automatically passed if the pass modifier
     is given, otherwise they are still subject to block and pass rules.

     The following rules can be defined in the NAT ruleset: binat, nat, and rdr.
     They have the same effect as binat-to, nat-to and rdr-to options for filter
     rules.

     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.
     If no rule matches the packet it is passed to the filter engine unmodified.

     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.

     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.

     See "COMPATIBILITY TRANSLATION EXAMPLES" below.

PACKET FILTERING
     pf(4) has the ability to block , pass and match packets based on attributes
     of their layer 3 (see ip(4) and ip6(4)) and layer 4 (see icmp(4), icmp6(4),
     tcp(4), sctp(4), udp(4)) headers.	In addition, packets  may  also  be  as-
     signed 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.	For block and pass , the
     last matching rule decides what action is taken.  For  match  ,  rules  are
     evaluated	every  time they match; the pass/block state of a packet remains
     unchanged.  If no rule matches the packet, the default action  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, an
		 SCTP ABORT for SCTP 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

     match
	   The	packet	is  matched.   This  mechanism	is  used to provide fine
	   grained filtering without altering the block/pass state of a  packet.
	   match  rules  differ from block and pass rules in that parameters are
	   set for every rule a packet matches, not only on  the  last	matching
	   rule.   For	the  following parameters, this means that the parameter
	   effectively becomes "sticky"  until	explicitly  overridden:  nat-to,
	   binat-to, rdr-to, queue, dnpipe, dnqueue, rtable, scrub

     pass  The	packet is passed; state is created unless the no state option 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.

     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 (all | matches | to <interface> | user)
	   In addition to any action specified, log the packet.  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;  pflog0 is monitored by the pflogd(8) logging daemon
	   which logs to the file /var/log/pflog in pcap(3) binary format.

	   The keywords all, matches, to, and user are optional and can be  com-
	   bined using commas, but must be enclosed in parentheses if given.

	   Use	all  to  force logging of all packets for a connection.  This is
	   not necessary when no state is explicitly specified.

	   If matches is specified, it logs the packet on all subsequent  match-
	   ing	rules.	It is often combined with to <interface> to avoid adding
	   noise to the default log file.

	   The keyword 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 addition to the normal information logged.

	   Only  the  first packet logged via log (all, user) will have the user
	   credentials logged when using stateful matching.

	   To specify a logging interface other than pflog0, use the  syntax  to
	   <interface>.

     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).  any  will
	   match any existing interface except loopback ones.

     <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), sctp(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, interface names or interface group names, or  as
	   any of the following keywords:

	   any		   Any address.
	   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.
	   self 	   Expands to all addresses assigned to all interfaces.
	   <table>	   Any address that matches the given table.

	   Ranges of addresses are specified by using the `-' operator.  For in-
	   stance: "10.1.1.10 - 10.1.1.12" means all addresses from 10.1.1.10 to
	   10.1.1.12, hence addresses 10.1.1.10, 10.1.1.11, and 10.1.1.12.

	   Interface  names  and  interface group names, and self can have modi-
	   fiers 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  non-link-local  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"

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

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

     user <user>
	   This rule only applies to packets of sockets owned by  the  specified
	   user.   For outgoing connections initiated from the firewall, this is
	   the user that opened the connection.  For incoming 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 }

	   The	example  below	permits  users with uid between 1000 and 1500 to
	   open connections:

		 block out proto tcp all
		 pass  out proto tcp from self user { 999 >< 1501 }

	   The `:' operator, which works for port number matching, does not work
	   for user and group match.

     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 checked 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 af-to, nat,
	   binat or rdr rules, modulate or synproxy state options,  or	scrubbed
	   with  reassemble  tcp  will also not be recoverable from intermediate
	   packets.  Such connections will stall and time out.

     icmp-type <type> file ... [code <code>]

     icmp6-type <type> file ... [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 critical, inetcontrol, lowdelay, netcontrol,
	   throughput, reliability, or one of the DiffServ Code Points: ef,  va,
	   af11 ... af43, cs0 ... cs7; or as either 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, packets with IPv4 options or IPv6 hop-by-hop or destina-
	   tion options header 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 options.  For packets that match
	   state, the rule that initially created the state is	used.	The  im-
	   plicit  pass  rule,	that  is  used	when a packet does not match any
	   rules, does not allow IP options or option headers.	Note  that  IPv6
	   packets with type 0 routing headers are always dropped.

     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.

     ridentifier <number>
	   Add	an  identifier (number) to the rule, which can be used to corre-
	   late the rule to pflog entries, even after ruleset updates.

     max-pkt-rate number/seconds
	   Measure the rate of packets matching the rule and states  created  by
	   it.	 When  the  specified rate is exceeded, the rule stops matching.
	   Only packets in the direction in which the state was created are con-
	   sidered, so that typically requests are counted and replies are  not.
	   For example, to pass up to 100 ICMP packets per 10 seconds:

		 block in proto icmp
		 pass in proto icmp max-pkt-rate 100/10

	   When  the  rate is exceeded, all ICMP is blocked until the rate falls
	   below 100 per 10 seconds again.

     max-pkt-size <number>
	   Limit each packet to be no more than the specified number  of  bytes.
	   This includes the IP header, but not any layer 2 header.

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

	   For example:

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

     set prio priority | (priority, priority)
	   Packets  matching this rule will be assigned a specific queueing pri-
	   ority.  Priorities are assigned as integers	0  through  7.	 If  the
	   packet  is  transmitted on a vlan(4) interface, the queueing priority
	   will be written as the priority code point in the 802.1Q VLAN header.
	   If two priorities are given, TCP ACKs with no data payload and  pack-
	   ets which have a TOS of lowdelay will be assigned to the second one.

	   For example:

		 pass in proto tcp to port 25 set prio 2
		 pass in proto tcp to port 22 set prio (2, 5)

     [!]received-on interface
	   Only match packets which were received on the specified interface (or
	   interface group).  any will match any existing interface except loop-
	   back ones.

     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, binat  or  ether
	   rules  in addition to filter rules.	Tags take the same macros as la-
	   bels (see above).

     tagged <string>
	   Used with filter, translation or scrub rules to specify that  packets
	   must already be tagged with the given tag in order to match the rule.

     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.

     divert-to <host> port <port>
	   Used  to  divert(4)	packets  to the given divert port.  Historically
	   OpenBSD pf has another meaning for this, and  FreeBSD  pf  uses  this
	   syntax  to  support	divert(4)instead. Hence, host has no meaning and
	   can be set to anything like 127.0.0.1.  If a  packet  is  re-injected
	   and does not change direction then it will not be re-diverted.

     divert-reply
	   It has no meaning in FreeBSD pf.

     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%

     prio <number>
	   Only match packets which have the given queueing priority assigned.

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.

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

     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, bitmask  is  not
	   permitted as a pool type.

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

     map-e-portset <psid-offset> / <psid-len> / <psid>
	   With nat rules, the map-e-portset  option  enables  the  source  port
	   translation	of MAP-E (RFC 7597) Customer Edge.  In order to make the
	   host act as a MAP-E Customer Edge, setting up a  tunneling  interface
	   and	pass  rules for encapsulated packets are required in addition to
	   the map-e-portset nat rule.

	   For example:

		 nat on $gif_mape_if from $int_if:network to any \
		       -> $ipv4_mape_src map-e-portset 6/8/0x34

	   sets PSID offset 6, PSID length 8, PSID 0x34.

     endpoint-independent
	   With nat rules, the endpoint-independent option caues pf(4) to always
	   map connections from a UDP source address and port to  the  same  NAT
	   address and port.  This feature implements "full-cone" NAT behavior.

     Additionally,  options sticky-address and prefer-ipv6-nexthop can be speci-
     fied to influence how IP addresses selected from pools.

     The sticky-address option can be specified to  help  ensure  that	multiple
     connections  from	the  same  source are mapped to the same redirection ad-
     dress.  This option can be used with the random and  round-robin  pool  op-
     tions.   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  map-
     pings  last  beyond the lifetime of the states, increase the global options
     with set timeout src.track.  See "STATEFUL TRACKING OPTIONS" for more  ways
     to control the source tracking.

     The  prefer-ipv6-nexthop option allows for IPv6 addresses to be used as the
     nexthop for IPv4 packets routed with the route-to rule option. If	a  table
     is used with IPv4 and IPv6 addresses, first the IPv6 addresses will be used
     in round-robin fashion, then IPv4 addresses.

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  bridge(4).   Also
     they act on incoming SYN packets only.

     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 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, e.g. in asymmetric routing situa-
	   tions.  Cannot be used with modulate or synproxy state.
     pflow
	   States created by this rule are exported on the pflow(4) interface.
     allow-related
	   Automatically allow connections related to this  one,  regardless  of
	   rules  that might otherwise affect them.  This currently only applies
	   to SCTP multihomed connection.

     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.

     When  one	of  these  limits  is reached, further packets that would create
     state are dropped until existing states time out.

     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 packets to appear as any
     operating system; an operating system patch could change the stack behavior
     and no fingerprints will match it until the database is updated; and multi-
     ple 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  set reassemble option or scrub rules as described in
     "TRAFFIC NORMALIZATION" above, there are three options for  handling  frag-
     ments in the packet filter.

     One alternative is to filter individual fragments with filter rules.  If no
     scrub  rule  applies  to  a fragment or set reassemble is set to no , it is
     passed to the filter.  Filter rules with matching IP header parameters  de-
     cide whether the fragment is passed or blocked, in the same way as complete
     packets  are  filtered.  Without reassembly, 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 set reassemble option or scrub rules with
     the fragment reassemble modifier to reassemble all fragments.

     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.

     When  forwarding  reassembled  IPv6  packets,  pf refragments them with the
     original maximum fragment size.  This allows the sender  to  determine  the
     optimal fragment size by path MTU discovery.

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 packet filtering parameters 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
     anchors, 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.

     An  anchor  rule  can  also  contain  a filter ruleset in a brace-delimited
     block.  In that case, no separate loading of rules into the anchor  is  re-
     quired.   Brace delimited blocks may contain rules or other brace-delimited
     blocks.  When an anchor is populated this way, the anchor name becomes  op-
     tional.

	   anchor "external" on $ext_if {
		   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.

SCTP CONSIDERATIONS
     pf(4) supports sctp(4) connections.  It can match ports,  track  state  and
     NAT  SCTP	traffic.   However, it will not alter port numbers during nat or
     rdr translations.	Doing so would break SCTP multihoming.

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
	   match in on $ext_if proto tcp from any to any port 80 \
		 rdr-to 127.0.0.1 port 8080

     If a pass rule is used with the quick modifier, packets matching the trans-
     lation rule are passed without inspecting subsequent filter rules:

	   pass in quick on $ext_if proto tcp from any to any port 80 \
		 rdr-to 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.)

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

     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.
	   pass out on $ext_if inet from ! ($ext_if) to any nat-to ($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.
	   pass out on $ext_if inet proto udp from any port = isakmp to any \
		 nat-to ($ext_if) port 500

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

	   # Translate packets arriving on $peer_if addressed to 172.22.16.0/20
	   # to the corresponding address in 172.21.16.0/20 (bidirectional).
	   pass on $peer_if from 172.21.16.0/20 to any binat-to 172.22.16.0/20

	   # RDR
	   # Translate incoming packets' destination addresses.
	   # As an example, redirect a TCP and UDP port to an internal machine.
	   pass in on $ext_if inet proto tcp from any to ($ext_if) port 8080 \
		 rdr-to 10.1.2.151 port 22
	   pass in on $ext_if inet proto udp from any to ($ext_if) port 8080 \
		 rdr-to 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.
	   pass in on $int_if proto tcp from any to any port 21 \
		 rdr-to 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.
	   pass out on $ext_if inet from any to any nat-to 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.
	   pass in on $ext_if proto tcp from any to any port 80 \
		 rdr-to { 10.1.2.155, 10.1.2.160, 10.1.2.161 } round-robin

COMPATIBILITY TRANSLATION EXAMPLES
     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.

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

	   # 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

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.

	   # Reassemble incoming traffic
	   set reassemble yes

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

	   # 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

     In the example below, a router handling both address families translates an
     internal IPv4 subnet to IPv6 using the well-known 64:ff9b::/96 prefix:

	 pass in on $v4_if inet af-to inet6 from ($v6_if) to 64:ff9b::/96

     Paired  with  the	example  above, the example below can be used on another
     router handling both address families to translate back to IPv4:

	 pass in on $v6_if inet6 to 64:ff9b::/96 af-to inet from ($v4_if)

GRAMMAR
     Syntax for pf.conf in BNF:

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

     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" ) ]
		      [ "state-defaults" state-opts ]
		      [ "require-order" ( "yes" | "no" ) ]
		      [ "fingerprints" filename ] |
		      [ "skip on" ifspec ] |
		      [ "debug" ( "none" | "urgent" | "misc" | "loud" ) ]
		      [ "keepcounters" ] )

     ether-rule     = "ether" etheraction [ ( "in" | "out" ) ]
		      [ "quick" ] [ "on" ifspec ] [ "bridge-to" interface-name ]
		      [ etherprotospec ] [ etherhosts ] [ "l3" hosts ]
		      [ etherfilteropt-list ]

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

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

     etherfilteropt-list = etherfilteropt-list etherfilteropt | etherfilteropt
     etherfilteropt = "tag" string | "tagged" string | "queue" ( string ) |
		      "ridentifier" number | "label" string

     filteropt-list = filteropt-list filteropt | filteropt
     filteropt	    = user | group | flags | icmp-type | icmp6-type | "tos" tos |
		      "af-to" af "from" ( redirhost | "{" redirhost-list "}" )
		      [ "to" ( redirhost | "{" redirhost-list "}" ) ] |
		      ( "no" | "keep" | "modulate" | "synproxy" ) "state"
		      [ "(" state-opts ")" ] |
		      "fragment" | "no-df" | "min-ttl" number | "set-tos" tos |
		      "max-mss" number | "random-id" | "reassemble tcp" |
		      fragmentation | "allow-opts" |
		      "label" string | "tag" string | [ "!" ] "tagged" string |
		      "max-pkt-rate" number "/" seconds |
		      "set prio" ( number | "(" number [ [ "," ] number ] ")" ) |
		      "max-pkt-size" number |
		      "queue" ( string | "(" string [ [ "," ] string ] ")" ) |
		      "rtable" number | "probability" number"%" | "prio" number |
		      "dnpipe" ( number | "(" number "," number ")" ) |
		      "dnqueue" ( number | "(" number "," number ")" ) |
		      "ridentifier" number |
		      "binat-to" ( redirhost | "{" redirhost-list "}" )
		      [ portspec ] [ pooltype ] |
		      "rdr-to" ( redirhost | "{" redirhost-list "}" )
		      [ portspec ] [ pooltype ] |
		      "nat-to" ( redirhost | "{" redirhost-list "}" )
		      [ portspec ] [ pooltype ] [ "static-port" ] |
		      [ ! ] "received-on" ( interface-name | interface-group )

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

     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" ifspec [ af ] [ "label" string ]
		      [ "ridentifier" number ]

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

     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 ] [ filteropt-list ] [ "{" ]

     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" | "%" )

     etheraction    = "pass" | "block"
     action	    = "pass" | "match" | "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-group ) ) |
		      "{" interface-list "}"
     interface-list = [ "!" ] ( interface-name | interface-group )
		      [ [ "," ] interface-list ]
     route	    = ( "route-to" | "reply-to" | "dup-to" )
		      ( routehost | "{" routehost-list "}" )
		      [ pooltype ]
     af 	    = "inet" | "inet6"

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

     etherhosts     = "from" macaddress "to" macaddress
     macaddress     = mac | mac "/" masklen | mac "&" mask

     hosts	    = "all" |
		      "from" ( "any" | "no-route" | "urpf-failed" | "self" | host |
		      "{" host-list "}" ) [ port ] [ os ]
		      "to"   ( "any" | "no-route" | "self" | host |
		      "{" host-list "}" ) [ 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-group |
		      "(" ( interface-name | interface-group ) ")" |
		      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	    = ( "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" | "pflow" )

     fragmentation  = [ "fragment reassemble" ]

     timeout-list   = timeout [ [ "," ] timeout-list ]
     timeout	    = ( "tcp.first" | "tcp.opening" | "tcp.established" |
		      "tcp.closing" | "tcp.finwait" | "tcp.closed" |
		      "sctp.first" | "sctp.opening" | "sctp.established" |
		      "sctp.closing" | "sctp.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 | prefer-ipv6-nexthop ]

     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 ")" )
     include	    = "include" filename

FILES
     /etc/hosts      Host name database.
     /etc/pf.conf    Default location of the ruleset file.  The file has  to  be
		     created manually as it is not installed with a standard in-
		     stallation.
     /etc/pf.os      Default location of OS fingerprints.
     /etc/protocols  Protocol name database.
     /etc/services   Service name database.

SEE ALSO
     altq(4),  carp(4),  icmp(4),  icmp6(4), ip(4), ip6(4), pf(4), pflow(4), pf-
     sync(4), sctp(4), tcp(4), udp(4), hosts(5),  pf.os(5),  protocols(5),  ser-
     vices(5), ftp-proxy(8), pfctl(8), pflogd(8)

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

FreeBSD ports 15.quarterly	November 3, 2025		      PF.CONF(5)

Want to link to this manual page? Use this URL:
<https://man.freebsd.org/cgi/man.cgi?query=pf.conf&sektion=5&manpath=FreeBSD+15.1-RELEASE+and+Ports.quarterly>

home | help