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 seven types of	statements in pf.conf:

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

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

       Options
	     Options tune the behaviour	of the packet filtering	engine.

       Traffic Normalization (e.g. scrub)
	     Traffic  normalization  protects internal machines	against	incon-
	     sistencies	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 pack-
	     ets.

       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
       extend to the end of the	current	line.

       Additional  configuration  files	 can be	included with the include key-
       word, 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 un-
       derscores.   Macro  names  may not be reserved words (for example pass,
       in, out).  Macros are not expanded inside quotes.

       For example,

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

TABLES
       Tables are named	structures which can hold a  collection	 of  addresses
       and  networks.	Lookups	 against  tables in pf(4) are relatively fast,
       making a	single rule with tables	 much  more  efficient,	 in  terms  of
       processor  usage	 and  memory consumption, than a large number of rules
       which differ only in IP address (either created explicitly or automati-
       cally 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 ad-
       dress of	nat and	rdr rules and in the routing options of	filter	rules,
       but only	for round-robin	pools.

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

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

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

       Tables may be defined with the following	attributes:

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

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

       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  fil-
       ter 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	refer-
       ence  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  ig-
       nored.  In addition to being specified by IP address, hosts may also be
       specified  by  their  hostname.	 When  the resolver is called to add a
       hostname	to a table, all	resulting IPv4 and IPv6	addresses  are	placed
       into  the table.	 IP addresses can also be entered in a table by	speci-
       fying a valid interface name, a valid interface group or	the self  key-
       word,  in which case all	addresses 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 performance of	the firewall at	the risk  of  dropping
	     valid idle	connections.

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

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

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

	     Other protocols are handled similarly to UDP:

	     other.first
	     other.single
	     other.multiple

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

	     adaptive.start
		   When	the number of state entries exceeds this value,	 adap-
		   tive	 scaling  begins.   All	timeout	values are scaled lin-
		   early 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 fac-
		   tor,	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 set-
	     ting both adaptive.start and adaptive.end to 0.

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

	     For example:

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

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

       set loginterface
	     Enable collection of packet and byte  count  statistics  for  the
	     given  interface  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.

	     For example,

		   set limit states 20000

	     sets the maximum number of	entries	in the	memory	pool  used  by
	     state table entries (generated by pass rules which	do not specify
	     no	state) to 20000.  Using

		   set limit frags 20000

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

		   set limit src-nodes 2000

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

		   set limit tables 1000
		   set limit table-entries 100000

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

	     Various limits can	be combined on a single	line:

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

       set ruleset-optimization
	     none      Disable the ruleset optimizer.
	     basic     Enable basic ruleset optimization.  This	is the default
		       behaviour.  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 advanta-
			    geous
		       4.   re-order the rules to improve  evaluation  perfor-
			    mance

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

	     It	 is  important	to note	that the ruleset optimizer will	modify
	     the ruleset to improve performance.  A side effect	of the ruleset
	     modification is that per-rule  accounting	statistics  will  have
	     different meanings	than before.  If per-rule accounting is	impor-
	     tant  for	billing	 purposes or whatnot, either the ruleset opti-
	     mizer 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  connec-
		   tion).
	     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	connections early.
	     conservative
		   Extremely conservative settings.  Avoid dropping legitimate
		   connections	at  the	 expense of greater memory utilization
		   (possibly much greater on a busy network) and slightly  in-
		   creased processor utilization.

	     For example:

		   set optimization aggressive

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

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

	     For example:

		   set block-policy return

       set 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  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 state-defaults
	     The  state-defaults option	sets the state options for states cre-
	     ated 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 de-
	     sirable 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
	     enforcement.

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

	     For example:

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

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

		   set skip on lo0

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

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

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

       scrub has the following options:

       no-df
	     Clears the	dont-fragment bit from a matching IP packet.  Some op-
	     erating 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 specified.

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

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

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

       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,  af11  ...
	     af43, cs0 ... cs7;	or as either hex or decimal.

       random-id
	     Replaces  the  IP identification field with random	values to com-
	     pensate for predictable values generated by many hosts.  This op-
	     tion only applies to packets that are not	fragmented  after  the
	     optional fragment reassembly.

       fragment	reassemble
	     Using scrub rules,	fragments can be reassembled by	normalization.
	     In	 this  case, fragments are buffered until they form a complete
	     packet, and only the completed packet is passed on	to the filter.
	     The advantage is that filter rules	have to	deal  only  with  com-
	     plete packets, and	can ignore fragments.  The drawback of caching
	     fragments is the additional memory	cost.

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

	     ttl      Neither  side  of	 the  connection  is allowed to	reduce
		      their IP TTL.  An	attacker may send a packet  such  that
		      it reaches the firewall, affects the firewall state, and
		      expires	 before	  reaching   the   destination	 host.
		      reassemble tcp will raise	the TTL	of all packets back up
		      to the highest value seen	on the connection.
	     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	timestamp and multiplying by a
		      constant.	 Also observing	several	 different  timestamps
		      can  be  used  to	 count hosts behind a NAT device.  And
		      spoofing TCP packets into	a connection requires  knowing
		      or guessing valid	timestamps.  Timestamps	merely need to
		      be monotonically increasing and not derived off a	guess-
		      able base	time.  reassemble tcp will cause scrub to mod-
		      ulate the	TCP timestamps with a random number.
	     extended PAWS checks
		      There is a problem with TCP on long fat pipes, in	that a
		      packet  might  get  delayed for longer than it takes the
		      connection to wrap its 32-bit sequence space.   In  such
		      an occurrence, the old packet would be indistinguishable
		      from  a  new  packet and would be	accepted as such.  The
		      solution to this	is  called  PAWS:  Protection  Against
		      Wrapped  Sequence	 numbers.   It	protects against it by
		      making sure the timestamp	on each	 packet	 does  not  go
		      backwards.  reassemble tcp also makes sure the timestamp
		      on  the packet does not go forward more than the RFC al-
		      lows.  By	doing this, pf(4) artificially extends the se-
		      curity of	TCP sequence numbers by	10 to 18 bits when the
		      host uses	appropriately randomized timestamps,  since  a
		      blind  attacker  would  have  to	guess the timestamp as
		      well.

       For example,

	     scrub in on $ext_if all fragment reassemble

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

QUEUEING
       The ALTQ	system is currently not	available in the GENERIC kernel	nor as
       loadable	modules.  In order to use the herein after called queueing op-
       tions 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	parti-
	     tioning and sharing of link bandwidth  by	hierarchically	struc-
	     tured  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 primarily affects throughput.  hfsc supports both
	     link-sharing and guaranteed real-time  services.	It  employs  a
	     service curve based QoS model, and	its unique feature is an abil-
	     ity 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
	     values are	cbq for	Class Based Queueing, priq for Priority	Queue-
	     ing and hfsc for the Hierarchical Fair Service Curve scheduler.

       bandwidth <bw>
	     The maximum bitrate for all queues	on an interface	may be	speci-
	     fied  using the bandwidth keyword.	 The value can be specified as
	     an	absolute value or as a percentage of the interface  bandwidth.
	     When  using an absolute value, the	suffixes b, Kb,	Mb, and	Gb are
	     used to represent bits, kilobits, megabits, and gigabits per sec-
	     ond, respectively.	 The value must	not exceed the interface band-
	     width.  If	bandwidth is not specified, the	interface bandwidth is
	     used (but take note that some interfaces do not know their	 band-
	     width, 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
       sequence	 of queue directives may be defined.  The name associated with
       a queue must match a queue defined in the altq directive	 (e.g.	mail),
       or,  except for the priq	scheduler, in a	parent queue declaration.  The
       following keywords can be used:

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

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

       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  de-
	     fault  for	 all is	1.  Priq queues	with a higher priority are al-
	     ways 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 aver-
		   age queue length.

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

       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 con-
       trols the bandwidth assigned to the queue.  m1 and d are	 optional  and
       can be used to control the initial bandwidth assignment.	 For the first
       d milliseconds the queue	gets the bandwidth given as m1,	afterwards the
       value given in m2.

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

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

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

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

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

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

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

       The state entry created permits pf(4) to	keep track of the original ad-
       dress for traffic associated with that state and	correctly  direct  re-
       turn traffic for	that connection.

       Various types of	translation are	possible with pf:

       binat
	     A	binat rule specifies a bidirectional mapping between an	exter-
	     nal IP netblock and an internal IP	netblock.

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

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

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

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

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

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

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

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

	     rdr on ne3	inet proto tcp to port smtp -> 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 de-
       sired, any of the local non-loopback addresses should be	used as	 redi-
       rection	target instead,	which allows external connections only to dae-
       mons bound to this address or not bound to any address.

       See "TRANSLATION	EXAMPLES" below.

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

       For  each  packet  processed by the packet filter, the filter rules are
       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.

       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	behav-
	     iour  is to drop packets silently,	however	this can be overridden
	     or	made explicit either globally, by setting the block-policy op-
	     tion, 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
		   message,  however  this  can	 be overridden by specifying a
		   message as a	code or	number.
	     return
		   This	causes a TCP RST to be returned	for tcp(4) packets and
		   an ICMP UNREACHABLE for UDP and other packets.

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

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

		   block all

       pass  The packet	is passed; state is created 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 con-
       nection is closed or times out, the state entry	is  automatically  re-
       moved.

       This  has  several advantages.  For TCP connections, comparing a	packet
       to a state involves checking its	sequence numbers, as well as TCP time-
       stamps 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 at-
       tacker sends packets with a fake	source address/port but	does not  know
       the connection's	sequence numbers.  Similarly, pf(4) knows how to match
       ICMP replies to states.	For example,

	     pass out inet proto icmp all icmp-type echoreq

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

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

       Furthermore,  correct  handling	of  ICMP error messages	is critical to
       many protocols, particularly TCP.  pf(4)	matches	ICMP error messages to
       the correct connection, checks them against connection parameters,  and
       passes  them if appropriate.  For example if an ICMP source quench mes-
       sage 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 transla-
       tion on returning 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
       addresses  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
       keyword	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 packets with matching	attributes.  Certain parameters	can be
       expressed  as  lists,  in which case pfctl(8) generates all needed rule
       combinations.

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

       log   In	addition to the	action specified, a log	message	is  generated.
	     Only  the packet that establishes the state is logged, unless the
	     no	state option is	specified.  The	logged packets are sent	 to  a
	     pflog(4)  interface,  by default pflog0.  This interface is moni-
	     tored by the pflogd(8) logging daemon,  which  dumps  the	logged
	     packets to	the file /var/log/pflog	in pcap(3) binary format.

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

       log (user)
	     Logs  the	Unix  user ID of the user that owns the	socket and the
	     PID of the	process	that has the socket open where the  packet  is
	     sourced from or destined to (depending on which socket is local).
	     This is in	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.

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

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

       on <interface>
	     This  rule	 applies  only	to  packets coming in on, or going out
	     through, this particular interface	or interface group.  For  more
	     information  on  interface	 groups,  see  the  group  keyword  in
	     ifconfig(8).

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

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

       from <source> port <source> os <source> to <dest> port <dest>
	     This rule applies only to packets with the	specified  source  and
	     destination 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.
	     <table>	     Any address that matches the given	table.

	     Ranges of addresses are specified by using	the `-'	operator.  For
	     instance:	"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 can have	modifiers  ap-
	     pended:

	     :network	   Translates to the network(s)	attached to the	inter-
			   face.
	     :broadcast	   Translates	to   the   interface's	broadcast  ad-
			   dress(es).
	     :peer	   Translates to the point-to-point  interface's  peer
			   address(es).
	     :0		   Do not include interface aliases.

	     Host  names  may also have	the :0 option appended to restrict the
	     name resolution to	the first of each v4 and non-link-local	v6 ad-
	     dress 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 reloaded for the change to	be reflected  in  the  kernel.
	     Surrounding the interface name (and optional modifiers) in	paren-
	     theses  changes  this behaviour.  When the	interface name is sur-
	     rounded by	parentheses, the rule is automatically	updated	 when-
	     ever  the	interface  changes  its	address.  The ruleset does not
	     need to be	reloaded.  This	is especially useful with nat.

	     Ports can be specified either by number or	by name.  For example,
	     port 80 can be specified as www.  For a list of all port name  to
	     number mappings used by pfctl(8), see the file /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 argu-
	     ments).  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 fol-
	     lowing 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	speci-
	     fied user.	 For outgoing connections initiated from the firewall,
	     this  is  the user	that opened the	connection.  For incoming con-
	     nections to the firewall itself, this is the user that listens on
	     the destination port.  For	forwarded connections, where the fire-
	     wall is not  a  connection	 endpoint,  the	 user  and  group  are
	     unknown.

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

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

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

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

       flags <a> /<b> |	/<b> | any
	     This rule only applies to TCP packets that	have the flags <a> set
	     out of set	<b>.  Flags not	specified in  <b>  are	ignored.   For
	     stateful  connections,  the  default  is flags S/SA.  To indicate
	     that flags	should not be 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
	     specified),  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 syn-
	     chronize to existing connections, for instance if one flushes the
	     state table.  However,  states  created  from  such  intermediate
	     packets  may be missing connection	details	such as	the TCP	window
	     scaling factor.  States which modify the  packet  flow,  such  as
	     those  affected  by nat, binat or rdr rules, modulate or synproxy
	     state options, or scrubbed	with reassemble	tcp will also  not  be
	     recoverable  from	intermediate  packets.	 Such connections will
	     stall and time out.

       icmp-type <type>	code <code>

       icmp6-type <type> code <code>
	     This rule only applies to ICMP or ICMPv6 packets with the	speci-
	     fied  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 indicator (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, af11 ... af43,	cs0 ...	cs7; or	as either hex or deci-
	     mal.

	     For example, the following	rules are identical:

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

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

       label <string>
	     Adds a label (name) to the	rule, which can	be  used  to  identify
	     the  rule.	  For instance,	pfctl -s labels	shows per-rule statis-
	     tics 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  con-
	     figuration	file parse time, not during runtime.

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

	     For example:

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

       set prio	priority | (priority, priority)
	     Packets matching this rule	will be	assigned a  specific  queueing
	     priority.	 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, packets which	have a
	     TOS of lowdelay and TCP ACKs with no data	payload	 will  be  as-
	     signed 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)

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

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

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

       divert-to <host>	port <port>
	     Used  to  redirect	 packets  to  a	local socket bound to host and
	     port.  The	packets	will not be modified, so getsockname(2)	on the
	     socket will  return  the  original	 destination  address  of  the
	     packet.

       divert-reply
	     Used  to  receive replies for sockets that	are bound to addresses
	     which are not local to the	machine.  See setsockopt(2) for	infor-
	     mation on how to bind these sockets.

       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 ex-
	     ample, 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 as-
	     signed.

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 optional address for the next hop.  When a route-to rule
	     creates state, only packets that pass in the  same	 direction  as
	     the  filter  rule	specifies will be routed in this way.  Packets
	     passing in	the opposite direction (replies) are not affected  and
	     are routed	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 connec-
	     tions to route all	outgoing packets of a connection  through  the
	     interface	the  incoming  connection  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 address), a variety of different methods for	assigning this
       address can be used:

       bitmask
	     The bitmask option	applies	the network portion of the redirection
	     address to	the address to be modified (source with	nat,  destina-
	     tion 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 de-
	     termine the redirection address, ensuring	that  the  redirection
	     address  is  always the same for a	given source.  An optional key
	     can be specified after this keyword either	in hex or as a string;
	     by	default	pfctl(8) randomly  generates  a	 key  for  source-hash
	     every time	the ruleset is reloaded.

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

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

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

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

STATE MODULATION
       Much of the security derived from TCP is	attributable to	how  well  the
       initial	sequence numbers (ISNs)	are chosen.  Some popular stack	imple-
       mentations choose very poor ISNs	and thus are normally  susceptible  to
       ISN  prediction	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 connection's	modulator.  When the state is lost,  the  con-
       nection	may  be	 left dangling until the respective endpoints time out
       the connection.	It is possible on a fast local network	for  the  end-
       points  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 further information.

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

       No  packets are sent to the passive endpoint before the active endpoint
       has completed the handshake, hence so-called SYN	 floods	 with  spoofed
       source  addresses  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 con-
       nection from/to the other endpoint.  pf(4) chooses random  initial  se-
       quence numbers for both handshakes.  Once the handshakes	are completed,
       the  sequence  number  modulators  (see	previous  section) are used to
       translate further packets of the	connection.  synproxy  state  includes
       modulate	state.

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

       Example:

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

STATEFUL TRACKING OPTIONS
       A  number  of  options related to stateful tracking can be applied on a
       per-rule	basis.	keep state, modulate state and synproxy	state  support
       these options, and keep state must be specified explicitly to apply op-
       tions 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
	     will not match this rule until existing states time out.
       no-sync
	     Prevent state changes for states created by this  rule  from  ap-
	     pearing 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  situations.   Cannot  be	used with modulate or synproxy
	     state.

       Multiple	options	can be specified, separated by commas:

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

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

       source-track rule
	     The  maximum  number of states created by this rule is limited by
	     the rule's	max-src-nodes and max-src-states options.  Only	 state
	     entries  created  by this particular rule count toward the	rule's
	     limits.
       source-track global
	     The number	of states created by all rules that use	this option is
	     limited.  Each  rule  can	specify	 different  max-src-nodes  and
	     max-src-states options, however state entries created by any par-
	     ticipating	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 simulta-
	     neously 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 (con-
       nections	which have completed the TCP 3-way handshake) can also be  en-
       forced 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 con-
	     nection rate is an	approximation calculated as a moving average.

       Because the 3-way handshake ensures that	the source address is not  be-
       ing 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  modifier	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
       connection's  initial SYN packet	and guess at the host's	operating sys-
       tem.  Unfortunately these nuances are easily spoofed by an attacker  so
       the  fingerprint	 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  ver-
       sion,  or  by  subtype/patchlevel.  The class of	an operating system is
       typically the vendor or genre and would be OpenBSD for the pf(4)	 fire-
       wall  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
       patchlevel  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 fingerprints may be listed by running:

	     # pfctl -so

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

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

       Examples:

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

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

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

BLOCKING SPOOFED TRAFFIC
       "Spoofing"  is the faking of IP addresses, typically for	malicious pur-
       poses.  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 interface.

       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	incom-
       ing  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
       necessary  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.	Unfortunately for a firewalling	device,	only the first
       logical fragment	will contain the necessary header information for  the
       subprotocol  that allows	pf(4) to filter	on things such as TCP ports or
       to perform NAT.

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

       One alternative is to filter individual fragments  with	filter	rules.
       If  no  scrub  rule  applies to a fragment, it is passed	to the filter.
       Filter rules with matching IP  header  parameters  decide  whether  the
       fragment	 is passed or blocked, in the same way as complete packets are
       filtered.  Without reassembly, fragments	can only be filtered based  on
       IP  header fields (source/destination address, protocol), since subpro-
       tocol 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	infor-
       mation  is not available	for each fragment.  This also means that frag-
       ments cannot create new or match	existing state	table  entries,	 which
       makes stateful filtering	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 mem-
       ory cost, and it's recommended to use scrub  rules  to  reassemble  all
       fragments via the fragment reassemble modifier.

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

       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 at-
       tachment	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 attach-
       ing child anchors to it or loading  rules  into	it.   Anchors  may  be
       nested,	with  components  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 fol-
       lowing 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
       proceed to evaluate all rules specified in that anchor.

       Matching	 filter	and translation	rules marked with the quick option are
       final 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
       contained.  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  manipulated	through	pfctl(8) without reloading the main ruleset or
       other anchors.  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
       connections 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
       destination 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 alphabet-
       ical ordering 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
       contained,  there  is a mechanism for accessing the parent and ancestor
       anchors of a given anchor.  Similar to file system  path	 name  resolu-
       tion,  if  the  sequence	 ".." 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
       finally evaluating the pass rule.

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

	     anchor "external" on $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	refer-
       ence to an anchor name containing `/' characters	 will  require	double
       quote (`"') characters around the anchor	name.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

       # ICMP

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

       # UDP

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

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

       # TCP

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

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

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

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

       # Packet	Tagging

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

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

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

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

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

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

GRAMMAR
       Syntax for pf.conf in BNF:

       line	      =	( option | pf-rule | nat-rule |	binat-rule | rdr-rule |
			antispoof-rule | altq-rule | queue-rule	| trans-anchors	|
			anchor-rule | anchor-close | load-anchor | table-rule |
			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"	) ] )

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

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

       filteropt-list =	filteropt-list filteropt | filteropt
       filteropt      =	user | group | flags | icmp-type | icmp6-type |	"tos" tos |
			( "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 |
			"set prio" ( number | "(" number [ [ "," ] number ] ")"	) |
			"queue"	( string | "(" string [	[ "," ]	string ] ")" ) |
			"rtable" number	| "probability"	number"%" | "prio" number

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

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

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

       antispoof-rule =	"antispoof" [ "log" ] [	"quick"	]
			"for" ifspec [ af ] [ "label" string ]

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

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

       ifspec	      =	( [ "!"	] ( interface-name | interface-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"

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

       hosts	      =	"all" |
			"from" ( "any" | "no-route" | "urpf-failed" | "self" | host |
			"{" host-list "}" ) [ 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"	)

       fragmentation  =	[ "fragment reassemble"	]

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

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

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

       subqueue	      =	string | "{" queue-list	"}"
       queue-list     =	string [ [ "," ] string	]
       cbq-def	      =	"cbq" [	"(" cbq-opt [ [	"," ] cbq-opt ]	")" ]
       priq-def	      =	"priq" [ "(" priq-opt [	[ "," ]	priq-opt ] ")" ]
       hfsc-def	      =	"hfsc" [ "(" hfsc-opt [	[ "," ]	hfsc-opt ] ")" ]
       cbq-opt	      =	( "default" | "borrow" | "red" | "ecn" | "rio" )
       priq-opt	      =	( "default" | "red" | "ecn" | "rio" )
       hfsc-opt	      =	( "default" | "red" | "ecn" | "rio" |
			linkshare-sc | realtime-sc | upperlimit-sc )
       linkshare-sc   =	"linkshare" sc-spec
       realtime-sc    =	"realtime" sc-spec
       upperlimit-sc  =	"upperlimit" sc-spec
       sc-spec	      =	( bandwidth-spec |
			"(" bandwidth-spec number bandwidth-spec ")" )
       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 stan-
		       dard installation.
       /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), pfsync(4),
       tcp(4),	udp(4),	  hosts(5),   pf.os(5),	  protocols(5),	  services(5),
       ftp-proxy(8), pfctl(8), pflogd(8)

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

FreeBSD	13.0		       December	7, 2019			    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+13.0-RELEASE+and+Ports>

home | help