diff options
Diffstat (limited to 'static/openbsd/man5/pf.conf.5')
| -rw-r--r-- | static/openbsd/man5/pf.conf.5 | 3171 |
1 files changed, 3171 insertions, 0 deletions
diff --git a/static/openbsd/man5/pf.conf.5 b/static/openbsd/man5/pf.conf.5 new file mode 100644 index 00000000..3a383b23 --- /dev/null +++ b/static/openbsd/man5/pf.conf.5 @@ -0,0 +1,3171 @@ +.\" $OpenBSD: pf.conf.5,v 1.609 2026/01/18 16:38:01 schwarze Exp $ +.\" +.\" Copyright (c) 2002, Daniel Hartmeier +.\" Copyright (c) 2003 - 2013 Henning Brauer <henning@openbsd.org> +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" +.\" - Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" - Redistributions in binary form must reproduce the above +.\" copyright notice, this list of conditions and the following +.\" disclaimer in the documentation and/or other materials provided +.\" with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +.\" "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +.\" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +.\" FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +.\" COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +.\" BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +.\" LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +.\" CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +.\" ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +.\" POSSIBILITY OF SUCH DAMAGE. +.\" +.Dd $Mdocdate: January 18 2026 $ +.Dt PF.CONF 5 +.Os +.Sh NAME +.Nm pf.conf +.Nd packet filter configuration file +.Sh DESCRIPTION +The +.Xr pf 4 +packet filter modifies, drops, or passes packets according to rules or +definitions specified in +.Nm . +.Pp +This is an overview of the sections in this manual page: +.Bl -inset +.It Sx PACKET FILTERING +including network address translation (NAT). +.It Sx OPTIONS +globally tune the behaviour of the packet filtering engine. +.It Sx QUEUEING +provides rule-based bandwidth and traffic control. +.It Sx TABLES +provide a method for dealing with large numbers of addresses. +.It Sx ANCHORS +are containers for rules and tables. +.It Sx STATEFUL FILTERING +tracks packets by state. +.It Sx TRAFFIC NORMALISATION +includes scrub, fragment handling, and blocking spoofed traffic. +.It Sx OPERATING SYSTEM FINGERPRINTING +is a method for detecting a host's operating system. +.It Sx EXAMPLES +provides some example rulesets. +.It Sx GRAMMAR +provides a complete BNF grammar reference. +.El +.Pp +The current line can be extended over multiple lines using a backslash +.Pq Sq \e . +Comments can be put anywhere in the file using a hash mark +.Pq Sq # , +and extend to the end of the current line. +Care should be taken when commenting out multi-line text: +the comment is effective until the end of the entire block. +.Pp +Arguments not beginning with a letter, digit, or underscore +must be quoted. +.Pp +Additional configuration files can be included with the +.Ic include +keyword, for example: +.Bd -literal -offset indent +include "/etc/pf/sub.filter.conf" +.Ed +.Pp +A macro is defined with a command of the form +.Ar name Ns = Ns Ar value . +The macro +.Ar name +can contain letters, digits, and underscores and cannot be a reserved word +(for example, +.Ic pass , +.Cm in , +or +.Cm out ) . +Within unquoted arguments, the string +.Pf $ Ar name +is later expanded to +.Ar value . +.Pp +For example: +.Bd -literal -offset indent +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 +.Ed +.Sh PACKET FILTERING +.Xr pf 4 +has the ability to +.Ic block , +.Ic pass , +and +.Ic match +packets based on attributes of their layer 3 +and layer 4 headers. +Filter rules determine which of these actions are taken; +filter parameters specify the packets to which a rule applies. +.Pp +Each time a packet processed by the packet filter comes in on or +goes out through an interface, the filter rules are evaluated in +sequential order, from first to last. +For +.Ic block +and +.Ic pass , +the last matching rule decides what action is taken; +if no rule matches the packet, the default action is to pass +the packet without creating a state. +For +.Ic match , +rules are evaluated every time they match; +the pass/block state of a packet remains unchanged. +.Pp +Most parameters are optional. +If a parameter is specified, the rule only applies to packets with +matching attributes. +The matching for some parameters can be inverted with the +.Cm !\& +operator. +Certain parameters can be expressed as lists, in which case +.Xr pfctl 8 +generates all needed rule combinations. +.Pp +By default +.Xr pf 4 +filters packets statefully: +the first time a packet matches a +.Ic pass +rule, a state entry is created. +The packet filter examines each packet to see if it matches an existing state. +If it does, the packet is passed without evaluation of any rules. +After the connection is closed or times out, the state entry is automatically +removed. +.Pp +The following actions can be used in the filter: +.Bl -tag -width Ds +.It Ic block +The packet is blocked. +There are a number of ways in which a +.Ic block +rule can behave when blocking a packet. +The default behaviour is to +.Cm drop +packets silently, however this can be overridden or made +explicit either globally, by setting the +.Cm block-policy +option, or on a per-rule basis with one of the following options: +.Pp +.Bl -tag -width return-icmp6 -compact +.It Cm drop +The packet is silently dropped. +.It Cm return +This causes a TCP RST to be returned for TCP packets +and an ICMP UNREACHABLE for other types of packets. +.It Cm return-icmp +.It Cm 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. +.It Cm return-rst +This applies only to TCP packets, +and issues a TCP RST which closes the connection. +An optional parameter, +.Cm ttl , +may be given with a TTL value. +.El +.Pp +Options returning ICMP packets currently have no effect if +.Xr pf 4 +operates on a +.Xr bridge 4 , +as the code to support this feature has not yet been implemented. +.Pp +The simplest mechanism to block everything by default and only pass +packets that match explicit rules is specify a first filter rule of: +.Pp +.Dl block all +.It Ic match +The packet is matched. +This mechanism is used to provide fine grained filtering +without altering the block/pass state of a packet. +.Ic match +rules differ from +.Ic block +and +.Ic pass +rules in that parameters are set every time a packet matches the +rule, not only on the last matching rule. +For the following parameters, +this means that the parameter effectively becomes +.Dq sticky +until explicitly overridden: +.Cm nat-to , +.Cm binat-to , +.Cm rdr-to , +.Cm queue , +.Cm rtable , +and +.Cm scrub . +.Pp +.Cm log +is different still, +in that the action happens every time a rule matches +i.e. a single packet can get logged more than once. +.It Ic pass +The packet is passed; +state is created unless the +.Cm no state +option is specified. +.El +.Pp +The following parameters can be used in the filter: +.Bl -tag -width Ds +.It Cm in No or Cm out +A packet always comes in on, or goes out through, one interface. +.Cm in +and +.Cm out +apply to incoming and outgoing packets; +if neither are specified, +the rule will match packets in both directions. +.It Cm log Pq Cm all | matches | to Ar interface | Cm user +In addition to any action specified, +log the packet. +Only the packet that establishes the state is logged, +unless the +.Cm no state +option is specified. +The logged packets are sent to a +.Xr pflog 4 +interface, by default +.Pa pflog0 ; +pflog0 is monitored by the +.Xr pflogd 8 +logging daemon which logs to the file +.Pa /var/log/pflog +in pcap binary format. +.Pp +The keywords +.Cm all , matches , to , +and +.Cm user +are optional and can be combined using commas, +but must be enclosed in parentheses if given. +.Pp +Use +.Cm all +to force logging of all packets for a connection. +This is not necessary when +.Cm no state +is explicitly specified. +.Pp +If +.Cm matches +is specified, +it logs the packet on all subsequent matching rules. +It is often combined with +.Cm to Ar interface +to avoid adding noise to the default log file. +.Pp +The keyword +.Cm user +logs the UID and PID of the +socket on the local host used to send or receive a packet, +in addition to the normal information. +.Pp +To specify a logging interface other than +.Pa pflog0 , +use the syntax +.Cm to Ar interface . +.It Cm quick +If a packet matches a rule which has the +.Cm quick +option set, this rule +is considered the last matching rule, and evaluation of subsequent rules +is skipped. +.It Cm on Ar interface | Cm any +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 +.Ic group +keyword in +.Xr ifconfig 8 . +.Cm any +will match any existing interface except loopback ones. +.It Cm on rdomain Ar number +This rule applies only to packets coming in on, or going out through, this +particular routing domain. +.It Cm inet | inet6 +This rule applies only to packets of this address family. +.It Cm proto Ar protocol +This rule applies only to packets of this protocol. +Common protocols are ICMP, ICMP6, TCP, and UDP. +For a list of all the protocol name to number mappings used by +.Xr pfctl 8 , +see the file +.Pa /etc/protocols . +.It Xo +.Cm from Ar source +.Cm port Ar source +.Cm os Ar source +.Cm to Ar dest +.Cm port Ar dest +.Xc +This rule applies only to packets with the specified source and destination +addresses and ports. +.Pp +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: +.Pp +.Bl -tag -width urpf-failed -compact +.It Cm any +Any address. +.It Cm no-route +Any address which is not currently routable. +.It Cm route Ar label +Any address matching the given +.Xr route 8 +.Ar label . +.It Cm self +Expands to all addresses assigned to all interfaces. +.It Pf < Ar table Ns > +Any address matching the given +.Ar table . +.It Cm 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. +.El +.Pp +Ranges of addresses are specified using the +.Sq - +operator. +For instance: +.Dq 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. +.Pp +Interface names, interface group names, and +.Cm self +can have modifiers appended: +.Pp +.Bl -tag -width :broadcast -compact +.It Cm :0 +Do not include interface aliases. +.It Cm :broadcast +Translates to the interface's broadcast address(es). +.It Cm :network +Translates to the network(s) attached to the interface. +.It Cm :peer +Translates to the point-to-point interface's peer address(es). +.El +.Pp +Host names may also have the +.Cm :0 +modifier appended to restrict the name resolution to the first of each +v4 and v6 address found. +.Pp +Host name resolution and interface to address translation are done at +ruleset load-time. +When the address of an interface (or host name) changes (under DHCP or PPP, +for instance), the ruleset must be reloaded for the change to be reflected +in the kernel. +Surrounding the interface name (and optional modifiers) in parentheses +changes this behaviour. +When the interface name is surrounded by parentheses, the rule is +automatically updated whenever the interface changes its address. +The ruleset does not need to be reloaded. +This is especially useful with NAT. +.Pp +Ports can be specified either by number or by name. +For example, port 80 can be specified as +.Cm www . +For a list of all port name to number mappings used by +.Xr pfctl 8 , +see the file +.Pa /etc/services . +.Pp +Ports and ranges of ports are specified using these operators: +.Bd -literal -offset indent += (equal) +!= (unequal) +< (less than) +<= (less than or equal) +> (greater than) +>= (greater than or equal) +: (range including boundaries) +>< (range excluding boundaries) +<> (except range) +.Ed +.Pp +.Sq >< , +.Sq <> +and +.Sq \&: +are binary operators (they take two arguments). +For instance: +.Bl -tag -width Ds +.It Li port 2000:2004 +means +.Sq all ports \(>= 2000 and \(<= 2004 , +hence ports 2000, 2001, 2002, 2003, and 2004. +.It Li port 2000 >< 2004 +means +.Sq all ports > 2000 and < 2004 , +hence ports 2001, 2002, and 2003. +.It Li port 2000 <> 2004 +means +.Sq all ports < 2000 or > 2004 , +hence ports 1\(en1999 and 2005\(en65535. +.El +.Pp +The operating system of the source host can be specified in the case of TCP +rules with the +.Cm os +modifier. +See the +.Sx OPERATING SYSTEM FINGERPRINTING +section for more information. +.Pp +The +.Cm host , +.Cm port , +and +.Cm os +specifications are optional, as in the following examples: +.Bd -literal -offset indent +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 \e + to ! 10.1.2.3 port != ssh +pass in proto tcp from any os "OpenBSD" +pass in proto tcp from route "DTAG" +.Ed +.El +.Pp +The following additional parameters can be used in the filter: +.Pp +.Bl -tag -width Ds -compact +.It Cm all +This is equivalent to +.Ql from any to any . +.Pp +.It Cm allow-opts +By default, packets with IPv4 options or IPv6 hop-by-hop or destination +options header are blocked. +When +.Cm allow-opts +is specified for a +.Ic pass +rule, packets that pass the filter based on that rule (last matching) +do so even if they contain options. +For packets that match state, the rule that initially created the +state is used. +The implicit pass rule, that is used when a packet does not match +any rules, does not allow IP options or option headers. +Note that IPv6 packets with type 0 routing headers are always dropped. +.Pp +.It Cm divert-packet port Ar port +Used to send matching packets to +.Xr divert 4 +sockets bound to port +.Ar port . +If the default option of fragment reassembly is enabled, scrubbing with +.Cm reassemble tcp +is also enabled for +.Cm divert-packet +rules. +.Pp +.It Cm divert-reply +Used to receive replies for sockets that are bound to addresses +which are not local to the machine. +See +.Xr setsockopt 2 +for information on how to bind these sockets. +.Pp +.It Cm divert-to Ar host Cm port Ar port +Used to redirect packets to a local socket bound to +.Ar host +and +.Ar port . +The packets will not be modified, preserving the original destination +address for the application to access. +.Dv SOCK_STREAM +connections can access the original destination address using +.Xr getsockname 2 . +.Dv SOCK_DGRAM +sockets can be configured with the +.Xr ip 4 +.Dv IP_RECVDSTADDR +and +.Dv IP_RECVDSTPORT +socket options when receiving IPv4 packets, or the +.Xr ip6 4 +.Dv IPV6_RECVPKTINFO +and +.Dv IPV6_RECVDSTPORT +socket options when receiving IPv6 packets. +.Pp +.It Cm flags Ar a Ns / Ns Ar b | Cm any +This rule only applies to TCP packets that have the flags +.Ar a +set out of set +.Ar b . +Flags not specified in +.Ar b +are ignored. +For stateful connections, the default is +.Cm flags S/SA . +To indicate that flags should not be checked at all, specify +.Cm flags any . +The flags are: (F)IN, (S)YN, (R)ST, (P)USH, (A)CK, (U)RG, (E)CE, and C(W)R. +.Bl -tag -width "flags /SFRA" +.It Cm flags S/S +Flag SYN is set. +The other flags are ignored. +.It Cm 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. +.It Cm flags /SFRA +If the first set is not specified, it defaults to none. +All of SYN, FIN, RST, and ACK must be unset. +.El +.Pp +Because +.Cm flags S/SA +is applied by default (unless +.Cm 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 +.Pq non-SYN +packets, by specifying +.Cm flags any . +This will cause +.Xr pf 4 +to synchronize 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 +.Cm af-to , +.Cm modulate state , +.Cm nat-to , +.Cm rdr-to , +or +.Cm synproxy state +options, or scrubbed with +.Cm reassemble tcp , +will also not be recoverable from intermediate packets. +Such connections will stall and time out. +.Pp +.It Cm group Ar group +Similar to +.Cm user , +this rule only applies to packets of sockets owned by the specified +.Ar group . +.Pp +.It Cm icmp-type Ar type Op Cm code Ar code +.It Cm icmp6-type Ar type Op Cm code Ar code +This rule only applies to ICMP or ICMP6 packets with the specified type +and code. +Text names for ICMP types and codes are listed in +.Xr icmp 4 +and +.Xr icmp6 4 . +The protocol and the ICMP type indicator +.Po +.Cm icmp-type +or +.Cm icmp6-type +.Pc +must match. +.Pp +ICMP responses are not permitted unless they either match an +existing request, or unless +.Cm no state +or +.Cm keep state (sloppy) +is specified. +.Pp +.It Cm label Ar string +Adds a label to the rule, which can be used to identify the rule. +For instance, +.Ql pfctl -s labels +shows per-rule statistics for rules that have labels. +.Pp +The following macros can be used in labels: +.Pp +.Bl -tag -width "$srcaddrXXX" -compact -offset indent +.It Va $dstaddr +The destination IP address. +.It Va $dstport +The destination port specification. +.It Va $if +The interface. +.It Va $nr +The rule number. +.It Va $proto +The protocol name. +.It Va $srcaddr +The source IP address. +.It Va $srcport +The source port specification. +.El +.Pp +For example: +.Bd -literal -offset indent -compact +ips = "{ 1.2.3.4, 1.2.3.5 }" +pass in proto tcp from any to $ips \e + port > 1023 label "$dstaddr:$dstport" +.Ed +.Pp +Expands to: +.Bd -literal -offset indent -compact +pass in inet proto tcp from any to 1.2.3.4 \e + port > 1023 label "1.2.3.4:>1023" +pass in inet proto tcp from any to 1.2.3.5 \e + port > 1023 label "1.2.3.5:>1023" +.Ed +.Pp +The macro expansion for the +.Cm label +directive occurs only at configuration file parse time, not during runtime. +.Pp +.It Cm max-pkt-rate Ar number Ns / Ns Ar seconds +Measure the rate of packets matching the rule and states created by it. +When the specified rate is exceeded, the rule stops matching. +Only packets in the direction in which the state was created are considered, +so that typically requests are counted and replies are not. +For example, +to pass up to 100 ICMP packets per 10 seconds: +.Bd -literal -offset indent +block in proto icmp +pass in proto icmp max-pkt-rate 100/10 +.Ed +.Pp +When the rate is exceeded, all ICMP is blocked until the rate falls below +100 per 10 seconds again. +.Pp +.It Cm once +Create a one shot rule. +The first matching packet marks the rule as expired. +Expired rules are skipped and hidden, unless +.Xr pfctl 8 +is used in debug or verbose mode. +.Pp +.It Cm probability Ar number Ns % +A probability attribute can be attached to a rule, +with a value set between 0 and 100%, +in which case the rule is honoured using the given probability value. +For example, the following rule will drop 20% of incoming ICMP packets: +.Pp +.Dl block in proto icmp probability 20% +.Pp +.It Cm state limiter Ar name Oo Cm (limiter options) Oc +Use the specified state limiter to restrict the creation of states +by this rule. +By default if capacity is not available, the packet gets blocked +and ruleset evaluation stops. +Use +.Ic no-match +option to change default behavior such rule is ignored and ruleset +evaluation continues with next rule. +See the +.Sx State Limiters +section for more information. +.Pp +.It Cm source limiter Ar name Oo Cm (limiter options) Oc +Use the specified source limiter to restrict the creation of states +by this rule. +By default if capacity is not available, the packet gets blocked +and ruleset evaluation stops. +Use +.Ic no-match +option to change default behavior such rule is ignored and ruleset +evaluation continues with next rule. +See the +.Sx Source Limiters +section for more information. +.Pp +.It Cm prio Ar number +Only match packets which have the given queueing priority assigned. +.Pp +.It Oo Cm \&! Oc Ns Cm received-on Ar interface +Only match packets which were received on the specified +.Cm interface +(or interface group). +.Cm any +will match any existing interface except loopback ones. +.Pp +.It Cm rtable Ar number +Used to select an alternate routing table for the routing lookup. +Only effective before the route lookup happened, i.e. when filtering inbound. +.Pp +.It Cm set delay Ar milliseconds +Packets matching this rule will be delayed at the outbound interface by the +given number of milliseconds. +.Pp +.It Cm set prio Ar priority | Pq Ar priority , priority +Packets matching this rule will be assigned a specific queueing priority. +Priorities are assigned as integers 0 through 7, +with a default priority of 3. +If the packet is transmitted on a +.Xr vlan 4 +interface, the queueing priority will also be written as the priority +code point in the 802.1Q VLAN header. +If two priorities are given, TCP ACKs with no data payload and packets +which have a TOS of +.Cm lowdelay +will be assigned to the second one. +Packets with a higher priority number are processed first, +and packets with the same priority are processed +in the order in which they are received. +.Pp +For example: +.Bd -literal -offset indent +pass in proto tcp to port 25 set prio 2 +pass in proto tcp to port 22 set prio (2, 5) +.Ed +.Pp +The interface priority queues accessed by the +.Cm set prio +keyword are always enabled and do not require any additional +configuration, unlike the queues described below and in the +.Sx QUEUEING +section. +.Pp +.It Cm set queue Ar queue | Pq Ar queue , queue +Packets matching this rule will be assigned to the specified +.Ar queue . +If two queues are given, packets which have a TOS of +.Cm lowdelay +and TCP ACKs with no data payload will be assigned to the second one. +See +.Sx QUEUEING +for setup details. +.Pp +For example: +.Bd -literal -offset indent +pass in proto tcp to port 25 set queue mail +pass in proto tcp to port 22 set queue(ssh_bulk, ssh_prio) +.Ed +.Pp +.It Cm set tos Ar string | number +Enforces a TOS for matching packets. +.Ar string +may be one of +.Cm critical , +.Cm inetcontrol , +.Cm lowdelay , +.Cm netcontrol , +.Cm throughput , +.Cm reliability , +or one of the DiffServ Code Points: +.Cm ef , +.Cm af11 No ... Cm af43 , +.Cm cs0 No ... Cm cs7 ; +.Ar number +may be either a hex or decimal number. +.Pp +.It Cm tag Ar string +Packets matching this rule will be tagged with the specified +.Ar 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 +.Dq 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. +Tags take the same macros as labels (see above). +.Pp +.It Oo Cm \&! Oc Ns Cm tagged Ar string +Used with filter or translation rules +to specify that packets must already +be tagged with the given +.Ar string +in order to match the rule. +.Pp +.It Cm tos Ar string | number +This rule applies to packets with the specified TOS bits set. +.Ar string +may be one of +.Cm critical , +.Cm inetcontrol , +.Cm lowdelay , +.Cm netcontrol , +.Cm throughput , +.Cm reliability , +or one of the DiffServ Code Points: +.Cm ef , +.Cm af11 No ... Cm af43 , +.Cm cs0 No ... Cm cs7 ; +.Ar number +may be either a hex or decimal number. +.Pp +For example, the following rules are identical: +.Bd -literal -offset indent +pass all tos lowdelay +pass all tos 0x10 +pass all tos 16 +.Ed +.Pp +.It Cm user Ar user +This rule only applies to packets of sockets owned by the specified +.Ar user . +For outgoing connections initiated from the firewall, this is the user +that opened the connection. +For incoming connections to the firewall itself, this is the user that +listens on the destination port. +.Pp +When listening sockets are bound to the wildcard address, +.Xr pf 4 +cannot determine if a connection is destined for the firewall itself. +To avoid false matches on just the destination port, combine a +.Cm user +rule with source or destination address +.Cm self . +.Pp +All packets, both outgoing and incoming, of one connection are associated +with the same user and group. +Only TCP and UDP packets can be associated with users. +.Pp +The +.Ar user +and +.Ar group +arguments 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. +.Pp +User and group IDs can be specified as either numbers or names. +The syntax is similar to the one for ports. +The following example allows only selected users to open outgoing +connections: +.Bd -literal -offset indent +block out proto tcp all +pass out proto tcp from self user { < 1000, dhartmei } +.Ed +.Pp +The example below permits users with uid between 1000 and 1500 +to open connections: +.Bd -literal -offset indent +block out proto tcp all +pass out proto tcp from self user { 999 >< 1501 } +.Ed +.Pp +The +.Sq \&: +operator, which works for port number matching, does not work for +.Cm user +and +.Cm group +match. +.El +.Ss Translation +Translation options modify either the source or destination address and +port of the packets associated with a stateful connection. +.Xr pf 4 +modifies the specified address and/or port in the packet and recalculates +IP, TCP, and UDP checksums as necessary. +.Pp +If specified on a +.Ic match +rule, subsequent rules will see packets as they look +after any addresses and ports have been translated. +These rules will therefore have to filter based on the translated +address and port number. +.Pp +The state entry created permits +.Xr pf 4 +to keep track of the original address for traffic associated with that state +and correctly direct return traffic for that connection. +.Pp +Different types of translation are possible with pf: +.Bl -tag -width binat-to +.It Cm af-to +Translation between different address families (NAT64) is handled +using +.Cm af-to +rules. +Because address family translation overrides the routing table, it's +only possible to use +.Cm af-to +on inbound rules, and a source address for the resulting translation +must always be specified. +.Pp +The optional second argument is the host or subnet the original +addresses are translated into for the destination. +The lowest bits of the original destination address form the host +part of the new destination address according to the specified subnet. +It is possible to embed a complete IPv4 address into an IPv6 address +using a network prefix of /96 or smaller. +.Pp +When a destination address is not specified, it is assumed that the host +part is 32-bit long. +For IPv6 to IPv4 translation this would mean using only the lower 32 +bits of the original IPv6 destination address. +For IPv4 to IPv6 translation the destination subnet defaults to the +subnet of the new IPv6 source address with a prefix length of /96. +See RFC 6052 Section 2.2 for details on how the prefix determines the +destination address encoding. +.Pp +For example, the following rules are identical: +.Bd -literal -offset indent +pass in inet af-to inet6 from 2001:db8::1 to 2001:db8::/96 +pass in inet af-to inet6 from 2001:db8::1 +.Ed +.Pp +In the above example the matching IPv4 packets will be modified to +have a source address of 2001:db8::1 and a destination address will +get prefixed with 2001:db8::/96, e.g. 198.51.100.100 will be +translated to 2001:db8::c633:6464. +.Pp +In the reverse case the following rules are identical: +.Bd -literal -offset indent +pass in inet6 from any to 64:ff9b::/96 af-to inet \e + from 198.51.100.1 to 0.0.0.0/0 +pass in inet6 from any to 64:ff9b::/96 af-to inet \e + from 198.51.100.1 +.Ed +.Pp +The destination IPv4 address is assumed to be embedded inside the +original IPv6 destination address, e.g. 64:ff9b::c633:6464 will be +translated to 198.51.100.100. +.Pp +The current implementation will only extract IPv4 addresses from the +IPv6 addresses with a prefix length of /96 and greater. +.It Cm binat-to +A +.Cm binat-to +rule specifies a bidirectional mapping between an external IP +netblock and an internal IP netblock. +It expands to an outbound +.Cm nat-to +rule and an inbound +.Cm rdr-to +rule. +.It Cm nat-to +A +.Cm nat-to +option specifies that IP addresses are to be changed as the packet +traverses the given interface. +This technique allows one or more IP addresses +on the translating host to support network traffic for a larger range of +machines on an +.Dq 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. +Those netblocks are: +.Bd -literal -offset indent +10.0.0.0 \(en 10.255.255.255 (all of net 10, i.e. 10/8) +172.16.0.0 \(en 172.31.255.255 (i.e. 172.16/12) +192.168.0.0 \(en 192.168.255.255 (i.e. 192.168/16) +.Ed +.Pp +.Cm nat-to +is usually applied outbound. +If applied inbound, nat-to to a local IP address is not supported. +.It Cm rdr-to +The packet is redirected to another destination and possibly a +different port. +.Cm rdr-to +can optionally specify port ranges instead of single ports. +For instance: +.Bl -tag -width Ds +.It match in ... port 2000:2999 rdr-to ... port 4000 +redirects ports 2000 to 2999 (inclusive) to port 4000. +.It match in ... port 2000:2999 rdr-to ... port 4000:* +redirects port 2000 to 4000, port 2001 to 4001, ..., port 2999 to 4999. +.El +.Pp +.Cm rdr-to +is usually applied inbound. +If applied outbound, rdr-to to a local IP address is not supported. +.El +.Pp +In addition to modifying the address, some translation rules may modify +source or destination ports for TCP or UDP connections; +implicitly in the case of +.Cm nat-to +options and explicitly in the case of +.Cm rdr-to +ones. +Port numbers are never translated with a +.Cm binat-to +rule. +.Pp +Translation options apply only to packets that pass through the specified +interface, and if no interface is specified, translation is applied +to packets on all interfaces. +For instance, redirecting port 80 on an external interface to an internal +web server will only work for connections originating from the outside. +Connections to the address of the external interface from local hosts will +not be redirected, since such packets do not actually pass through the +external interface. +Redirections cannot reflect packets back through the interface they arrive +on, they can only be redirected to hosts connected to different interfaces +or to the firewall itself. +.Pp +However packets may be redirected to hosts connected to the interface the +packet arrived on by using redirection with NAT. +For example: +.Bd -literal -offset indent +pass in on $int_if proto tcp from $int_net to $ext_if port 80 \e + rdr-to $server +pass out on $int_if proto tcp to $server port 80 \e + received-on $int_if nat-to $int_if +.Ed +.Pp +Note that redirecting external incoming connections to the loopback address +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. +For example: +.Bd -literal -offset indent +pass in on egress proto tcp from any to any port smtp \e + rdr-to 127.0.0.1 port spamd +.Ed +.Pp +Unless this effect is desired, any of the local non-loopback addresses +should be used instead as the redirection target, which allows external +connections only to daemons bound to this address or not bound to +any address. +.Pp +For +.Cm af-to , +.Cm nat-to +and +.Cm rdr-to +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: +.Bl -tag -width xxxx +.It Cm bitmask +The +.Cm bitmask +option applies the network portion of the redirection address to the address +to be modified (source with +.Cm nat-to , +destination with +.Cm rdr-to ) . +.It Cm least-states Op Cm sticky-address +The +.Cm least-states +option selects the address with the least active states from +a given address pool and considers given weights +associated with address(es). +Weights can be specified between 1 and 65535. +Addresses with higher weights are selected more often. +.Pp +.Cm sticky-address +can be specified to ensure that multiple connections from the +same source are mapped to the same redirection address. +Associations are destroyed as soon as there are +no longer states which refer to them; +in order to make the mappings last +beyond the lifetime of the states, +increase the global options with +.Ic set Cm timeout src.track . +.It Cm random Op Cm sticky-address +The +.Cm random +option selects an address at random within the defined block of addresses. +.Cm sticky-address +is as described above. +.It Cm round-robin Op Cm sticky-address +The +.Cm round-robin +option loops through the redirection address(es) and considers given weights +associated with address(es). +Weights can be specified between 1 and 65535. +Addresses with higher weights are selected more often. +.Cm sticky-address +is as described above. +.It Cm source-hash Oo Ar key Oc Op Cm sticky-address +The +.Cm source-hash +option uses a hash of the source address to determine the redirection address, +ensuring that the redirection address is always the same for a given source. +An optional +.Ar key +can be specified after this keyword either in hex or as a string; +by default +.Xr pfctl 8 +randomly generates a key for source-hash every time the +ruleset is reloaded. +.Cm sticky-address +is as described above. +.It Cm static-port +With +.Cm nat-to +rules, the +.Cm static-port +option prevents +.Xr pf 4 +from modifying the source port on TCP and UDP packets. +.El +.Pp +When more than one redirection address or a table is specified, +.Cm bitmask +is not permitted as a pool type. +.Ss Routing +If a packet matches a rule with one of the following route options 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. +.Bl -tag -width route-to +.It Cm dup-to +The +.Cm dup-to +option creates a duplicate of the packet and routes it like +.Cm route-to . +The original packet gets routed as it normally would. +.It Cm reply-to +The +.Cm reply-to +option is similar to +.Cm route-to , +but routes packets that pass in the opposite direction (replies) to the +specified address. +Opposite direction is only defined in the context of a state entry, and +.Cm reply-to +is useful only in rules that create state. +It can be used on systems with multiple paths to the internet to ensure +that replies to an incoming network connection to a particular address +are sent using the path associated with that address (symmetric routing +enforcement). +.It Cm route-to +The +.Cm route-to +option routes the packet to the specified destination address instead +of the destination address in the packet header. +When a +.Cm 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. +.El +.Pp +For the +.Cm dup-to , +.Cm reply-to , +and +.Cm route-to +route 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), +the methods +.Cm least-states , +.Cm random , +.Cm round-robin , +and +.Cm source-hash , +as described above, +can be used. +.Sh OPTIONS +.Xr pf 4 +may be tuned for various situations using the +.Ic set +command. +.Bl -tag -width Ds +.It Ic set Cm block-policy drop | return +The +.Cm block-policy +option sets the default behaviour for the packet +.Ic block +action: +.Pp +.Bl -tag -width return -compact +.It Cm drop +Packet is silently dropped. +.It Cm 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. +.El +.Pp +The default value is +.Cm drop . +.It Ic set Cm debug Ar level +Set the debug +.Ar level , +which limits the severity of log messages printed by +.Xr pf 4 . +This should be a keyword from the following ordered list +(highest to lowest): +.Cm emerg , +.Cm alert , +.Cm crit , +.Cm err , +.Cm warning , +.Cm notice , +.Cm info , +and +.Cm debug . +These keywords correspond to the similar (LOG_) values specified to the +.Xr syslog 3 +library routine. +The default value is +.Cm err . +.It Cm set Cm fingerprints Ar filename +Load fingerprints of known operating systems from the given +.Ar filename . +By default fingerprints of known operating systems are automatically +loaded from +.Xr pf.os 5 , +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. +The default location for fingerprints is +.Pa /etc/pf.os . +.It Ic set Cm hostid Ar number +The 32-bit hostid +.Ar number +identifies this firewall's state table entries to other firewalls +in a +.Xr pfsync 4 +failover cluster. +By default the hostid is set to a pseudo-random value, however it may be +desirable to manually configure it, for example to more easily identify the +source of state table entries. +The hostid may be specified in either decimal or hexadecimal. +.It Ic set Cm limit Ar limit-item number +Sets hard limits on the memory pools used by the packet filter. +See +.Xr pool 9 +for an explanation of memory pools. +.Pp +Limits can be set on the following: +.Bl -tag -width pktdelay_pkts +.It Cm states +Set the maximum number of entries in the memory pool used by state table +entries (those generated by +.Ic pass +rules which do not specify +.Cm no state ) . +The default is 100000. +.It Cm src-nodes +Set the maximum number of entries in the memory pool used for tracking +source IP addresses (generated by the +.Cm sticky-address +and +.Cm src.track +options). +The default is 10000. +.It Cm frags +Set the maximum number of entries in the memory pool used for fragment +reassembly. +The maximum may not exceed, and should be well below, +the maximum number of mbuf clusters +.Pq sysctl kern.maxclusters +in the system. +The default is NMBCLUSTERS/32. +.Dv NMBCLUSTERS +defines the total number of packets which can exist in-system at any one time. +Refer to +.In machine/param.h +for the platform-specific value. +.It Cm tables +Set the number of tables that can exist. +The default is 1000. +.It Cm table-entries +Set the number of addresses that can be stored in tables. +The default is 200000, or 100000 on machines with +less than 100MB of physical memory. +.It Cm pktdelay_pkts +Set the maximum number of packets that can be held in the delay queue. +The default is 10000. +.It Cm anchors +Set the number of anchors that can exist. +The default is 512. +.El +.Pp +Multiple limits can be combined on a single line: +.Bd -literal -offset indent +set limit { states 20000, frags 2000, src-nodes 2000 } +.Ed +.It Ic set Cm loginterface Ar interface | Cm none +Enable collection of packet and byte count statistics for the given +interface or interface group. +These statistics can be viewed using: +.Pp +.Dl # pfctl -s info +.Pp +In this example +.Xr pf 4 +collects statistics on the interface named dc0: +.Pp +.Dl set loginterface dc0 +.Pp +One can disable the loginterface using: +.Pp +.Dl set loginterface none +.Pp +The default value is +.Cm none . +.It Ic set Cm optimization Ar environment +Optimize state timeouts for one of the following network environments: +.Pp +.Bl -tag -width Ds -compact +.It Cm aggressive +Aggressively expire connections. +This can greatly reduce the memory usage of the firewall at the cost of +dropping idle connections early. +.It Cm conservative +Extremely conservative settings. +Avoid dropping legitimate connections at the +expense of greater memory utilization (possibly much greater on a busy +network) and slightly increased processor utilization. +.It Cm high-latency +A high-latency environment (such as a satellite connection). +.It Cm normal +A normal network environment. +Suitable for almost all networks. +.It Cm satellite +Alias for +.Cm high-latency . +.El +.Pp +The default value is +.Cm normal . +.It Ic set Cm reassemble yes | no Op Cm no-df +The +.Cm reassemble +option is used to enable or disable the reassembly of fragmented packets, +and can be set to +.Cm yes +(the default) or +.Cm no . +If +.Cm no-df +is also specified, fragments with the +.Dq dont-fragment +bit set are reassembled too, +instead of being dropped; +the reassembled packet will have the +.Dq dont-fragment +bit cleared. +The default value is +.Cm yes . +.It Ic set Cm ruleset-optimization Ar level +.Bl -tag -width profile -compact +.It Cm basic +Enable basic ruleset optimization. +This is the default behaviour. +Basic ruleset optimization does four things to improve the +performance of ruleset evaluations: +.Pp +.Bl -enum -compact +.It +remove duplicate rules +.It +remove rules that are a subset of another rule +.It +combine multiple rules into a table when advantageous +.It +reorder the rules to improve evaluation performance +.El +.Pp +.It Cm none +Disable the ruleset optimizer. +.It Cm profile +Uses the currently loaded ruleset as a feedback profile to tailor the +ordering of +.Cm quick +rules to actual network traffic. +.El +.Pp +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 important for billing purposes or whatnot, +either the ruleset optimizer should not be used or a label field should +be added to all of the accounting rules to act as optimization barriers. +.Pp +Optimization can also be set as a command-line argument to +.Xr pfctl 8 , +overriding the settings in +.Nm . +.It Ic set Cm skip on Ar ifspec +List interfaces for which packets should not be filtered. +Packets 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 filtering is not desired and can have unexpected effects. +PF filters traffic on all interfaces by default. +.It Ic set Cm state-defaults Ar state-option , ... +The +.Cm state-defaults +option sets the state options for states created from rules +without an explicit +.Cm keep state . +For example: +.Pp +.Dl set state-defaults pflow, no-sync +.It Ic set Cm state-policy if-bound | floating +The +.Cm state-policy +option sets the default behaviour for states: +.Pp +.Bl -tag -width if-bound -compact +.It Cm if-bound +States are bound to an interface. +.It Cm floating +States can match packets on any interfaces (the default). +.El +.It Ic set Cm syncookies never | always | adaptive +When +.Cm syncookies +are active, pf will answer each and every incoming TCP SYN with a +syncookie SYNACK, without allocating any resources. +Upon reception of the client's ACK in response to the syncookie +SYNACK, pf will evaluate the ruleset and create state if the ruleset +permits it, complete the three way handshake with the target host, +and continue the connection with synproxy in place. +This allows pf to be resilient against large synflood attacks, +which could otherwise exhaust the state table. +Due to the blind answers to each and every SYN, +syncookies share the caveats of synproxy: +seemingly accepting connections that will be dropped later on. +.Pp +.Bl -tag -width adaptive -compact +.It Cm never +pf will never send syncookie SYNACKs (the default). +.It Cm always +pf will always send syncookie SYNACKs. +.It Cm adaptive +pf will enable syncookie mode when a given percentage of the state table +is used up by half-open TCP connections, such as those that saw the initial +SYN but didn't finish the three way handshake. +The thresholds for entering and leaving syncookie mode can be specified using: +.Bd -literal -offset indent +set syncookies adaptive (start 25%, end 12%) +.Ed +.El +.It Ic set Cm timeout Ar variable value +.Bl -tag -width "src.track" -compact +.It Cm frag +Seconds before an unassembled fragment is expired (60 by default). +.It Cm interval +Interval between purging expired states and fragments (10 seconds by default). +.It Cm src.track +Length of time to retain a source tracking entry after the last state +expires (0 by default, which means there is no global limit. +The value is defined by the rule which creates the state.). +.El +.Pp +When a packet matches a stateful connection, the seconds to live for the +connection will be updated to that of the +protocol and 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. +Alternatively, these values may be adjusted collectively +in a manner suitable for a specific environment using +.Cm set optimization +(see above). +.Pp +.Bl -tag -width Ds -compact +.It Cm tcp.closed Pq 90 seconds by default +The state after one endpoint sends an RST. +.It Cm tcp.closing Pq 900 seconds by default +The state after the first FIN has been sent. +.It Cm tcp.established Pq 24 hours by default +The fully established state. +.It Cm tcp.finwait Pq 45 seconds by default +The state after both FINs have been exchanged and the connection is closed. +Some hosts (notably web servers on Solaris) send TCP packets even after closing +the connection. +Increasing +.Cm tcp.finwait +(and possibly +.Cm tcp.closing ) +can prevent blocking of such packets. +.It Cm tcp.first Pq 120 seconds by default +The state after the first packet. +.It Cm tcp.opening Pq 30 seconds by default +The state after the second packet but before both endpoints have +acknowledged the connection. +.It Cm tcp.tsdiff Pq 30 seconds by default +Maximum allowed time difference between RFC 1323 compliant packet timestamps. +.El +.Pp +ICMP and UDP are handled in a fashion similar to TCP, but with a much more +limited set of states: +.Pp +.Bl -tag -width Ds -compact +.It Cm icmp.error Pq 10 seconds by default +The state after an ICMP error came back in response to an ICMP packet. +.It Cm icmp.first Pq 20 seconds by default +The state after the first packet. +.It Cm udp.first Pq 60 seconds by default +The state after the first packet. +.It Cm udp.multiple Pq 60 seconds by default +The state if both hosts have sent packets. +.It Cm udp.single Pq 30 seconds by default +The state if the source host sends more than one packet but the destination +host has never sent one back. +.El +.Pp +Other protocols are handled similarly to UDP: +.Pp +.Bl -tag -width xxxx -compact +.It Cm other.first Pq 60 seconds by default +.It Cm other.multiple Pq 60 seconds by default +.It Cm other.single Pq 30 seconds by default +.El +.Pp +Timeout values can be reduced adaptively as the number of state table +entries grows. +.Pp +.Bl -tag -width Ds -compact +.It Cm adaptive.start Pq 60000 states by default +When the number of state entries exceeds this value, adaptive scaling +begins. +All timeout values are scaled linearly with factor +(adaptive.end \- number of states) / (adaptive.end \- adaptive.start). +.It Cm adaptive.end Pq 120000 states by default +When reaching this number of state entries, all timeout values become +zero, effectively purging all state entries immediately. +This value is used to define the scale factor; it should not actually +be reached (set a lower state limit, see below). +.El +.Pp +Adaptive timeouts are enabled by default, with an adaptive.start value +equal to 60% of the state limit, and an adaptive.end value equal to +120% of the state limit. +They can be disabled by setting both adaptive.start and adaptive.end to 0. +.Pp +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. +.Pp +For example: +.Bd -literal -offset indent +set timeout tcp.first 120 +set timeout tcp.established 86400 +set timeout { adaptive.start 60000, adaptive.end 120000 } +set limit states 100000 +.Ed +.Pp +With 90000 state table entries, the timeout values are scaled to 50% +(tcp.first 60, tcp.established 43200). +.El +.Pp +.Dq pfctl -F Reset +restores default values for the following options: debug, all limit options, +loginterface, reassemble, skip, syncookies, all timeouts. +.Sh QUEUEING +Packets can be assigned to queues for the purpose of bandwidth +control. +At least one declaration is required to configure queues, and later +any packet filtering rule can reference the defined queues by name. +When filtering, the last referenced +.Ar queue +name is where any passed packets will be queued, while for +blocked packets it specifies where any resulting ICMP or TCP RST +packets should be queued. +If the referenced queue does not exist on the outgoing interface, +the default queue for that interface is used. +Queues attached to an interface build a tree, +thus each queue can have further child queues. +Only leaf queues, i.e. queues without children, can be used to assign +packets to. +The root queue must specifically reference an interface, all other queues +pick up the interfaces they should be created on from their parent queues. +.Pp +In the following example, a queue named std is created on the interface em0, +with 3 child queues ssh, mail and http: +.Bd -literal -offset indent +queue std on em0 bandwidth 100M +queue ssh parent std bandwidth 10M +queue mail parent std bandwidth 10M +queue http parent std bandwidth 80M default +.Ed +.Pp +The specified bandwidth is the target bandwidth, every queue can receive +more bandwidth as long as the parent still has some available. +The maximum bandwidth that should be assigned to a given queue can be limited +using the +.Cm max +keyword. +If a limitation isn't imposed on the root queue, borrowing can result in +saturating the bandwidth of the outgoing interface. +Similarly, a minimum (reserved) bandwidth can be specified: +.Pp +.Dl queue ssh parent std bandwidth 10M min 5M max 25M +.Pp +For each of these 3 bandwidth specifications an additional burst bandwidth and +time can be specified: +.Pp +.Dl queue ssh parent std bandwidth 10M burst 90M for 100ms +.Pp +All +.Cm bandwidth +values are specified as bits per second or using the suffixes +.Cm K , +.Cm M , +and +.Cm G +to represent kilobits, megabits, and gigabits per second, respectively. +The value must not exceed the interface bandwidth. +.Pp +If multiple connections are assigned the same queue, they're not guaranteed +to share the queue bandwidth fairly. +An alternative flow queue manager can be used to achieve fair sharing by +indicating how many simultaneous states are expected with a +.Cm flows +option, unless a minimum bandwidth has been specified as well. +.Pp +When packets are classified by the stateful inspection engine, a flow +identifier is assigned to all packets belonging to the state, +thus limiting the number of individual flows that can be recognized +by the resolution of a flow identifier. +The current implementation is able to classify traffic into 32767 distinct +flows. +However, efficient fair sharing is observed even with a much smaller number +of flows. +For example on a 10Mbit/s DSL or a cable modem uplink, the following simple +configuration can be used: +.Bd -literal -offset 4n +queue outq on em0 bandwidth 9M max 9M flows 1024 qlimit 1024 \e + default +.Ed +.Pp +It's important to specify the upper bound within 90-95% of the expected +bandwidth and raise the default queue limit. +.Pp +If a +.Cm flows +option appears without a +.Cm bandwidth +specification, the flow queue manager is selected as the queueing discipline +for the corresponding interface acting as a default queue for all outgoing +packets. +In such a scenario, a queueing hierarchy is not supported. +.Pp +In addition to the bandwidth and flow specifications, queues support the +following options: +.Bl -tag -width xxxx +.It Cm default +Packets not matched by another queue are assigned to this queue. +Exactly one default queue per interface is required. +.It Cm on Ar interface +Specifies the interface the queue operates on. +If not given, it operates on all matching interfaces. +.It Cm parent Ar name +Defines which parent queue the queue should be attached to. +Mandatory for all queues except root queues. +The parent queue must exist. +.It Cm quantum Ar size +Specifies the quantum of service for the flow queue manager. +The lower the quantum size the more advantage is given to streams of smaller +packets at the expense of bulk transfers. +The default value is set to the configured Maximum Transmission Unit (MTU) +of the specified interface. +.It Cm qlimit Ar limit +The maximum number of packets held in the queue. +The default is 50. +.El +.Pp +Packets can be assigned to queues based on filter rules by using the +.Cm queue +keyword. +Normally only one +.Ar queue +is specified; when a second one is specified it will instead be used for +packets which have a TOS of +.Cm lowdelay +and for TCP ACKs with no data payload. +.Pp +To continue the previous example, the examples below would specify the +four referenced +queues, plus a few child queues. +Interactive +.Xr ssh 1 +sessions get a queue with a minimum bandwidth; +.Xr scp 1 +and +.Xr sftp 1 +bulk transfers go to a separate queue. +The queues are then referenced by filtering rules. +.Bd -literal -offset 4n +queue rootq on em0 bandwidth 100M max 100M +queue http parent rootq bandwidth 60M burst 90M for 100ms +queue developers parent http bandwidth 45M +queue employees parent http bandwidth 15M +queue mail parent rootq bandwidth 10M +queue ssh parent rootq bandwidth 20M +queue ssh_interactive parent ssh bandwidth 10M min 5M +queue ssh_bulk parent ssh bandwidth 10M +queue std parent rootq bandwidth 20M default + +block return out on em0 inet all set queue std +pass out on em0 inet proto tcp from $developerhosts to any port 80 \e + set queue developers +pass out on em0 inet proto tcp from $employeehosts to any port 80 \e + set queue employees +pass out on em0 inet proto tcp from any to any port 22 \e + set queue(ssh_bulk, ssh_interactive) +pass out on em0 inet proto tcp from any to any port 25 \e + set queue mail +.Ed +.Sh TABLES +Tables are named structures which can hold a collection of addresses and +networks. +Lookups against tables in +.Xr pf 4 +are relatively fast, making a single rule with tables much more efficient, +in terms of +processor usage and memory consumption, than a large number of rules which +differ only in IP address (either created explicitly or automatically by rule +expansion). +.Pp +Tables can be used as the source or destination of filter +or translation rules. +They can also be used for the redirect address of +.Cm nat-to +and +.Cm rdr-to +and in the routing options of filter rules, but not for +.Cm bitmask +pools. +.Pp +Tables can be defined with any of the following +.Xr pfctl 8 +mechanisms. +As with macros, reserved words may not be used as table names. +.Bl -tag -width "manually" +.It manually +Persistent tables can be manually created with the +.Cm add +or +.Cm replace +option of +.Xr pfctl 8 , +before or after the ruleset has been loaded. +.It Nm +Table definitions can be placed directly in this file and loaded at the +same time as other rules are loaded, atomically. +Table definitions inside +.Nm +use the +.Ic table +statement, and are especially useful to define non-persistent tables. +The contents of a pre-existing table defined without a list of addresses +to initialize it is not altered when +.Nm +is loaded. +A table initialized with the empty list, +.Li { } , +will be cleared on load. +.El +.Pp +Tables may be defined with the following attributes: +.Bl -tag -width counters +.It Cm const +The +.Cm const +flag prevents the user from altering the contents of the table once it +has been created. +Without that flag, +.Xr pfctl 8 +can be used to add or remove addresses from the table at any time, even +when running with +.Xr securelevel 7 += 2. +.It Cm counters +The +.Cm counters +flag enables per-address packet and byte counters, which can be displayed with +.Xr pfctl 8 . +.It Cm persist +The +.Cm 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. +.El +.Pp +This example creates a table called +.Dq private , +to hold RFC 1918 private network blocks, +and a table called +.Dq badhosts , +which is initially empty. +A filter rule is set up to block all traffic coming from addresses listed in +either table: +.Bd -literal -offset indent +table <private> const { 10/8, 172.16/12, 192.168/16 } +table <badhosts> persist +block on fxp0 from { <private>, <badhosts> } to any +.Ed +.Pp +The private table cannot have its contents changed and the badhosts table +will exist even when no active filter rules reference it. +Addresses may later be added to the badhosts table, so that traffic from +these hosts can be blocked by using the following: +.Pp +.Dl # pfctl -t badhosts -Tadd 204.92.77.111 +.Pp +A table can also be initialized with an address list specified in one or more +external files, using the following syntax: +.Bd -literal -offset indent +table <spam> persist file "/etc/spammers" file "/etc/openrelays" +block on fxp0 from <spam> to any +.Ed +.Pp +The files +.Pa /etc/spammers +and +.Pa /etc/openrelays +list IP addresses, one per line. +Any lines beginning with a +.Sq # +are treated as comments and ignored. +In addition to being specified by IP address, hosts may also be +specified by their hostname. +When the resolver is called to add a hostname to a table, +.Em all +resulting IPv4 and IPv6 addresses are placed into the table. +IP addresses can also be entered in a table by specifying a valid interface +name, a valid interface group, or the +.Cm self +keyword, in which case all addresses assigned to the interface(s) will be +added to the table. +.Sh ANCHORS +Besides the main ruleset, +.Nm +can specify anchor attachment points. +An anchor is a container that can hold rules, +address tables, and other anchors. +When evaluation of the main ruleset reaches an +.Ic anchor +rule, +.Xr pf 4 +will proceed to evaluate all rules specified in that anchor. +.Pp +The following example 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: +.Bd -literal -offset indent +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 +.Ed +.Pp +Anchors can be manipulated through +.Xr pfctl 8 +without reloading the main ruleset or other anchors. +This loads a single rule into the anchor, +which blocks all packets from a specific address: +.Bd -literal -offset indent +# echo "block in quick from 1.2.3.4 to any" | pfctl -a spam -f - +.Ed +.Pp +The anchor can also be populated by adding a +.Ic load anchor +rule after the anchor rule. +When +.Xr pfctl 8 +loads +.Nm , +it will also load all the rules from the file +.Pa /etc/pf-spam.conf +into the anchor. +.Bd -literal -offset indent +anchor spam +load anchor spam from "/etc/pf-spam.conf" +.Ed +.Pp +An anchor rule can also contain a filter ruleset +in a brace-delimited block. +In that case, no separate loading of rules into the anchor +is required. +Brace delimited blocks may contain rules or other brace-delimited blocks. +When an anchor is populated this way, the anchor name becomes optional. +Since the parser specification for anchor names is a string, +double quote characters +.Pq Sq \&" +should be placed around the anchor name. +.Bd -literal -offset indent +anchor "external" on egress { + block + anchor out { + pass proto tcp from any to port { 25, 80, 443 } + } + pass in proto tcp to any port 22 +} +.Ed +.Pp +Anchor rules can also 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: +.Bd -literal -offset indent +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 +.Ed +.Pp +The rules inside anchor "spam" are only evaluated +for TCP packets with destination port 25. +Hence, the following +will only block connections from 1.2.3.4 to port 25: +.Bd -literal -offset indent +# echo "block in quick from 1.2.3.4 to any" | pfctl -a spam -f - +.Ed +.Pp +Matching filter and translation rules marked with the +.Cm 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 +.Cm quick +option, +ruleset evaluation will terminate when the anchor is exited if the packet is +matched by any rule within the anchor. +.Pp +An anchor references other anchor attachment points +using the following syntax: +.Bl -tag -width xxxx +.It Ic anchor Ar name +Evaluates the filter rules in the specified anchor. +.El +.Pp +An anchor has a name which specifies the path where +.Xr pfctl 8 +can be used to access the anchor to perform operations on it, such as +attaching child anchors to it or loading rules into it. +Anchors may be nested, with components separated by +.Sq / +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. +.Pp +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 +.Ic load anchor +rule will be attached under that anchor point. +.Pp +Anchors may end with the asterisk +.Pq Sq * +character, which signifies that all anchors attached at that point +should be evaluated in the alphabetical ordering of their anchor name. +For example, +the following +will evaluate each rule in each anchor attached to the "spam" anchor: +.Bd -literal -offset indent +anchor "spam/*" +.Ed +.Pp +Note that it will only evaluate anchors that are directly attached to the +"spam" anchor, and will not descend to evaluate anchors recursively. +.Pp +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 resolution, if the sequence +.Sq .. +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: +.Bd -literal -offset indent +# printf 'anchor "spam/allowed"\en' | pfctl -f - +# printf 'anchor "../banned"\enpass\en' | pfctl -a spam/allowed -f - +.Ed +.Pp +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 +.Ic pass +rule. +.Sh STATEFUL FILTERING +.Xr pf 4 +filters packets statefully, +which has several advantages. +For TCP connections, comparing a packet to a state involves checking +its sequence numbers, as well as TCP timestamps if a rule using the +.Cm reassemble tcp +parameter applies to the connection. +If these values are outside the narrow windows of expected +values, the packet is dropped. +This prevents spoofing attacks, such as when an attacker sends packets with +a fake source address/port but does not know the connection's sequence +numbers. +Similarly, +.Xr pf 4 +knows how to match ICMP replies to states. +For example, +to allow echo requests (such as those created by +.Xr ping 8 ) +out statefully and match incoming echo replies correctly to states: +.Pp +.Dl pass out inet proto icmp all icmp-type echoreq +.Pp +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). +.Pp +Furthermore, correct handling of ICMP error messages is critical to +many protocols, particularly TCP. +.Xr 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 message referring to a stateful TCP +connection arrives, it will be matched to the state and get passed. +.Pp +Finally, state tracking is required for +.Cm nat-to +and +.Cm rdr-to +options, in order to track address and port translations and reverse the +translation on returning packets. +.Pp +.Xr 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. +.Pp +If stateless filtering of individual packets is desired, +the +.Cm no state +keyword can be used to specify that state will not be created +if this is the last matching rule. +Note that packets which match neither block nor pass rules, +and thus are passed by default, +are effectively passed as if +.Cm no state +had been specified. +.Pp +A number of parameters can also be set to affect how +.Xr pf 4 +handles state tracking, +as detailed below. +.Ss State Modulation +Much of the security derived from TCP is attributable to how well the +initial sequence numbers (ISNs) are chosen. +Some popular stack implementations choose +.Em very +poor ISNs and thus are normally susceptible to ISN prediction exploits. +By applying a +.Cm modulate state +rule to a TCP connection, +.Xr pf 4 +will create a high quality random sequence number for each connection +endpoint. +.Pp +The +.Cm modulate state +directive implicitly keeps state on the rule and is +only applicable to TCP connections. +.Pp +For instance: +.Bd -literal -offset indent +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 \e + modulate state +.Ed +.Pp +Note that modulated connections will not recover when the state table +is lost (firewall reboot, flushing the state table, etc.). +.Xr 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 connection may be left dangling until the +respective endpoints time out the connection. +It is possible on a fast local network for the endpoints to start an ACK +storm while trying to resynchronize after the loss of the modulator. +The default +.Cm flags +settings (or a more strict equivalent) should be used on +.Cm modulate state +rules to prevent ACK storms. +.Pp +Note that alternative methods are available +to prevent loss of the state table +and allow for firewall failover. +See +.Xr carp 4 +and +.Xr pfsync 4 +for further information. +.Ss SYN Proxy +By default, +.Xr pf 4 +passes packets that are part of a +TCP handshake between the endpoints. +The +.Cm synproxy state +option can be used to cause +.Xr pf 4 +itself to complete the handshake with the active endpoint, perform a handshake +with the passive endpoint, and then forward packets between the endpoints. +.Pp +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. +.Pp +The proxy is transparent to both endpoints; they each see a single +connection from/to the other endpoint. +.Xr pf 4 +chooses random initial sequence 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. +.Cm synproxy state +includes +.Cm modulate state . +.Pp +Rules with +.Cm synproxy state +will not work if +.Xr pf 4 +operates on a +.Xr bridge 4 . +Also they act on incoming SYN packets only. +.Pp +Example: +.Bd -literal -offset indent +pass in proto tcp from any to any port www synproxy state +.Ed +.Ss State Limiters +State limiters provide a mechanism to limit the number of states created, +or the rate of state creation, +by a set of rules. +State limiters are configured and loaded with the main ruleset, but +can be used by rules in any anchor. +The overall number of states is still subject to the limit set with +.Cm set limit states , +but the number of states created by a subset of rules can be provided +by a state limiter. +.Pp +A state limiter is configured with the following statement: +.Pp +.Bl -tag -width xxxx -compact +.It Cm state limiter Ar name +Each state limiter is identified by a unique name. +.El +.Pp +State limiters support the following configuration: +.Pp +.Bl -tag -width xxxx -compact +.It Cm id Ar number +A unique identifier between 1 and 255. +This configuration is required. +.It Cm limit Ar number +Specify the maximum number of states. +This configuration is required. +.It Cm rate Ar number Ns / Ns Ar seconds +Limit the rate at which states can be created over a time interval. +The connection rate is an approximation calculated as a moving +average. +.El +.Pp +Pass rules can specify a state limiter using the +.Cm state limiter Ar name +option. +If the number of states allowed has hit the limit, the pass rule +does not match and ruleset evaluation continues past it. +.Pp +An example use case for a state limiter is to restrict the number of +connections allowed to a service that is accessible via multiple +protocols, e.g. a DNS server that can be accessed by both TCP and +UDP on port 53, DNS-over-TLS on TCP port 853, and DNS-over-HTTPS +on TCP port 443 can be limited to 1000 concurrent connections: +.Pp +.Bd -literal -offset indent -compact +state limiter "dns-server" id 1 limit 1000 + +pass in proto { tcp udp } to port domain state limiter "dns-server" +pass in proto tcp to port { 853 443 } state limiter "dns-server" +.Ed +.Ss Source Limiters +Source limiters apply limits on the number of states, +or the rate of state creation, +for connections coming from a source address or network for a set +of rules. +Source limiters are configured and loaded with the main ruleset, but +can be used by rules in any anchor. +The overall number of states is still subject to the limit set with +.Cm set limit states , +but limits on states for a subset of source addresses and rules can +be provided with source limiters. +.Pp +Source address entries in source pools are created on demand, +and are used to account for the states created for each source +address or network. +A source limiter specifies the maximum number of source address +entries it will track, and can be configured to mask bits in network +prefixes to have source entries cover larger portions of the address +space if needed. +.Pp +A source limiter is configured with the following statement: +.Pp +.Bl -tag -width xxxx -compact +.It Cm source limiter Ar name +Each source limiter is uniquely identified by the specified name. +.El +.Pp +Source limiter support the following configuration: +.Pp +.Bl -tag -width xxxx -compact +.It Cm id Ar number +A unique identifier between 1 and 255. +This configuration is required. +.It Cm entries Ar number +Specify the maximum number of source address entries. +This configuration is required. +.It Cm limit Ar number +Specify the maximum number of states for each source address entry. +This configuration is required. +.It Cm rate Ar number Ns / Ns Ar seconds +Limit the rate at which states can be created by each source address +entry over a time interval. +The connection rate is an approximation calculated as a moving +average. +.It Cm inet mask Ar prefixlen +Mask IPv4 source addresses using the prefix length specified with +.Ar prefixlen +when creating an address entry. +The default IPv4 prefix length is 32 bits. +.It Cm inet6 mask Ar prefixlen +Mask IPv6 source addresses using the prefix length specified with +.Ar prefixlen +when creating an address entry. +The default IPv6 prefix length is 128 bits. +.It Cm table < Ns Ar table Ns > Cm above Ar hwm Op Cm below Ar lwm +Add the address to the specified +.Ar table +when the number of states goes above the +.Ar hwm +high water mark. +The address will be removed from the table when the number of states +drops below the +.Ar lwm +low water mark. +The default low water mark is 0. +.El +.Pp +Pass rules can specify a source limiter using the +.Cm source limiter Ar name +option. +.Pp +An example use for a source limiter is the mitigation of denial of +service caused by the exhaustion of firewall resources by network +or port scans from outside the network. +The states created by any one scanner from any one source address +can be limited to avoid impacting other sources. +Below, up to 10000 IPv4 hosts and IPv6 /64 networks from the external +network are each limited to a maximum of 1000 connections, and are +rate limited to creating 100 states over a 10 second interval: +.Pp +.Bd -literal -offset indent -compact +source limiter "internet" id 1 entries 10000 \e + limit 1000 rate 100/10 \e + inet6 mask 64 + +block in on egress +pass in on egress source limiter "internet" +.Ed +.Ss Stateful Tracking Options +A number of options related to stateful tracking can be applied on a +per-rule basis. +One of +.Cm keep state , +.Cm modulate state , +or +.Cm synproxy state +must be specified explicitly to apply these options to a rule. +.Pp +.Bl -tag -width xxxx -compact +.It Cm floating +States can match packets on any interfaces +(the opposite of +.Cm if-bound ) . +This is the default. +.It Cm if-bound +States are bound to an interface +(the opposite of +.Cm floating ) . +.It Cm max Ar number +Limits the number of concurrent states the rule may create. +When this limit is reached, further packets that would create +state are dropped until existing states time out. +.It Cm no-sync +Prevent state changes for states created by this rule from appearing on the +.Xr pfsync 4 +interface. +.It Cm pflow +States created by this rule are exported on the +.Xr pflow 4 +interface. +.It Cm sloppy +For TCP, uses a sloppy 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. +It cannot be used with +.Cm modulate state +or +.Cm synproxy state . +For ICMP, this option allows states to be created from replies, +not just requests. +.It Ar timeout seconds +Changes the +.Ar timeout +values used for states created by this rule. +For a list of all valid +.Ar timeout +names, see +.Sx OPTIONS +above. +.El +.Pp +Multiple options can be specified, separated by commas: +.Bd -literal -offset indent +pass in proto tcp from any to any \e + port www keep state \e + (max 100, source-track rule, max-src-nodes 75, \e + max-src-states 3, tcp.established 60, tcp.closing 5) +.Ed +.Pp +When the +.Cm source-track +keyword is specified, the number of states per source IP is tracked. +.Pp +.Bl -tag -width xxxx -compact +.It Cm source-track global +The number of states created by all rules that use this option is limited. +Each rule can specify different +.Cm max-src-nodes +and +.Cm max-src-states +options, however state entries created by any participating rule count towards +each individual rule's limits. +.It Cm source-track rule +The maximum number of states created by this rule is limited by the rule's +.Cm max-src-nodes +and +.Cm max-src-states +options. +Only state entries created by this particular rule count toward the rule's +limits. +.El +.Pp +The following limits can be set: +.Pp +.Bl -tag -width xxxx -compact +.It Cm max-src-nodes Ar number +Limits the maximum number of source addresses which can simultaneously +have state table entries. +.It Cm max-src-states Ar number +Limits the maximum number of simultaneous state entries that a single +source address can create with this rule. +.El +.Pp +For stateful TCP connections, limits on established connections (connections +which have completed the TCP 3-way handshake) can also be enforced +per source IP. +.Pp +.Bl -tag -width xxxx -compact +.It Cm max-src-conn Ar number +Limits the maximum number of simultaneous TCP connections which have +completed the 3-way handshake that a single host can make. +.It Cm max-src-conn-rate Ar number Ns / Ns Ar seconds +Limit the rate of new connections over a time interval. +The connection rate is an approximation calculated as a moving average. +.El +.Pp +When one of these limits is reached, further packets that would create +state are dropped until existing states time out. +.Pp +Because the 3-way handshake ensures that the source address is not being +spoofed, more aggressive action can be taken based on these limits. +With the +.Cm overload Pf < Ar table Ns > +state option, source IP addresses which hit either of the limits on +established connections will be added to the named +.Ar 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. +.Pp +The optional +.Cm flush +keyword kills all states created by the matching rule which originate +from the host which exceeds these limits. +The +.Cm global +modifier to the +.Cm flush +command kills all states originating from the +offending host, regardless of which rule created the state. +.Pp +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. +.Bd -literal -offset indent +block quick from <bad_hosts> +pass in on $ext_if proto tcp to $webserver port www keep state \e + (max-src-conn-rate 100/10, overload <bad_hosts> flush global) +.Ed +.Sh TRAFFIC NORMALISATION +Traffic normalisation is a broad umbrella term +for aspects of the packet filter which deal with +verifying packets, packet fragments, spoof traffic, +and other irregularities. +.Ss Scrub +Scrub involves sanitising packet content in such a way +that there are no ambiguities in packet interpretation on the receiving side. +It is invoked with the +.Cm scrub +option, added to regular rules. +.Pp +Parameters are specified enclosed in parentheses. +At least one of the following parameters must be specified: +.Bl -tag -width xxxx +.It Cm max-mss Ar number +Reduces the maximum segment size (MSS) +on TCP SYN packets to be no greater than +.Ar number . +This is sometimes required in scenarios where the two endpoints +of a TCP connection are not able to carry similar sized packets +and the resulting mismatch can lead to packet fragmentation or loss. +Note that setting the MSS this way can have undesirable effects, +such as interfering with the OS detection features of +.Xr pf 4 . +.It Cm min-ttl Ar number +Enforces a minimum TTL for matching IP packets. +.It Cm no-df +Clears the +.Dq dont-fragment +bit from a matching IPv4 packet. +Some operating systems have NFS implementations +which are known to generate fragmented packets with the +.Dq dont-fragment +bit set. +.Xr pf 4 +will drop such fragmented +.Dq dont-fragment +packets unless +.Cm no-df +is specified. +.Pp +Unfortunately some operating systems also generate their +.Dq dont-fragment +packets with a zero IP identification field. +Clearing the +.Dq dont-fragment +bit on packets with a zero IP ID may cause deleterious results if an +upstream router later fragments the packet. +Using +.Cm random-id +is recommended in combination with +.Cm no-df +to ensure unique IP identifiers. +.It Cm random-id +Replaces the IPv4 identification field with random values to compensate +for predictable values generated by many hosts. +This option only applies to packets that are not fragmented +after the optional fragment reassembly. +.It Cm reassemble tcp +Statefully normalises TCP connections. +.Cm reassemble tcp +performs the following normalisations: +.Bl -ohang +.It 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. +.Cm reassemble tcp +will raise the TTL of all packets back up to the highest value seen on +the connection. +.It 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 +guessable base time. +.Cm reassemble tcp +will cause +.Cm scrub +to modulate the TCP timestamps with a random number. +.It 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. +.Cm reassemble tcp +also makes sure the timestamp on the packet does not go forward more +than the RFC allows. +By doing this, +.Xr pf 4 +artificially extends the security of TCP sequence numbers by 10 to 18 +bits when the host uses appropriately randomized timestamps, since a +blind attacker would have to guess the timestamp as well. +.El +.El +.Pp +For example: +.Pp +.Dl match in all scrub (no-df random-id max-mss 1440) +.Ss 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 +.Xr pf 4 +to filter on things such as TCP ports or to perform NAT. +.Pp +One alternative is to filter individual fragments with filter rules. +If packet reassembly is turned off, 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 subprotocol header +fields are not available (TCP/UDP port numbers, ICMP code/type). +The +.Cm fragment +option can be used to restrict filter rules to apply only to +fragments, but not complete packets. +Filter rules without the +.Cm fragment +option still apply to fragments, if they only specify IP header fields. +For instance: +.Bd -literal -offset indent +pass in proto tcp from any to any port 80 +.Ed +.Pp +The rule above never applies to a fragment, +even if the fragment is part of a TCP packet with destination port 80, +because without reassembly this information +is not available for each fragment. +This also means that fragments cannot create new or match existing +state table entries, which makes stateful filtering and address +translation (NAT, redirection) for fragments impossible. +.Pp +In most cases, the benefits of reassembly outweigh the additional +memory cost, +so reassembly is on by default. +.Pp +The memory allocated for fragment caching can be limited using +.Xr 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. +.Pp +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. +.Ss Blocking Spoofed Traffic +Spoofing is the faking of IP addresses, +typically for malicious purposes. +The +.Ic 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. +.Pp +For example: +.Dl antispoof for lo0 +.Pp +Expands to: +.Bd -literal -offset indent -compact +block drop in on ! lo0 inet from 127.0.0.1/8 to any +block drop in on ! lo0 inet6 from ::1 to any +.Ed +.Pp +For non-loopback interfaces, there are additional rules to block incoming +packets with a source IP address identical to the interface's IP(s). +For example, assuming the interface wi0 had an IP address of 10.0.0.1 and a +netmask of 255.255.255.0: +.Pp +.Dl antispoof for wi0 inet +.Pp +Expands to: +.Bd -literal -offset indent -compact +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 +.Ed +.Pp +Caveat: Rules created by the +.Ic antispoof +directive interfere with packets sent over loopback interfaces +to local addresses. +One should pass these explicitly. +.Sh 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 system. +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. +.Pp +The fingerprints may be specified by operating system class, by +version, or by subtype/patchlevel. +The class of an operating system is typically the vendor or genre +and would be +.Ox +for the +.Xr pf 4 +firewall itself. +The version of the oldest available +.Ox +release on the main FTP site +would be 2.6 and the fingerprint would be written as: +.Pp +.Dl \&"OpenBSD 2.6\&" +.Pp +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 +.Ox , +the only subtype is for a fingerprint that was +normalised by the +.Cm no-df +scrub option and would be specified as: +.Pp +.Dl \&"OpenBSD 3.3 no-df\&" +.Pp +Fingerprints for most popular operating systems are provided by +.Xr pf.os 5 . +Once +.Xr pf 4 +is running, a complete list of known operating system fingerprints may +be listed by running: +.Pp +.Dl # pfctl -so +.Pp +Filter rules can enforce policy at any level of operating system specification +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. +.Pp +The +.Cm unknown +class can also be used as the fingerprint which will match packets for +which no operating system fingerprint is known. +.Pp +Examples: +.Bd -literal -offset indent +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" +.Ed +.Pp +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. +.Pp +Caveat: operating system fingerprints are occasionally wrong. +There are three problems: an attacker can trivially craft packets to +appear as any operating system; +an operating system patch could change the stack behavior and no fingerprints +will match it until the database is updated; +and multiple operating systems may have the same fingerprint. +.Sh EXAMPLES +In this example, +the external interface is +.Pa kue0 . +We use a macro for the interface name, so it can be changed easily. +All incoming traffic is "normalised", +and everything is blocked and logged by default. +.Bd -literal -offset 4n +ext_if = "kue0" +match in all scrub (no-df max-mss 1440) +block return log on $ext_if all +.Ed +.Pp +Here we specifically block packets we don't want: +anything coming from source we have no back routes for; +packets whose ingress interface does not match the one in +the route back to their source address; +anything that does not have our address (157.161.48.183) as source; +broadcasts (cable modem noise); +and anything from reserved address space or invalid addresses. +.Bd -literal -offset 4n +block in from no-route to any +block in from urpf-failed to any +block out log quick on $ext_if from ! 157.161.48.183 to any +block in quick on $ext_if from any to 255.255.255.255 +block in log quick on $ext_if from { 10.0.0.0/8, 172.16.0.0/12, \e + 192.168.0.0/16, 255.255.255.255/32 } to any +.Ed +.Pp +For ICMP, +pass out/in ping queries. +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. +.Bd -literal -offset 4n +pass on $ext_if inet proto icmp all icmp-type 8 code 0 +.Ed +.Pp +For UDP, +pass out all UDP connections. +DNS connections are passed in. +.Bd -literal -offset 4n +pass out on $ext_if proto udp all +pass in on $ext_if proto udp from any to any port domain +.Ed +.Pp +For TCP, +pass out all TCP connections and modulate state. +SSH, SMTP, DNS, and IDENT connections are passed in. +We do not allow Windows 9x SMTP connections since they are typically +a viral worm. +.Bd -literal -offset 4n +pass out on $ext_if proto tcp all modulate state +pass in on $ext_if proto tcp from any to any \e + port { ssh, smtp, domain, auth } +block in on $ext_if proto tcp from any \e + os { "Windows 95", "Windows 98" } to any port smtp +.Ed +.Pp +Here we 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. +.Bd -literal -offset 4n +pass quick on gif0 inet6 +pass quick on $ext_if proto ipv6 +.Ed +.Pp +This example illustrates packet tagging. +There are three interfaces: $int_if, $ext_if, and $wifi_if (wireless). +NAT is being done on $ext_if for all outgoing packets. +Packets in on $int_if are tagged and passed out on $ext_if. +All other outgoing packets +(i.e. packets from the wireless network) +are only permitted to access port 80. +.Bd -literal -offset 4n +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 +.Ed +.Pp +In this example, +we tag incoming packets as they are redirected to +.Xr spamd 8 . +The tag is used to pass those packets through the packet filter. +.Bd -literal -offset 4n +match in on $ext_if inet proto tcp from <spammers> to port smtp \e + tag SPAMD rdr-to 127.0.0.1 port spamd + +block in on $ext_if +pass in on $ext_if inet proto tcp tagged SPAMD +.Ed +.Pp +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). +.Bd -literal -offset 4n +match in on $ext_if proto tcp from any to any port 80 \e + rdr-to 127.0.0.1 port 8080 +.Ed +.Pp +If a +.Ic pass +rule is used with the +.Cm quick +modifier, packets matching the translation rule are passed without +inspecting subsequent filter rules. +.Bd -literal -offset 4n +pass in quick on $ext_if proto tcp from any to any port 80 \e + rdr-to 127.0.0.1 port 8080 +.Ed +.Pp +In the example below, vlan12 is configured as 192.168.168.1; +the machine translates all packets coming from 192.168.168.0/24 to 204.92.77.111 +when they are going out any interface except vlan12. +This has the net effect of making traffic from the 192.168.168.0/24 +network appear as though it is the Internet routable address +204.92.77.111 to nodes behind any interface on the router except +for the nodes on vlan12. +Thus, 192.168.168.1 can talk to the 192.168.168.0/24 nodes. +.Bd -literal -offset 4n +match out on ! vlan12 from 192.168.168.0/24 to any nat-to 204.92.77.111 +.Ed +.Pp +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 last rule excludes protocol AH from being translated. +.Bd -literal -offset 4n +pass out on $ext_if from 144.19.74.0/24 nat-to 204.92.77.100 +pass out on $ext_if proto ah from 144.19.74.0/24 +.Ed +.Pp +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. +.Bd -literal -offset 4n +pass in on $int_if proto { tcp, udp } from any to any port 80 \e + rdr-to 127.0.0.1 port 80 +pass in on $int_if proto { tcp, udp } from any to $server port 80 +pass in on $int_if proto { tcp, udp } from $sysadmins to any port 80 +.Ed +.Pp +This example maps 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. +.Bd -literal -offset 4n +match out on $ext_if inet proto udp from any port isakmp to any \e + nat-to ($ext_if) port 500 +.Ed +.Pp +One more example uses +.Cm rdr-to +to redirect a TCP and UDP port to an internal machine. +.Bd -literal -offset 4n +match in on $ext_if inet proto tcp from any to ($ext_if) port 8080 \e + rdr-to 10.1.2.151 port 22 +match in on $ext_if inet proto udp from any to ($ext_if) port 8080 \e + rdr-to 10.1.2.151 port 53 +.Ed +.Pp +In this example, a NAT gateway is set up to translate internal addresses +using a pool of public addresses (192.0.2.16/28). +A given source address is always translated to the same pool address by +using the +.Cm source-hash +keyword. +The gateway also translates incoming web server connections +to a group of web servers on the internal network. +.Bd -literal -offset 4n +match out on $ext_if inet from any to any nat-to 192.0.2.16/28 \e + source-hash +match in on $ext_if proto tcp from any to any port 80 \e + rdr-to { 10.1.2.155 weight 2, 10.1.2.160 weight 1, \e + 10.1.2.161 weight 8 } round-robin +.Ed +.Pp +The bidirectional address translation example uses a single +.Cm binat-to +rule that expands to a +.Cm nat-to +and an +.Cm rdr-to +rule. +.Bd -literal -offset 4n +pass on $ext_if from 10.1.2.120 to any binat-to 192.0.2.17 +.Ed +.Pp +The previous example is identical to the following set of rules: +.Bd -literal -offset 4n +pass out on $ext_if inet from 10.1.2.120 to any \e + nat-to 192.0.2.17 static-port +pass in on $ext_if inet from any to 192.0.2.17 rdr-to 10.1.2.120 +.Ed +.Pp +In the example below, a router handling both address families +translates an internal IPv4 subnet to IPv6 using the well-known +64:ff9b::/96 prefix: +.Bd -literal -offset 4n +pass in on $v4_if inet af-to inet6 from ($v6_if) to 64:ff9b::/96 +.Ed +.Pp +Paired with the example above, the example below can be used on +another router handling both address families to translate back +to IPv4: +.Bd -literal -offset 4n +pass in on $v6_if inet6 to 64:ff9b::/96 af-to inet from ($v4_if) +.Ed +.Sh GRAMMAR +Syntax for +.Nm +in BNF: +.Bd -literal +line = ( option | pf-rule | + antispoof-rule | queue-rule | 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 ] + [ "fingerprints" filename ] | + [ "skip on" ifspec ] | + [ "debug" ( "emerg" | "alert" | "crit" | "err" | + "warning" | "notice" | "info" | "debug" ) ] | + [ "reassemble" ( "yes" | "no" ) [ "no-df" ] ] ) + +pf-rule = action [ ( "in" | "out" ) ] + [ "log" [ "(" logopts ")"] ] [ "quick" ] + [ "on" ( ifspec | "rdomain" number ) ] [ af ] + [ protospec ] [ hosts ] [ filteropts ] + +logopts = logopt [ [ "," ] logopts ] +logopt = "all" | "matches" | "user" | "to" interface-name + +filteropts = filteropt [ [ "," ] filteropts ] +filteropt = user | group | flags | icmp-type | icmp6-type | + "tos" tos | + ( "no" | "keep" | "modulate" | "synproxy" ) "state" + [ "(" state-opts ")" ] | "scrub" "(" scrubopts ")" | + "fragment" | "allow-opts" | "once" | + "divert-packet" "port" port | "divert-reply" | + "divert-to" host "port" port | + "label" string | "tag" string | [ "!" ] "tagged" string | + "max-pkt-rate" number "/" seconds | + "set delay" number | + "set prio" ( number | "(" number [ [ "," ] number ] ")" ) | + "set queue" ( string | "(" string [ [ "," ] string ] ")" ) | + "rtable" number | "probability" number"%" | + "state limiter" name | + "state limiter" name "(" limiter-opts ")" | + "source limiter" name | + "source limiter" name "(" limiter-opts ")" | "prio" number | + "af-to" af "from" ( redirhost | "{" redirhost-list "}" ) + [ "to" ( redirhost | "{" redirhost-list "}" ) ] | + "binat-to" ( redirhost | "{" redirhost-list "}" ) + [ portspec ] [ pooltype ] | + "rdr-to" ( redirhost | "{" redirhost-list "}" ) + [ portspec ] [ pooltype ] | + "nat-to" ( redirhost | "{" redirhost-list "}" ) + [ portspec ] [ pooltype ] [ "static-port" ] | + [ route ] | [ "set tos" tos ] | + [ [ "!" ] "received-on" ( interface-name | interface-group ) ] + +scrubopts = scrubopt [ [ "," ] scrubopts ] +scrubopt = "no-df" | "min-ttl" number | "max-mss" number | + "reassemble tcp" | "random-id" + +antispoof-rule = "antispoof" [ "log" ] [ "quick" ] + "for" ifspec [ af ] [ "label" string ] + +table-rule = "table" "<" string ">" [ tableopts ] +tableopts = tableopt [ tableopts ] +tableopt = "persist" | "const" | "counters" | + "file" string | "{" [ tableaddrs ] "}" +tableaddrs = tableaddr-spec [ [ "," ] tableaddrs ] +tableaddr-spec = [ "!" ] tableaddr [ "/" mask-bits ] +tableaddr = hostname | ifspec | "self" | + ipv4-dotted-quad | ipv6-coloned-hex + +queue-rule = "queue" string [ "on" interface-name ] queueopts-list + +anchor-rule = "anchor" [ string ] [ ( "in" | "out" ) ] [ "on" ifspec ] + [ af ] [ protospec ] [ hosts ] [ filteropt-list ] [ "{" ] + +anchor-close = "}" + +load-anchor = "load anchor" string "from" filename + +queueopts-list = queueopts-list queueopts | queueopts +queueopts = ([ "bandwidth" bandwidth ] | [ "min" bandwidth ] | + [ "max" bandwidth ] | [ "parent" string ] | + [ "default" ]) | + ([ "flows" number ] | [ "quantum" number ]) | + [ "qlimit" number ] + +bandwidth = bandwidth-spec [ "burst" bandwidth-spec "for" number "ms" ] +bandwidth-spec = number ( "" | "K" | "M" | "G" ) + +action = "pass" | "match" | "block" [ return ] +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" ) + ( redirhost | "{" redirhost-list "}" ) +af = "inet" | "inet6" + +protospec = "proto" ( proto-name | proto-number | + "{" proto-list "}" ) +proto-list = ( proto-name | proto-number ) [ [ "," ] proto-list ] + +hosts = "all" | + "from" ( "any" | "no-route" | "urpf-failed" | "self" | + host | "{" host-list "}" | "route" string ) [ port ] + [ os ] + "to" ( "any" | "no-route" | "self" | host | + "{" host-list "}" | "route" string ) [ port ] + +ipspec = "any" | host | "{" host-list "}" +host = [ "!" ] ( address [ "weight" number ] | + address [ "/" mask-bits ] [ "weight" number ] | + "<" string ">" ) +redirhost = 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 ] + +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" | + "pflow" | "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" [ "global" ] ] | + "if-bound" | "floating" ) + +timeout-list = timeout [ [ "," ] timeout-list ] +timeout = ( "tcp.first" | "tcp.opening" | "tcp.established" | + "tcp.closing" | "tcp.finwait" | "tcp.closed" | "tcp.tsdiff" | + "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" | "tables" | + "table-entries" ) number + +pooltype = ( "bitmask" | "least-states" | + "random" | "round-robin" | + "source-hash" [ ( hex-key | string-key ) ] ) + [ "sticky-address" ] + +limiter-opts = "block" | "no-match" + +include = "include" filename +.Ed +.Sh FILES +.Bl -tag -width /etc/examples/pf.conf -compact +.It Pa /etc/hosts +Host name database. +.It Pa /etc/pf.conf +Default location of the ruleset file. +.It Pa /etc/examples/pf.conf +Example ruleset file. +.It Pa /etc/pf.os +Default location of OS fingerprints. +.It Pa /etc/protocols +Protocol name database. +.It Pa /etc/services +Service name database. +.El +.Sh SEE ALSO +.Xr pf 4 , +.Xr pflow 4 , +.Xr pfsync 4 , +.Xr pf.os 5 , +.Xr pfctl 8 , +.Xr pflogd 8 +.Sh HISTORY +The +.Nm +file format first appeared in +.Ox 3.0 . |
