diff options
Diffstat (limited to 'static/freebsd/man5/pf.conf.5 3.html')
| -rw-r--r-- | static/freebsd/man5/pf.conf.5 3.html | 3028 |
1 files changed, 3028 insertions, 0 deletions
diff --git a/static/freebsd/man5/pf.conf.5 3.html b/static/freebsd/man5/pf.conf.5 3.html new file mode 100644 index 00000000..dfa40f42 --- /dev/null +++ b/static/freebsd/man5/pf.conf.5 3.html @@ -0,0 +1,3028 @@ +<table class="head"> + <tr> + <td class="head-ltitle">PF.CONF(5)</td> + <td class="head-vol">File Formats Manual</td> + <td class="head-rtitle">PF.CONF(5)</td> + </tr> +</table> +<div class="manual-text"> +<section class="Sh"> +<h1 class="Sh" id="NAME"><a class="permalink" href="#NAME">NAME</a></h1> +<p class="Pp"><code class="Nm">pf.conf</code> — <span class="Nd">packet + filter configuration file</span></p> +</section> +<section class="Sh"> +<h1 class="Sh" id="DESCRIPTION"><a class="permalink" href="#DESCRIPTION">DESCRIPTION</a></h1> +<p class="Pp">The <a class="Xr">pf(4)</a> packet filter modifies, drops or + passes packets according to rules or definitions specified in + <code class="Nm">pf.conf</code>.</p> +</section> +<section class="Sh"> +<h1 class="Sh" id="STATEMENT_ORDER"><a class="permalink" href="#STATEMENT_ORDER">STATEMENT + ORDER</a></h1> +<p class="Pp">There are eight types of statements in + <code class="Nm">pf.conf</code>:</p> +<dl class="Bl-tag"> + <dt id="Macros"><a class="permalink" href="#Macros"><code class="Cm">Macros</code></a></dt> + <dd>User-defined variables may be defined and used later, simplifying the + configuration file. Macros must be defined before they are referenced in + <code class="Nm">pf.conf</code>.</dd> + <dt id="Tables"><a class="permalink" href="#Tables"><code class="Cm">Tables</code></a></dt> + <dd>Tables provide a mechanism for increasing the performance and flexibility + of rules with large numbers of source or destination addresses.</dd> + <dt id="Options"><a class="permalink" href="#Options"><code class="Cm">Options</code></a></dt> + <dd>Options tune the behaviour of the packet filtering engine.</dd> + <dt id="Ethernet"><a class="permalink" href="#Ethernet"><code class="Cm">Ethernet + Filtering</code></a></dt> + <dd>Ethernet filtering provides rule-based blocking or passing of Ethernet + packets.</dd> + <dt id="Traffic"><a class="permalink" href="#Traffic"><code class="Cm">Traffic + Normalization</code></a> <code class="Li">(e.g.</code> + <a class="permalink" href="#scrub"><i class="Em" id="scrub">scrub</i></a>)</dt> + <dd>Traffic normalization protects internal machines against inconsistencies + in Internet protocols and implementations.</dd> + <dt id="Queueing"><a class="permalink" href="#Queueing"><code class="Cm">Queueing</code></a></dt> + <dd>Queueing provides rule-based bandwidth control.</dd> + <dt id="Translation"><a class="permalink" href="#Translation"><code class="Cm">Translation</code></a> + <code class="Li">(Various forms of NAT)</code></dt> + <dd>Translation rules specify how addresses are to be mapped or redirected to + other addresses.</dd> + <dt id="Packet"><a class="permalink" href="#Packet"><code class="Cm">Packet + Filtering</code></a></dt> + <dd>Packet filtering provides rule-based blocking or passing of packets.</dd> +</dl> +<p class="Pp">With the exception of <code class="Cm">macros</code> and + <code class="Cm">tables</code>, the types of statements should be grouped + and appear in <code class="Nm">pf.conf</code> in the order shown above, as + this matches the operation of the underlying packet filtering engine. By + default <a class="Xr">pfctl(8)</a> enforces this order (see + <var class="Ar">set require-order</var> below).</p> +<p class="Pp">Comments can be put anywhere in the file using a hash mark + (‘#’), and extend to the end of the current line.</p> +<p class="Pp">Additional configuration files can be included with the + <code class="Ic">include</code> keyword, for example:</p> +<div class="Bd Pp Bd-indent Li"> +<pre>include "/etc/pf/sub.filter.conf"</pre> +</div> +</section> +<section class="Sh"> +<h1 class="Sh" id="MACROS"><a class="permalink" href="#MACROS">MACROS</a></h1> +<p class="Pp">A macro is defined with a command of the form + <var class="Ar">name</var>=<var class="Ar">value</var>. The macro + <var class="Ar">name</var> can contain letters, digits, and underscores and + cannot be a reserved word (for example, <var class="Ar">pass</var>, + <var class="Ar">in</var>, or <var class="Ar">out</var>). Within unquoted + arguments, the string $<var class="Ar">name</var> is later expanded to + <var class="Ar">value</var>. Ranges of network addresses used in macros that + will be expanded in lists later on must be quoted with additional simple + quotes.</p> +<p class="Pp">For example,</p> +<div class="Bd Pp Bd-indent Li"> +<pre>ext_if = "kue0" +all_ifs = "{" $ext_if lo0 "}" +pass out on $ext_if from any to any +pass in on $ext_if proto tcp from any to any port 25 + +usr_lan_range = "'192.0.2.0/24'" +srv_lan_range = "'198.51.100.0 - 198.51.100.255'" +nat_ranges = "{" $usr_lan_range $srv_lan_range "}" +nat on $ext_if from $nat_ranges to any -> ($ext_if)</pre> +</div> +</section> +<section class="Sh"> +<h1 class="Sh" id="TABLES"><a class="permalink" href="#TABLES">TABLES</a></h1> +<p class="Pp">Tables are named structures which can hold a collection of + addresses and networks. Lookups against tables in <a class="Xr">pf(4)</a> + 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).</p> +<p class="Pp">Tables can be used as the source or destination of filter rules, + <var class="Ar">scrub</var> rules or translation rules such as + <var class="Ar">nat</var> or <var class="Ar">rdr</var> (see below for + details on the various rule types). Tables can also be used for the redirect + address of <var class="Ar">nat</var> and <var class="Ar">rdr</var> and in + the routing options of filter rules, but not for + <var class="Ar">bitmask</var> pools.</p> +<p class="Pp">Tables can be defined with any of the following + <a class="Xr">pfctl(8)</a> mechanisms. As with macros, reserved words may + not be used as table names.</p> +<dl class="Bl-tag"> + <dt><var class="Ar">manually</var></dt> + <dd>Persistent tables can be manually created with the + <var class="Ar">add</var> or <var class="Ar">replace</var> option of + <a class="Xr">pfctl(8)</a>, before or after the ruleset has been + loaded.</dd> + <dt><span class="Pa">pf.conf</span></dt> + <dd>Table definitions can be placed directly in this file, and loaded at the + same time as other rules are loaded, atomically. Table definitions inside + <code class="Nm">pf.conf</code> use the <var class="Ar">table</var> + 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 <code class="Nm">pf.conf</code> is + loaded. A table initialized with the empty list, <code class="Li">{ + }</code>, will be cleared on load.</dd> +</dl> +<p class="Pp">Tables may be defined with the following attributes:</p> +<dl class="Bl-tag"> + <dt><var class="Ar">persist</var></dt> + <dd>The <var class="Ar">persist</var> 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.</dd> + <dt><var class="Ar">const</var></dt> + <dd>The <var class="Ar">const</var> flag prevents the user from altering the + contents of the table once it has been created. Without that flag, + <a class="Xr">pfctl(8)</a> can be used to add or remove addresses from the + table at any time, even when running with <a class="Xr">securelevel(7)</a> + = 2.</dd> + <dt><var class="Ar">counters</var></dt> + <dd>The <var class="Ar">counters</var> flag enables per-address packet and + byte counters which can be displayed with <a class="Xr">pfctl(8)</a>. Note + that this feature carries significant memory overhead for large + tables.</dd> +</dl> +<p class="Pp">For example,</p> +<div class="Bd Pp Bd-indent Li"> +<pre>table <private> const { 10/8, 172.16/12, 192.168/16 } +table <badhosts> persist +block on fxp0 from { <private>, <badhosts> } to any</pre> +</div> +<p class="Pp">creates a table called private, to hold RFC 1918 private network + blocks, and a table called badhosts, which is initially empty. A filter rule + is set up to block all traffic coming from addresses listed in either table. + The private table cannot have its contents changed and the badhosts table + will exist even when no active filter rules reference it. Addresses may + later be added to the badhosts table, so that traffic from these hosts can + be blocked by using</p> +<div class="Bd Pp Bd-indent Li"> +<pre># pfctl -t badhosts -Tadd 204.92.77.111</pre> +</div> +<p class="Pp">A table can also be initialized with an address list specified in + one or more external files, using the following syntax:</p> +<div class="Bd Pp Bd-indent Li"> +<pre>table <spam> persist file "/etc/spammers" file "/etc/openrelays" +block on fxp0 from <spam> to any</pre> +</div> +<p class="Pp" id="all">The files <span class="Pa">/etc/spammers</span> and + <span class="Pa">/etc/openrelays</span> list IP addresses, one per line. Any + lines beginning with a # are treated as comments and ignored. In addition to + being specified by IP address, hosts may also be specified by their + hostname. When the resolver is called to add a hostname to a table, + <a class="permalink" href="#all"><i class="Em">all</i></a> 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 + <a class="permalink" href="#self"><i class="Em" id="self">self</i></a> + keyword, in which case all addresses assigned to the interface(s) will be + added to the table.</p> +</section> +<section class="Sh"> +<h1 class="Sh" id="OPTIONS"><a class="permalink" href="#OPTIONS">OPTIONS</a></h1> +<p class="Pp"><a class="Xr">pf(4)</a> may be tuned for various situations using + the <var class="Ar">set</var> command.</p> +<dl class="Bl-tag"> + <dt><var class="Ar">set timeout</var></dt> + <dd> + <p class="Pp"></p> + <dl class="Bl-tag Bl-compact"> + <dt><var class="Ar">interval</var></dt> + <dd>Interval between purging expired states and fragments.</dd> + <dt><var class="Ar">frag</var></dt> + <dd>Seconds before an unassembled fragment is expired.</dd> + <dt><var class="Ar">src.track</var></dt> + <dd>Length of time to retain a source tracking entry after the last state + expires.</dd> + </dl> + <p class="Pp">When a packet matches a stateful connection, the seconds to + live for the connection will be updated to that of the + <var class="Ar">proto.modifier</var> 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 <code class="Cm">set optimization</code> (see above).</p> + <p class="Pp"></p> + <dl class="Bl-tag Bl-compact"> + <dt><var class="Ar">tcp.first</var></dt> + <dd>The state after the first packet.</dd> + <dt><var class="Ar">tcp.opening</var></dt> + <dd>The state after the second packet but before both endpoints have + acknowledged the connection.</dd> + <dt><var class="Ar">tcp.tsdiff</var></dt> + <dd>Maximum allowed time difference between RFC 1323 compliant packet + timestamps. 30 seconds by default.</dd> + <dt><var class="Ar">tcp.established</var></dt> + <dd>The fully established state.</dd> + <dt><var class="Ar">tcp.closing</var></dt> + <dd>The state after the first FIN has been sent.</dd> + <dt><var class="Ar">tcp.finwait</var></dt> + <dd>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 + <var class="Ar">tcp.finwait</var> (and possibly + <var class="Ar">tcp.closing</var>) can prevent blocking of such + packets.</dd> + <dt><var class="Ar">tcp.closed</var></dt> + <dd>The state after one endpoint sends an RST.</dd> + </dl> + <p class="Pp">SCTP timeout are handled similar to TCP, but with its own set + of states:</p> + <p class="Pp"></p> + <dl class="Bl-tag Bl-compact"> + <dt><var class="Ar">sctp.first</var></dt> + <dd>The state after the first packet.</dd> + <dt><var class="Ar">sctp.opening</var></dt> + <dd>The state before the destination host ever sends a packet.</dd> + <dt><var class="Ar">sctp.established</var></dt> + <dd>The fully established state.</dd> + <dt><var class="Ar">sctp.closing</var></dt> + <dd>The state after the first SHUTDOWN chunk has been sent.</dd> + <dt><var class="Ar">sctp.closed</var></dt> + <dd>The state after SHUTDOWN_ACK has been exchanged and the connection is + closed.</dd> + </dl> + <p class="Pp">ICMP and UDP are handled in a fashion similar to TCP, but with + a much more limited set of states:</p> + <p class="Pp"></p> + <dl class="Bl-tag Bl-compact"> + <dt><var class="Ar">udp.first</var></dt> + <dd>The state after the first packet.</dd> + <dt><var class="Ar">udp.single</var></dt> + <dd>The state if the source host sends more than one packet but the + destination host has never sent one back.</dd> + <dt><var class="Ar">udp.multiple</var></dt> + <dd>The state if both hosts have sent packets.</dd> + <dt><var class="Ar">icmp.first</var></dt> + <dd>The state after the first packet.</dd> + <dt><var class="Ar">icmp.error</var></dt> + <dd>The state after an ICMP error came back in response to an ICMP + packet.</dd> + </dl> + <p class="Pp">Other protocols are handled similarly to UDP:</p> + <p class="Pp"></p> + <dl class="Bl-tag Bl-compact"> + <dt><var class="Ar">other.first</var></dt> + <dd style="width: auto;"> </dd> + <dt><var class="Ar">other.single</var></dt> + <dd style="width: auto;"> </dd> + <dt><var class="Ar">other.multiple</var></dt> + <dd style="width: auto;"> </dd> + </dl> + <p class="Pp">Timeout values can be reduced adaptively as the number of + state table entries grows.</p> + <p class="Pp"></p> + <dl class="Bl-tag Bl-compact"> + <dt><var class="Ar">adaptive.start</var></dt> + <dd>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).</dd> + <dt><var class="Ar">adaptive.end</var></dt> + <dd>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).</dd> + </dl> + <p class="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.</p> + <p class="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.</p> + <p class="Pp">For example:</p> + <div class="Bd Pp Bd-indent Li"> + <pre>set timeout tcp.first 120 +set timeout tcp.established 86400 +set timeout { adaptive.start 60000, adaptive.end 120000 } +set limit states 100000</pre> + </div> + <p class="Pp">With 90000 state table entries, the timeout values are scaled + to 50% (tcp.first 60, tcp.established 43200).</p> + </dd> + <dt><var class="Ar">set loginterface</var></dt> + <dd>Enable collection of packet and byte count statistics for the given + interface or interface group. These statistics can be viewed using + <div class="Bd Pp Bd-indent Li"> + <pre># pfctl -s info</pre> + </div> + <p class="Pp">In this example <a class="Xr">pf(4)</a> collects statistics on + the interface named dc0:</p> + <div class="Bd Pp Bd-indent Li"> + <pre>set loginterface dc0</pre> + </div> + <p class="Pp">One can disable the loginterface using:</p> + <div class="Bd Pp Bd-indent Li"> + <pre>set loginterface none</pre> + </div> + </dd> + <dt><var class="Ar">set limit</var></dt> + <dd>Sets hard limits on the memory pools used by the packet filter. See + <a class="Xr">zone(9)</a> for an explanation of memory pools. + <p class="Pp">Limits can be set on the following:</p> + <dl class="Bl-tag"> + <dt id="states"><a class="permalink" href="#states"><code class="Cm">states</code></a></dt> + <dd>Set the maximum number of entries in the memory pool used by state + table entries (those generated by <var class="Ar">pass</var> rules + which do not specify <code class="Cm">no state</code>). The default is + 100000.</dd> + <dt id="src-nodes"><a class="permalink" href="#src-nodes"><code class="Cm">src-nodes</code></a></dt> + <dd>Set the maximum number of entries in the memory pool used for tracking + source IP addresses (generated by the + <var class="Ar">sticky-address</var> and + <var class="Ar">src.track</var> options). The default is 10000.</dd> + <dt id="table-entries"><a class="permalink" href="#table-entries"><code class="Cm">table-entries</code></a></dt> + <dd>Set the number of addresses that can be stored in tables. The default + is 200000.</dd> + <dt id="anchors"><a class="permalink" href="#anchors"><code class="Cm">anchors</code></a></dt> + <dd>Set the number of anchors that can exist. The default is 512.</dd> + <dt id="eth-anchors"><a class="permalink" href="#eth-anchors"><code class="Cm">eth-anchors</code></a></dt> + <dd>Set the number of anchors that can exist. The default is 512.</dd> + </dl> + <p class="Pp">Multiple limits can be combined on a single line:</p> + <div class="Bd Pp Bd-indent Li"> + <pre>set limit { states 20000, frags 2000, src-nodes 2000 }</pre> + </div> + </dd> + <dt><var class="Ar">set ruleset-optimization</var></dt> + <dd> + <dl class="Bl-tag Bl-compact"> + <dt><var class="Ar">none</var></dt> + <dd>Disable the ruleset optimizer.</dd> + <dt><var class="Ar">basic</var></dt> + <dd>Enable basic ruleset optimization. This is the default behaviour. + Basic ruleset optimization does four things to improve the performance + of ruleset evaluations: + <p class="Pp"></p> + <ol class="Bl-enum Bl-compact"> + <li>remove duplicate rules</li> + <li>remove rules that are a subset of another rule</li> + <li>combine multiple rules into a table when advantageous</li> + <li>re-order the rules to improve evaluation performance</li> + </ol> + <p class="Pp"></p> + </dd> + <dt><var class="Ar">profile</var></dt> + <dd>Uses the currently loaded ruleset as a feedback profile to tailor the + ordering of quick rules to actual network traffic.</dd> + </dl> + <p class="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.</p> + <p class="Pp">Optimization can also be set as a command-line argument to + <a class="Xr">pfctl(8)</a>, overriding the settings in + <code class="Nm">pf.conf</code>.</p> + </dd> + <dt><var class="Ar">set optimization</var></dt> + <dd>Optimize state timeouts for one of the following network environments: + <p class="Pp"></p> + <dl class="Bl-tag Bl-compact"> + <dt><var class="Ar">normal</var></dt> + <dd>A normal network environment. Suitable for almost all networks.</dd> + <dt><var class="Ar">high-latency</var></dt> + <dd>A high-latency environment (such as a satellite connection).</dd> + <dt><var class="Ar">satellite</var></dt> + <dd>Alias for <var class="Ar">high-latency</var>.</dd> + <dt><var class="Ar">aggressive</var></dt> + <dd>Aggressively expire connections. This can greatly reduce the memory + usage of the firewall at the cost of dropping idle connections + early.</dd> + <dt><var class="Ar">conservative</var></dt> + <dd>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.</dd> + </dl> + <p class="Pp">For example:</p> + <div class="Bd Pp Bd-indent Li"> + <pre>set optimization aggressive</pre> + </div> + </dd> + <dt><var class="Ar">set reassemble yes</var> | <var class="Ar">no</var> + [<code class="Cm">no-df</code>]</dt> + <dd>The <code class="Cm">reassemble</code> option is used to enable or disable + the reassembly of fragmented packets, and can be set to + <code class="Cm">yes</code> or <code class="Cm">no</code>. If + <code class="Cm">no-df</code> is also specified, fragments with the + “dont-fragment” bit set are reassembled too, instead of + being dropped; the reassembled packet will have the + “dont-fragment” bit cleared. The default value is + <code class="Cm">no</code>. + <p class="Pp">This option is ignored if there are pre-FreeBSD 14 + <code class="Cm">scrub</code> rules present.</p> + </dd> + <dt><var class="Ar">set block-policy</var></dt> + <dd>The <var class="Ar">block-policy</var> option sets the default behaviour + for the packet <var class="Ar">block</var> action: + <p class="Pp"></p> + <dl class="Bl-tag Bl-compact"> + <dt><var class="Ar">drop</var></dt> + <dd>Packet is silently dropped.</dd> + <dt><var class="Ar">return</var></dt> + <dd>A TCP RST is returned for blocked TCP packets, an SCTP ABORT chunk is + returned for blocked SCTP packets, an ICMP UNREACHABLE is returned for + blocked UDP packets, and all other packets are silently dropped.</dd> + </dl> + <p class="Pp">The default value is <code class="Cm">drop</code>.</p> + <p class="Pp">For example:</p> + <div class="Bd Pp Bd-indent Li"> + <pre>set block-policy return</pre> + </div> + </dd> + <dt><var class="Ar">set fail-policy</var></dt> + <dd>The <var class="Ar">fail-policy</var> option sets the behaviour of rules + which should pass a packet but were unable to do so. This might happen + when a nat or route-to rule uses an empty table as list of targets or if a + rule fails to create state or source node. The following + <var class="Ar">block</var> actions are possible: + <p class="Pp"></p> + <dl class="Bl-tag Bl-compact"> + <dt><var class="Ar">drop</var></dt> + <dd>Incoming packet is silently dropped.</dd> + <dt><var class="Ar">return</var></dt> + <dd>Incoming packet is dropped and TCP RST is returned for TCP packets, an + SCTP ABORT chunk is returned for blocked SCTP packets, an ICMP + UNREACHABLE is returned for UDP packets, and no response is sent for + other packets.</dd> + </dl> + <p class="Pp">For example:</p> + <div class="Bd Pp Bd-indent Li"> + <pre>set fail-policy return</pre> + </div> + </dd> + <dt><var class="Ar">set state-policy</var></dt> + <dd>The <var class="Ar">state-policy</var> option sets the default behaviour + for states: + <p class="Pp"></p> + <dl class="Bl-tag Bl-compact"> + <dt><var class="Ar">if-bound</var></dt> + <dd>States are bound to interface.</dd> + <dt><var class="Ar">floating</var></dt> + <dd>States can match packets on any interfaces (the default).</dd> + </dl> + <p class="Pp">For example:</p> + <div class="Bd Pp Bd-indent Li"> + <pre>set state-policy if-bound</pre> + </div> + </dd> + <dt><var class="Ar">set syncookies never</var> | <var class="Ar">always</var> + | <var class="Ar">adaptive</var></dt> + <dd>When <code class="Cm">syncookies</code> are active, pf will answer each + incoming TCP SYN with a syncookie SYNACK, without allocating any + resources. Upon reception of the client's ACK in response to the syncookie + SYNACK, pf will evaluate the ruleset and create state if the ruleset + permits it, 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 would run the state table + against its limits otherwise. Due to the blind answers to every incoming + SYN syncookies share the caveats of synproxy, namely seemingly accepting + connections that will be dropped later on. + <p class="Pp"></p> + <dl class="Bl-tag Bl-compact"> + <dt id="never"><a class="permalink" href="#never"><code class="Cm">never</code></a></dt> + <dd>pf will never send syncookie SYNACKs (the default).</dd> + <dt id="always"><a class="permalink" href="#always"><code class="Cm">always</code></a></dt> + <dd>pf will always send syncookie SYNACKs.</dd> + <dt id="adaptive"><a class="permalink" href="#adaptive"><code class="Cm">adaptive</code></a></dt> + <dd>pf will enable syncookie mode when a given percentage of the state + table is used up by half-open TCP connections, as in, those that saw + the initial SYN but didn't finish the three way handshake. The + thresholds for entering and leaving syncookie mode can be specified + using + <div class="Bd Pp Bd-indent Li"> + <pre>set syncookies adaptive (start 25%, end 12%)</pre> + </div> + </dd> + </dl> + </dd> + <dt><var class="Ar">set state-defaults</var></dt> + <dd>The <var class="Ar">state-defaults</var> option sets the state options for + states created from rules without an explicit <var class="Ar">keep + state</var>. For example: + <div class="Bd Pp Bd-indent Li"> + <pre>set state-defaults no-sync</pre> + </div> + </dd> + <dt><var class="Ar">set hostid</var></dt> + <dd>The 32-bit <var class="Ar">hostid</var> identifies this firewall's state + table entries to other firewalls in a <a class="Xr">pfsync(4)</a> 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. + <div class="Bd Pp Bd-indent Li"> + <pre>set hostid 1</pre> + </div> + <p class="Pp">The hostid may be specified in either decimal or + hexadecimal.</p> + </dd> + <dt id="options"><var class="Ar">set require-order</var></dt> + <dd>By default <a class="Xr">pfctl(8)</a> enforces an ordering of the + statement types in the ruleset to: + <a class="permalink" href="#options"><i class="Em">options</i></a>, + <a class="permalink" href="#normalization"><i class="Em" id="normalization">normalization</i></a>, + <a class="permalink" href="#queueing"><i class="Em" id="queueing">queueing</i></a>, + <a class="permalink" href="#translation"><i class="Em" id="translation">translation</i></a>, + <a class="permalink" href="#filtering"><i class="Em" id="filtering">filtering</i></a>. + Setting this option to <var class="Ar">no</var> disables this enforcement. + There may be non-trivial and non-obvious implications to an out of order + ruleset. Consider carefully before disabling the order enforcement.</dd> + <dt><var class="Ar">set fingerprints</var></dt> + <dd>Load fingerprints of known operating systems from the given filename. By + default fingerprints of known operating systems are automatically loaded + from <a class="Xr">pf.os(5)</a> in <span class="Pa">/etc</span> 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 <span class="Pa">/etc/pf.os</span>. + <p class="Pp">For example:</p> + <p class="Pp"></p> + <div class="Bd Bd-indent"><code class="Li">set fingerprints + "/etc/pf.os.devel"</code></div> + </dd> + <dt><var class="Ar">set skip on</var> + ⟨<var class="Ar">ifspec</var>⟩</dt> + <dd>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. For example: + <p class="Pp"></p> + <div class="Bd Bd-indent"><code class="Li">set skip on lo0</code></div> + </dd> + <dt><var class="Ar">set debug</var></dt> + <dd>Set the debug <var class="Ar">level</var> to one of the following: + <p class="Pp"></p> + <dl class="Bl-tag Bl-compact"> + <dt><var class="Ar">none</var></dt> + <dd>Don't generate debug messages.</dd> + <dt><var class="Ar">urgent</var></dt> + <dd>Generate debug messages only for serious errors.</dd> + <dt><var class="Ar">misc</var></dt> + <dd>Generate debug messages for various errors.</dd> + <dt><var class="Ar">loud</var></dt> + <dd>Generate debug messages for common conditions.</dd> + </dl> + </dd> + <dt><var class="Ar">set keepcounters</var></dt> + <dd>Preserve rule counters across rule updates. Usually rule counters are + reset to zero on every update of the ruleset. With + <var class="Ar">keepcounters</var> set pf will attempt to find matching + rules between old and new rulesets and preserve the rule counters.</dd> +</dl> +</section> +<section class="Sh"> +<h1 class="Sh" id="ETHERNET_FILTERING"><a class="permalink" href="#ETHERNET_FILTERING">ETHERNET + FILTERING</a></h1> +<p class="Pp"><a class="Xr">pf(4)</a> has the ability to + <var class="Ar">block</var> and <var class="Ar">pass</var> packets based on + attributes of their Ethernet (layer 2) header.</p> +<p class="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. 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.</p> +<p class="Pp">The following actions can be used in the filter:</p> +<dl class="Bl-tag"> + <dt><var class="Ar">block</var></dt> + <dd>The packet is blocked. Unlike for layer 3 traffic the packet is always + silently dropped.</dd> + <dt><var class="Ar">pass</var></dt> + <dd>The packet is passed; no state is created for layer 2 traffic.</dd> +</dl> +<section class="Ss"> +<h2 class="Ss" id="Parameters_applicable_to_layer_2_rules"><a class="permalink" href="#Parameters_applicable_to_layer_2_rules">Parameters + applicable to layer 2 rules</a></h2> +<p class="Pp">The rule parameters specify the packets to which a rule applies. A + packet always comes in on, or goes out through, one interface. Most + parameters are optional. If a parameter is specified, the rule only applies + to packets with matching attributes. The matching for some parameters can be + inverted with the <code class="Cm">!</code> operator. Certain parameters can + be expressed as lists, in which case <a class="Xr">pfctl(8)</a> generates + all needed rule combinations.</p> +<dl class="Bl-tag"> + <dt><var class="Ar">in</var> <span class="No">or</span> + <var class="Ar">out</var></dt> + <dd>This rule applies to incoming or outgoing packets. If neither + <var class="Ar">in</var> nor <var class="Ar">out</var> are specified, the + rule will match packets in both directions.</dd> + <dt><var class="Ar">quick</var></dt> + <dd>If a packet matches a rule which has the <var class="Ar">quick</var> + option set, this rule is considered the last matching rule, and evaluation + of subsequent rules is skipped.</dd> + <dt><var class="Ar">on</var> ⟨<var class="Ar">ifspec</var>⟩</dt> + <dd>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 <code class="Ic">group</code> keyword in + <a class="Xr">ifconfig(8)</a>. <var class="Ar">any</var> will match any + existing interface except loopback ones.</dd> + <dt><var class="Ar">bridge-to</var> ⟨interface⟩</dt> + <dd>Packets matching this rule will be sent out of the specified interface + without further processing.</dd> + <dt><var class="Ar">proto</var> + ⟨<var class="Ar">protocol</var>⟩</dt> + <dd>This rule applies only to packets of this protocol. Note that Ethernet + protocol numbers are different from those used in <a class="Xr">ip(4)</a> + and <a class="Xr">ip6(4)</a>.</dd> + <dt><var class="Ar">from</var> ⟨<var class="Ar">source</var>⟩ + <var class="Ar">to</var> ⟨<var class="Ar">dest</var>⟩</dt> + <dd>This rule applies only to packets with the specified source and + destination MAC addresses.</dd> + <dt><var class="Ar">queue</var> + ⟨<var class="Ar">queue</var>⟩</dt> + <dd>Packets matching this rule will be assigned to the specified queue. See + <a class="Sx" href="#QUEUEING">QUEUEING</a> for setup details.</dd> + <dt><var class="Ar">tag</var> + ⟨<var class="Ar">string</var>⟩</dt> + <dd>Packets matching this rule will be tagged with the specified string. The + tag acts as an internal marker that can be used to identify these packets + later on. This can be used, for example, to provide trust between + interfaces and to determine if packets have been processed by translation + rules. Tags are "sticky", meaning that the packet will be tagged + even if the rule is not the last matching rule. Further matching rules can + replace the tag with a new one but will not remove a previously applied + tag. A packet is only ever assigned one tag at a time.</dd> + <dt><var class="Ar">tagged</var> + ⟨<var class="Ar">string</var>⟩</dt> + <dd>Used to specify that packets must already be tagged with the given tag in + order to match the rule. Inverse tag matching can also be done by + specifying the ! operator before the tagged keyword.</dd> +</dl> +</section> +</section> +<section class="Sh"> +<h1 class="Sh" id="TRAFFIC_NORMALIZATION"><a class="permalink" href="#TRAFFIC_NORMALIZATION">TRAFFIC + NORMALIZATION</a></h1> +<p class="Pp">Traffic normalization is a broad umbrella term for aspects of the + packet filter which deal with verifying packets, packet fragments, spoofed + traffic, and other irregularities.</p> +<section class="Ss"> +<h2 class="Ss" id="Scrub"><a class="permalink" href="#Scrub">Scrub</a></h2> +<p class="Pp">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 <code class="Cm">scrub</code> option, added to filter + rules.</p> +<p class="Pp">Parameters are specified enclosed in parentheses. At least one of + the following parameters must be specified:</p> +<dl class="Bl-tag"> + <dt><var class="Ar">no-df</var></dt> + <dd>Clears the <var class="Ar">dont-fragment</var> bit from a matching IP + packet. Some operating systems are known to generate fragmented packets + with the <var class="Ar">dont-fragment</var> bit set. This is particularly + true with NFS. <var class="Ar">Scrub</var> will drop such fragmented + <var class="Ar">dont-fragment</var> packets unless + <var class="Ar">no-df</var> is specified. + <p class="Pp">Unfortunately some operating systems also generate their + <var class="Ar">dont-fragment</var> packets with a zero IP + identification field. Clearing the <var class="Ar">dont-fragment</var> + bit on packets with a zero IP ID may cause deleterious results if an + upstream router later fragments the packet. Using the + <var class="Ar">random-id</var> modifier (see below) is recommended in + combination with the <var class="Ar">no-df</var> modifier to ensure + unique IP identifiers.</p> + </dd> + <dt><var class="Ar">min-ttl</var> + ⟨<var class="Ar">number</var>⟩</dt> + <dd>Enforces a minimum TTL for matching IP packets.</dd> + <dt><var class="Ar">max-mss</var> + ⟨<var class="Ar">number</var>⟩</dt> + <dd>Reduces the maximum segment size (MSS) on TCP SYN packets to be no greater + than <var class="Ar">number</var>. 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 + <a class="Xr">pf(4)</a>.</dd> + <dt><var class="Ar">set-tos</var> ⟨<var class="Ar">string</var>⟩ + | ⟨<var class="Ar">number</var>⟩</dt> + <dd>Enforces a <i class="Em">TOS</i> for matching IP packets. + <i class="Em">TOS</i> may be given as one of + <var class="Ar">critical</var>, <var class="Ar">inetcontrol</var>, + <var class="Ar">lowdelay</var>, <var class="Ar">netcontrol</var>, + <var class="Ar">throughput</var>, <var class="Ar">reliability</var>, or + one of the DiffServ Code Points: <var class="Ar">ef</var>, + <var class="Ar">va</var>, <var class="Ar">af11</var> + <span class="No">...</span> <var class="Ar">af43</var>, + <var class="Ar">cs0</var> <span class="No">...</span> + <var class="Ar">cs7</var>; or as either hex or decimal.</dd> + <dt><var class="Ar">random-id</var></dt> + <dd>Replaces the IP 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.</dd> + <dt><var class="Ar">reassemble tcp</var></dt> + <dd>Statefully normalizes TCP connections. <var class="Ar">reassemble + tcp</var> performs the following normalizations: + <p class="Pp"></p> + <dl class="Bl-tag Bl-compact"> + <dt>ttl</dt> + <dd>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. + <var class="Ar">reassemble tcp</var> will raise the TTL of all packets + back up to the highest value seen on the connection.</dd> + <dt>timestamp modulation</dt> + <dd>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. <var class="Ar">reassemble tcp</var> will cause + <var class="Ar">scrub</var> to modulate the TCP timestamps with a + random number.</dd> + <dt>extended PAWS checks</dt> + <dd>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. <var class="Ar">reassemble tcp</var> + also makes sure the timestamp on the packet does not go forward more + than the RFC allows. By doing this, <a class="Xr">pf(4)</a> + 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.</dd> + </dl> + </dd> +</dl> +<p class="Pp">For example,</p> +<div class="Bd Pp Bd-indent Li"> +<pre>match in all scrub (no-df random-id max-mss 1440)</pre> +</div> +</section> +<section class="Ss"> +<h2 class="Ss" id="Scrub_ruleset_(pre-FreeBSD_14)"><a class="permalink" href="#Scrub_ruleset_(pre-FreeBSD_14)">Scrub + ruleset (pre-FreeBSD 14)</a></h2> +<p class="Pp">In order to maintain compatibility with older releases of FreeBSD + <var class="Ar">scrub</var> rules can also be specified in their own + ruleset. In such case they are invoked with the <var class="Ar">scrub</var> + directive. If there are such rules present they determine packet reassembly + behaviour. When no such rules are present the option <var class="Ar">set + reassembly</var> takes precedence. The <var class="Ar">scrub</var> rules can + take all parameters specified above for a <var class="Ar">scrub</var> option + of filter rules and 2 more parameters controlling fragment reassembly:</p> +<dl class="Bl-tag"> + <dt><var class="Ar">fragment reassemble</var></dt> + <dd>Using <var class="Ar">scrub</var> rules, fragments can be reassembled by + normalization. In this case, fragments are buffered until they form a + complete packet, and only the completed packet is passed on to the filter. + The advantage is that filter rules have to deal only with complete + packets, and can ignore fragments. The drawback of caching fragments is + the additional memory cost. This is the default behaviour unless no + fragment reassemble is specified.</dd> + <dt><var class="Ar">no fragment reassemble</var></dt> + <dd>Do not reassemble fragments.</dd> +</dl> +<p class="Pp">For example,</p> +<div class="Bd Pp Bd-indent Li"> +<pre>scrub in on $ext_if all fragment reassemble</pre> +</div> +<p class="Pp">The <var class="Ar">no</var> option prefixed to a scrub rule + causes matching packets to remain unscrubbed, much in the same way as + <var class="Ar">drop quick</var> works in the packet filter (see below). + This mechanism should be used when it is necessary to exclude specific + packets from broader scrub rules.</p> +<p class="Pp"><var class="Ar">scrub</var> rules in the + <var class="Ar">scrub</var> ruleset are evaluated for every packet before + stateful filtering. This means excessive usage of them will cause + performance penalty. <var class="Ar">scrub reassemble tcp</var> rules must + not have the direction (in/out) specified.</p> +</section> +</section> +<section class="Sh"> +<h1 class="Sh" id="QUEUEING_with_ALTQ"><a class="permalink" href="#QUEUEING_with_ALTQ">QUEUEING + with ALTQ</a></h1> +<p class="Pp">The ALTQ system is currently not available in the GENERIC kernel + nor as loadable modules. In order to use the herein after called queueing + options one has to use a custom built kernel. Please refer to + <a class="Xr">altq(4)</a> to learn about the related kernel options.</p> +<p class="Pp">Packets can be assigned to queues for the purpose of bandwidth + control. At least two declarations are required to configure queues, and + later any packet filtering rule can reference the defined queues by name. + During the filtering component of <code class="Nm">pf.conf</code>, the last + referenced <var class="Ar">queue</var> name is where any packets from + <var class="Ar">pass</var> rules will be queued, while for + <var class="Ar">block</var> rules it specifies where any resulting ICMP or + TCP RST packets should be queued. The <var class="Ar">scheduler</var> + defines the algorithm used to decide which packets get delayed, dropped, or + sent out immediately. There are three <var class="Ar">schedulers</var> + currently supported.</p> +<dl class="Bl-tag"> + <dt><var class="Ar">cbq</var></dt> + <dd>Class Based Queueing. <var class="Ar">Queues</var> attached to an + interface build a tree, thus each <var class="Ar">queue</var> can have + further child <var class="Ar">queues</var>. Each queue can have a + <var class="Ar">priority</var> and a <var class="Ar">bandwidth</var> + assigned. <var class="Ar">Priority</var> mainly controls the time packets + take to get sent out, while <var class="Ar">bandwidth</var> has primarily + effects on throughput. <var class="Ar">cbq</var> achieves both + partitioning and sharing of link bandwidth by hierarchically structured + classes. Each class has its own <var class="Ar">queue</var> and is + assigned its share of <var class="Ar">bandwidth</var>. A child class can + borrow bandwidth from its parent class as long as excess bandwidth is + available (see the option <var class="Ar">borrow</var>, below).</dd> + <dt><var class="Ar">priq</var></dt> + <dd>Priority Queueing. <var class="Ar">Queues</var> are flat attached to the + interface, thus, <var class="Ar">queues</var> cannot have further child + <var class="Ar">queues</var>. Each <var class="Ar">queue</var> has a + unique <var class="Ar">priority</var> assigned, ranging from 0 to 15. + Packets in the <var class="Ar">queue</var> with the highest + <var class="Ar">priority</var> are processed first.</dd> + <dt><var class="Ar">hfsc</var></dt> + <dd>Hierarchical Fair Service Curve. <var class="Ar">Queues</var> attached to + an interface build a tree, thus each <var class="Ar">queue</var> can have + further child <var class="Ar">queues</var>. Each queue can have a + <var class="Ar">priority</var> and a <var class="Ar">bandwidth</var> + assigned. <var class="Ar">Priority</var> mainly controls the time packets + take to get sent out, while <var class="Ar">bandwidth</var> primarily + affects throughput. <var class="Ar">hfsc</var> supports both link-sharing + and guaranteed real-time services. It employs a service curve based QoS + model, and its unique feature is an ability to decouple + <var class="Ar">delay</var> and <var class="Ar">bandwidth</var> + allocation.</dd> +</dl> +<p class="Pp">The interfaces on which queueing should be activated are declared + using the <var class="Ar">altq on</var> declaration. <var class="Ar">altq + on</var> has the following keywords:</p> +<dl class="Bl-tag"> + <dt>⟨<var class="Ar">interface</var>⟩</dt> + <dd>Queueing is enabled on the named interface.</dd> + <dt>⟨<var class="Ar">scheduler</var>⟩</dt> + <dd>Specifies which queueing scheduler to use. Currently supported values are + <var class="Ar">cbq</var> for Class Based Queueing, + <var class="Ar">priq</var> for Priority Queueing and + <var class="Ar">hfsc</var> for the Hierarchical Fair Service Curve + scheduler.</dd> + <dt><var class="Ar">bandwidth</var> + ⟨<var class="Ar">bw</var>⟩</dt> + <dd>The maximum bitrate for all queues on an interface may be specified using + the <var class="Ar">bandwidth</var> keyword. The value can be specified as + an absolute value or as a percentage of the interface bandwidth. When + using an absolute value, the suffixes <var class="Ar">b</var>, + <var class="Ar">Kb</var>, <var class="Ar">Mb</var>, and + <var class="Ar">Gb</var> are used to represent bits, kilobits, megabits, + and gigabits per second, respectively. The value must not exceed the + interface bandwidth. If <var class="Ar">bandwidth</var> is not specified, + the interface bandwidth is used (but take note that some interfaces do not + know their bandwidth, or can adapt their bandwidth rates).</dd> + <dt><var class="Ar">qlimit</var> + ⟨<var class="Ar">limit</var>⟩</dt> + <dd>The maximum number of packets held in the queue. The default is 50.</dd> + <dt><var class="Ar">tbrsize</var> + ⟨<var class="Ar">size</var>⟩</dt> + <dd>Adjusts the size, in bytes, of the token bucket regulator. If not + specified, heuristics based on the interface bandwidth are used to + determine the size.</dd> + <dt><var class="Ar">queue</var> + ⟨<var class="Ar">list</var>⟩</dt> + <dd>Defines a list of subqueues to create on an interface.</dd> +</dl> +<p class="Pp">In the following example, the interface dc0 should queue up to + 5Mbps in four second-level queues using Class Based Queueing. Those four + queues will be shown in a later example.</p> +<div class="Bd Pp Bd-indent Li"> +<pre>altq on dc0 cbq bandwidth 5Mb queue { std, http, mail, ssh }</pre> +</div> +<p class="Pp">Once interfaces are activated for queueing using the + <var class="Ar">altq</var> directive, a sequence of + <var class="Ar">queue</var> directives may be defined. The name associated + with a <var class="Ar">queue</var> must match a queue defined in the + <var class="Ar">altq</var> directive (e.g. mail), or, except for the + <var class="Ar">priq</var> <var class="Ar">scheduler</var>, in a parent + <var class="Ar">queue</var> declaration. The following keywords can be + used:</p> +<dl class="Bl-tag"> + <dt><var class="Ar">on</var> + ⟨<var class="Ar">interface</var>⟩</dt> + <dd>Specifies the interface the queue operates on. If not given, it operates + on all matching interfaces.</dd> + <dt><var class="Ar">bandwidth</var> + ⟨<var class="Ar">bw</var>⟩</dt> + <dd>Specifies the maximum bitrate to be processed by the queue. This value + must not exceed the value of the parent <var class="Ar">queue</var> and + can be specified as an absolute value or a percentage of the parent + queue's bandwidth. If not specified, defaults to 100% of the parent + queue's bandwidth. The <var class="Ar">priq</var> scheduler does not + support bandwidth specification.</dd> + <dt><var class="Ar">priority</var> + ⟨<var class="Ar">level</var>⟩</dt> + <dd>Between queues a priority level can be set. For <var class="Ar">cbq</var> + and <var class="Ar">hfsc</var>, the range is 0 to 7 and for + <var class="Ar">priq</var>, the range is 0 to 15. The default for all is + 1. <var class="Ar">Priq</var> queues with a higher priority are always + served first. <var class="Ar">Cbq</var> and <var class="Ar">Hfsc</var> + queues with a higher priority are preferred in the case of overload.</dd> + <dt><var class="Ar">qlimit</var> + ⟨<var class="Ar">limit</var>⟩</dt> + <dd>The maximum number of packets held in the queue. The default is 50.</dd> +</dl> +<p class="Pp">The <var class="Ar">scheduler</var> can get additional parameters + with ⟨<var class="Ar">scheduler</var>⟩ + (⟨<var class="Ar">parameters</var>⟩). Parameters are as + follows:</p> +<dl class="Bl-tag"> + <dt><var class="Ar">default</var></dt> + <dd>Packets not matched by another queue are assigned to this one. Exactly one + default queue is required.</dd> + <dt><var class="Ar">red</var></dt> + <dd>Enable RED (Random Early Detection) on this queue. RED drops packets with + a probability proportional to the average queue length.</dd> + <dt><var class="Ar">rio</var></dt> + <dd>Enables RIO on this queue. RIO is RED with IN/OUT, thus running RED two + times more than RIO would achieve the same effect. RIO is currently not + supported in the GENERIC kernel.</dd> + <dt><var class="Ar">ecn</var></dt> + <dd>Enables ECN (Explicit Congestion Notification) on this queue. ECN implies + RED.</dd> +</dl> +<p class="Pp">The <var class="Ar">cbq</var> <var class="Ar">scheduler</var> + supports an additional option:</p> +<dl class="Bl-tag"> + <dt><var class="Ar">borrow</var></dt> + <dd>The queue can borrow bandwidth from the parent.</dd> +</dl> +<p class="Pp">The <var class="Ar">hfsc</var> <var class="Ar">scheduler</var> + supports some additional options:</p> +<dl class="Bl-tag"> + <dt><var class="Ar">realtime</var> + ⟨<var class="Ar">sc</var>⟩</dt> + <dd>The minimum required bandwidth for the queue.</dd> + <dt><var class="Ar">upperlimit</var> + ⟨<var class="Ar">sc</var>⟩</dt> + <dd>The maximum allowed bandwidth for the queue.</dd> + <dt><var class="Ar">linkshare</var> + ⟨<var class="Ar">sc</var>⟩</dt> + <dd>The bandwidth share of a backlogged queue.</dd> +</dl> +<p class="Pp">⟨<var class="Ar">sc</var>⟩ is an acronym for + <var class="Ar">service curve</var>.</p> +<p class="Pp">The format for service curve specifications is + (<var class="Ar">m1</var>, <var class="Ar">d</var>, + <var class="Ar">m2</var>). <var class="Ar">m2</var> controls the bandwidth + assigned to the queue. <var class="Ar">m1</var> and <var class="Ar">d</var> + are optional and can be used to control the initial bandwidth assignment. + For the first <var class="Ar">d</var> milliseconds the queue gets the + bandwidth given as <var class="Ar">m1</var>, afterwards the value given in + <var class="Ar">m2</var>.</p> +<p class="Pp">Furthermore, with <var class="Ar">cbq</var> and + <var class="Ar">hfsc</var>, child queues can be specified as in an + <var class="Ar">altq</var> declaration, thus building a tree of queues using + a part of their parent's bandwidth.</p> +<p class="Pp">Packets can be assigned to queues based on filter rules by using + the <var class="Ar">queue</var> keyword. Normally only one + <var class="Ar">queue</var> is specified; when a second one is specified it + will instead be used for packets which have a <i class="Em">TOS</i> of + <i class="Em">lowdelay</i> and for TCP ACKs with no data payload.</p> +<p class="Pp">To continue the previous example, the examples below would specify + the four referenced queues, plus a few child queues. Interactive + <a class="Xr">ssh(1)</a> sessions get priority over bulk transfers like + <a class="Xr">scp(1)</a> and <a class="Xr">sftp(1)</a>. The queues may then + be referenced by filtering rules (see + <a class="Sx" href="#PACKET_FILTERING">PACKET FILTERING</a> below).</p> +<div class="Bd Pp Li"> +<pre>queue std bandwidth 10% cbq(default) +queue http bandwidth 60% priority 2 cbq(borrow red) \ + { employees, developers } +queue developers bandwidth 75% cbq(borrow) +queue employees bandwidth 15% +queue mail bandwidth 10% priority 0 cbq(borrow ecn) +queue ssh bandwidth 20% cbq(borrow) { ssh_interactive, ssh_bulk } +queue ssh_interactive bandwidth 50% priority 7 cbq(borrow) +queue ssh_bulk bandwidth 50% priority 0 cbq(borrow) + +block return out on dc0 inet all queue std +pass out on dc0 inet proto tcp from $developerhosts to any port 80 \ + queue developers +pass out on dc0 inet proto tcp from $employeehosts to any port 80 \ + queue employees +pass out on dc0 inet proto tcp from any to any port 22 \ + queue(ssh_bulk, ssh_interactive) +pass out on dc0 inet proto tcp from any to any port 25 \ + queue mail</pre> +</div> +</section> +<section class="Sh"> +<h1 class="Sh" id="QUEUEING_with_dummynet"><a class="permalink" href="#QUEUEING_with_dummynet">QUEUEING + with dummynet</a></h1> +<p class="Pp">Queueing can also be done with <a class="Xr">dummynet(4)</a>. + Queues and pipes can be created with <a class="Xr">dnctl(8)</a>.</p> +<p class="Pp">Packets can be assigned to queues and pipes using + <var class="Ar">dnqueue</var> and <var class="Ar">dnpipe</var> + respectively.</p> +<p class="Pp">Both <var class="Ar">dnqueue</var> and + <var class="Ar">dnpipe</var> take either a single pipe or queue number or + two numbers as arguments. The first pipe or queue number will be used to + shape the traffic in the rule direction, the second will be used to shape + the traffic in the reverse direction. If the rule does not specify a + direction the first packet to create state will be shaped according to the + first number, and the response traffic according to the second.</p> +<p class="Pp">If the <a class="Xr">dummynet(4)</a> module is not loaded any + traffic sent into a queue or pipe will be dropped.</p> +</section> +<section class="Sh"> +<h1 class="Sh" id="TRANSLATION"><a class="permalink" href="#TRANSLATION">TRANSLATION</a></h1> +<p class="Pp">Translation options modify either the source or destination + address and port of the packets associated with a stateful connection. + <a class="Xr">pf(4)</a> modifies the specified address and/or port in the + packet and recalculates IP, TCP, and UDP checksums as necessary.</p> +<p class="Pp">If specified on a <code class="Ic">match</code> 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.</p> +<p class="Pp">The state entry created permits <a class="Xr">pf(4)</a> to keep + track of the original address for traffic associated with that state and + correctly direct return traffic for that connection.</p> +<p class="Pp">Various types of translation are possible with pf:</p> +<dl class="Bl-tag"> + <dt><var class="Ar">af-to</var></dt> + <dd>Translation between different address families (NAT64) is handled using + <var class="Ar">af-to</var> rules. Because address family translation + overrides the routing table, it's only possible to use + <var class="Ar">af-to</var> on inbound rules, and a source address of the + resulting translation must always be specified. + <p class="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.</p> + <p class="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.</p> + <p class="Pp">For example, the following rules are identical:</p> + <div class="Bd Pp Bd-indent Li"> + <pre>pass in inet af-to inet6 from 2001:db8::1 to 2001:db8::/96 +pass in inet af-to inet6 from 2001:db8::1</pre> + </div> + <p class="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.</p> + <p class="Pp">In the reverse case the following rules are identical:</p> + <div class="Bd Pp Bd-indent Li"> + <pre>pass in inet6 from any to 64:ff9b::/96 af-to inet \ + from 198.51.100.1 to 0.0.0.0/0 +pass in inet6 from any to 64:ff9b::/96 af-to inet \ + from 198.51.100.1</pre> + </div> + <p class="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.</p> + <p class="Pp">The current implementation will only extract IPv4 addresses + from the IPv6 addresses with a prefix length of /96 and greater.</p> + </dd> + <dt><var class="Ar">binat-to</var></dt> + <dd>A <var class="Ar">binat-to</var> rule specifies a bidirectional mapping + between an external IP netblock and an internal IP netblock. It expands to + an outbound <var class="Ar">nat-to</var> rule and an inbound + <var class="Ar">rdr-to</var> rule.</dd> + <dt><var class="Ar">nat-to</var></dt> + <dd>A <var class="Ar">nat-to</var> option specifies that IP addresses are to + be changed as the packet traverses the given interface. This technique + allows one or more IP addresses on the translating host to support network + traffic for a larger range of machines on an "inside" network. + Although in theory any IP address can be used on the inside, it is + strongly recommended that one of the address ranges defined by RFC 1918 be + used. These netblocks are: + <div class="Bd Pp Bd-indent Li"> + <pre>10.0.0.0 - 10.255.255.255 (all of net 10.0.0.0, i.e., 10.0.0.0/8) +172.16.0.0 - 172.31.255.255 (i.e., 172.16.0.0/12) +192.168.0.0 - 192.168.255.255 (i.e., 192.168.0.0/16)</pre> + </div> + <p class="Pp"><var class="Ar">nat-to</var> is usually applied outbound. If + applied inbound, nat-to to a local IP address is not supported.</p> + </dd> + <dt><span class="Pa">rdr-to</span></dt> + <dd>The packet is redirected to another destination and possibly a different + port. <var class="Ar">rdr-to</var> can optionally specify port ranges + instead of single ports. For instance: + <div class="Bd Pp Bd-indent Li"> + <pre>match in ... port 2000:2999 rdr-to ... port 4000</pre> + </div> + redirects ports 2000 to 2999 (inclusive) to port 4000. + <div class="Bd Pp Bd-indent Li"> + <pre>qmatch in ... port 2000:2999 rdr-to ... port 4000:*</pre> + </div> + redirects port 2000 to 4000, 2001 to 4001, ..., 2999 to 4999.</dd> +</dl> +<p class="Pp"><var class="Ar">rdr-to</var> is usually applied inbound. If + applied outbound, rdr-to to a local IP address is not supported. In addition + to modifying the address, some translation rules may modify source or + destination ports for <a class="Xr">tcp(4)</a> or <a class="Xr">udp(4)</a> + connections; implicitly in the case of <var class="Ar">nat-to</var> options + and both implicitly and explicitly in the case of + <var class="Ar">rdr-to</var> ones. A <var class="Ar">rdr-to</var> option may + cause the source port to be modified if doing so avoids a conflict with an + existing connection. A random source port in the range 50001-65535 is chosen + in this case. Port numbers are never translated with a + <var class="Ar">binat-to</var> option.</p> +<p class="Pp">Note that redirecting external incoming connections to the + loopback address, as in</p> +<div class="Bd Pp Bd-indent Li"> +<pre>pass in on egress proto tcp from any to any port smtp \ + rdr-to 127.0.0.1 port spamd</pre> +</div> +<p class="Pp">will effectively allow an external host to connect to daemons + bound solely to the loopback address, circumventing the traditional blocking + of such connections on a real interface. Unless this effect is desired, any + of the local non-loopback addresses should be used as redirection target + instead, which allows external connections only to daemons bound to this + address or not bound to any address.</p> +<p class="Pp">See <a class="Sx" href="#TRANSLATION_EXAMPLES">TRANSLATION + EXAMPLES</a> below.</p> +<section class="Ss"> +<h2 class="Ss" id="NAT_ruleset_(pre-FreeBSD_15)"><a class="permalink" href="#NAT_ruleset_(pre-FreeBSD_15)">NAT + ruleset (pre-FreeBSD 15)</a></h2> +<p class="Pp">In order to maintain compatibility with older releases of FreeBSD + <var class="Ar">NAT</var> rules can also be specified in their own ruleset. + A stateful connection is automatically created to track packets matching + such a rule as long as they are not blocked by the filtering section of + <code class="Nm">pf.conf</code>. Since translation occurs before filtering + the filter engine will see packets as they look after any addresses and + ports have been translated. Filter rules will therefore have to filter based + on the translated address and port number. Packets that match a translation + rule are only automatically passed if the <var class="Ar">pass</var> + modifier is given, otherwise they are still subject to + <var class="Ar">block</var> and <var class="Ar">pass</var> rules.</p> +<p class="Pp">The following rules can be defined in the NAT ruleset: + <var class="Ar">binat</var>, <var class="Ar">nat</var>, and + <var class="Ar">rdr</var>. They have the same effect as + <var class="Ar">binat-to</var>, <var class="Ar">nat-to</var> and + <var class="Ar">rdr-to</var> options for filter rules.</p> +<p class="Pp">The <var class="Ar">no</var> option prefixed to a translation rule + causes packets to remain untranslated, much in the same way as + <var class="Ar">drop quick</var> works in the packet filter. If no rule + matches the packet it is passed to the filter engine unmodified.</p> +<p class="Pp">Evaluation order of the translation rules is dependent on the type + of the translation rules and of the direction of a packet. + <var class="Ar">binat</var> rules are always evaluated first. Then either + the <var class="Ar">rdr</var> rules are evaluated on an inbound packet or + the <var class="Ar">nat</var> rules on an outbound packet. Rules of the same + type are evaluated in the same order in which they appear in the ruleset. + The first matching rule decides what action is taken.</p> +<p class="Pp">Translation rules apply only to packets that pass through the + specified interface, and if no interface is specified, translation is + applied to packets on all interfaces. For instance, redirecting port 80 on + an external interface to an internal web server will only work for + connections originating from the outside. Connections to the address of the + external interface from local hosts will not be redirected, since such + packets do not actually pass through the external interface. Redirections + cannot reflect packets back through the interface they arrive on, they can + only be redirected to hosts connected to different interfaces or to the + firewall itself.</p> +<p class="Pp">See + <a class="Sx" href="#COMPATIBILITY_TRANSLATION_EXAMPLES">COMPATIBILITY + TRANSLATION EXAMPLES</a> below.</p> +</section> +</section> +<section class="Sh"> +<h1 class="Sh" id="PACKET_FILTERING"><a class="permalink" href="#PACKET_FILTERING">PACKET + FILTERING</a></h1> +<p class="Pp"><a class="Xr">pf(4)</a> has the ability to + <var class="Ar">block</var> , <var class="Ar">pass</var> and + <var class="Ar">match</var> packets based on attributes of their layer 3 + (see <a class="Xr">ip(4)</a> and <a class="Xr">ip6(4)</a>) and layer 4 (see + <a class="Xr">icmp(4)</a>, <a class="Xr">icmp6(4)</a>, + <a class="Xr">tcp(4)</a>, <a class="Xr">sctp(4)</a>, + <a class="Xr">udp(4)</a>) headers. In addition, packets may also be assigned + to queues for the purpose of bandwidth control.</p> +<p class="Pp">For each packet processed by the packet filter, the filter rules + are evaluated in sequential order, from first to last. For + <var class="Ar">block</var> and <var class="Ar">pass</var> , the last + matching rule decides what action is taken. For <var class="Ar">match</var> + , rules are evaluated every time they match; the pass/block state of a + packet remains unchanged. If no rule matches the packet, the default action + is to pass the packet.</p> +<p class="Pp">The following actions can be used in the filter:</p> +<dl class="Bl-tag"> + <dt><var class="Ar">block</var></dt> + <dd>The packet is blocked. There are a number of ways in which a + <var class="Ar">block</var> rule can behave when blocking a packet. The + default behaviour is to <var class="Ar">drop</var> packets silently, + however this can be overridden or made explicit either globally, by + setting the <var class="Ar">block-policy</var> option, or on a per-rule + basis with one of the following options: + <p class="Pp"></p> + <dl class="Bl-tag Bl-compact"> + <dt><var class="Ar">drop</var></dt> + <dd>The packet is silently dropped.</dd> + <dt><var class="Ar">return-rst</var></dt> + <dd>This applies only to <a class="Xr">tcp(4)</a> packets, and issues a + TCP RST which closes the connection.</dd> + <dt><var class="Ar">return-icmp</var></dt> + <dd style="width: auto;"> </dd> + <dt><var class="Ar">return-icmp6</var></dt> + <dd>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.</dd> + <dt><var class="Ar">return</var></dt> + <dd>This causes a TCP RST to be returned for <a class="Xr">tcp(4)</a> + packets, an SCTP ABORT for SCTP and an ICMP UNREACHABLE for UDP and + other packets.</dd> + </dl> + <p class="Pp">Options returning ICMP packets currently have no effect if + <a class="Xr">pf(4)</a> operates on a <a class="Xr">if_bridge(4)</a>, as + the code to support this feature has not yet been implemented.</p> + <p class="Pp">The simplest mechanism to block everything by default and only + pass packets that match explicit rules is specify a first filter rule + of:</p> + <div class="Bd Pp Bd-indent Li"> + <pre>block all</pre> + </div> + </dd> + <dt><var class="Ar">match</var></dt> + <dd>The packet is matched. This mechanism is used to provide fine grained + filtering without altering the block/pass state of a packet. + <var class="Ar">match</var> rules differ from <var class="Ar">block</var> + and <var class="Ar">pass</var> rules in that parameters are set for every + rule a packet matches, not only on the last matching rule. For the + following parameters, this means that the parameter effectively becomes + "sticky" until explicitly overridden: + <var class="Ar">nat-to</var>, <var class="Ar">binat-to</var>, + <var class="Ar">rdr-to</var>, <var class="Ar">queue</var>, + <var class="Ar">dnpipe</var>, <var class="Ar">dnqueue</var>, + <var class="Ar">rtable</var>, <var class="Ar">scrub</var></dd> + <dt><var class="Ar">pass</var></dt> + <dd>The packet is passed; state is created unless the <var class="Ar">no + state</var> option is specified.</dd> +</dl> +<p class="Pp">By default <a class="Xr">pf(4)</a> filters packets statefully; the + first time a packet matches a <var class="Ar">pass</var> rule, a state entry + is created; for subsequent packets the filter checks whether the packet + matches any state. If it does, the packet is passed without evaluation of + any rules. After the connection is closed or times out, the state entry is + automatically removed.</p> +<p class="Pp">This has several advantages. For TCP connections, comparing a + packet to a state involves checking its sequence numbers, as well as TCP + timestamps if a <var class="Ar">scrub reassemble tcp</var> rule applies to + the connection. If these values are outside the narrow windows of expected + values, the packet is dropped. This prevents spoofing attacks, such as when + an attacker sends packets with a fake source address/port but does not know + the connection's sequence numbers. Similarly, <a class="Xr">pf(4)</a> knows + how to match ICMP replies to states. For example,</p> +<div class="Bd Pp Bd-indent Li"> +<pre>pass out inet proto icmp all icmp-type echoreq</pre> +</div> +<p class="Pp">allows echo requests (such as those created by + <a class="Xr">ping(8)</a>) out statefully, and matches incoming echo replies + correctly to states.</p> +<p class="Pp">Also, looking up states is usually faster than evaluating + rules.</p> +<p class="Pp">Furthermore, correct handling of ICMP error messages is critical + to many protocols, particularly TCP. <a class="Xr">pf(4)</a> 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.</p> +<p class="Pp">Finally, state tracking is required for <var class="Ar">nat</var>, + <var class="Ar">binat</var> <span class="No">and</span> + <var class="Ar">rdr</var> rules, in order to track address and port + translations and reverse the translation on returning packets.</p> +<p class="Pp"><a class="Xr">pf(4)</a> 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.</p> +<p class="Pp">If stateless filtering of individual packets is desired, the + <var class="Ar">no state</var> keyword can be used to specify that state + will not be created if this is the last matching rule. A number of + parameters can also be set to affect how <a class="Xr">pf(4)</a> handles + state tracking. See <a class="Sx" href="#STATEFUL_TRACKING_OPTIONS">STATEFUL + TRACKING OPTIONS</a> below for further details.</p> +<section class="Ss"> +<h2 class="Ss" id="Parameters"><a class="permalink" href="#Parameters">Parameters</a></h2> +<p class="Pp">The rule parameters specify the packets to which a rule applies. A + packet always comes in on, or goes out through, one interface. Most + parameters are optional. If a parameter is specified, the rule only applies + to packets with matching attributes. Certain parameters can be expressed as + lists, in which case <a class="Xr">pfctl(8)</a> generates all needed rule + combinations.</p> +<dl class="Bl-tag"> + <dt><var class="Ar">in</var> <span class="No">or</span> + <var class="Ar">out</var></dt> + <dd>This rule applies to incoming or outgoing packets. If neither + <var class="Ar">in</var> nor <var class="Ar">out</var> are specified, the + rule will match packets in both directions.</dd> + <dt><var class="Ar">log</var> (<code class="Cm">all</code> | + <code class="Cm">matches</code> | <code class="Cm">to</code> + ⟨<var class="Ar">interface</var>⟩ | + <code class="Cm">user</code>)</dt> + <dd>In addition to any action specified, log the packet. Only the packet that + establishes the state is logged, unless the <var class="Ar">no state</var> + option is specified. The logged packets are sent to a + <a class="Xr">pflog(4)</a> interface, by default pflog0; pflog0 is + monitored by the <a class="Xr">pflogd(8)</a> logging daemon which logs to + the file <span class="Pa">/var/log/pflog</span> in + <a class="Xr">pcap(3)</a> binary format. + <p class="Pp">The keywords <code class="Cm">all</code>, + <code class="Cm">matches</code>, <code class="Cm">to</code>, and + <code class="Cm">user</code> are optional and can be combined using + commas, but must be enclosed in parentheses if given.</p> + <p class="Pp">Use <code class="Cm">all</code> to force logging of all + packets for a connection. This is not necessary when <var class="Ar">no + state</var> is explicitly specified.</p> + <p class="Pp">If <code class="Cm">matches</code> is specified, it logs the + packet on all subsequent matching rules. It is often combined with + <code class="Cm">to</code> + ⟨<var class="Ar">interface</var>⟩ to avoid adding noise to + the default log file.</p> + <p class="Pp">The keyword <code class="Cm">user</code> logs the + <span class="Ux">UNIX</span> user ID of the user that owns the socket + and the PID of the process that has the socket open where the packet is + sourced from or destined to (depending on which socket is local). This + is in addition to the normal information logged.</p> + <p class="Pp">Only the first packet logged via <var class="Ar">log (all, + user)</var> will have the user credentials logged when using stateful + matching.</p> + <p class="Pp">To specify a logging interface other than pflog0, use the + syntax <code class="Cm">to</code> + ⟨<var class="Ar">interface</var>⟩.</p> + </dd> + <dt><var class="Ar">quick</var></dt> + <dd>If a packet matches a rule which has the <var class="Ar">quick</var> + option set, this rule is considered the last matching rule, and evaluation + of subsequent rules is skipped.</dd> + <dt><var class="Ar">on</var> + ⟨<var class="Ar">interface</var>⟩</dt> + <dd>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 <code class="Ic">group</code> keyword in + <a class="Xr">ifconfig(8)</a>. <var class="Ar">any</var> will match any + existing interface except loopback ones.</dd> + <dt>⟨<var class="Ar">af</var>⟩</dt> + <dd>This rule applies only to packets of this address family. Supported values + are <var class="Ar">inet</var> and <var class="Ar">inet6</var>.</dd> + <dt><var class="Ar">proto</var> + ⟨<var class="Ar">protocol</var>⟩</dt> + <dd>This rule applies only to packets of this protocol. Common protocols are + <a class="Xr">icmp(4)</a>, <a class="Xr">icmp6(4)</a>, + <a class="Xr">tcp(4)</a>, <a class="Xr">sctp(4)</a>, and + <a class="Xr">udp(4)</a>. For a list of all the protocol name to number + mappings used by <a class="Xr">pfctl(8)</a>, see the file + <span class="Pa">/etc/protocols</span>.</dd> + <dt><var class="Ar">from</var> ⟨<var class="Ar">source</var>⟩ + <var class="Ar">port</var> ⟨<var class="Ar">source</var>⟩ + <var class="Ar">os</var> ⟨<var class="Ar">source</var>⟩ + <var class="Ar">to</var> ⟨<var class="Ar">dest</var>⟩ + <var class="Ar">port</var> ⟨<var class="Ar">dest</var>⟩</dt> + <dd>This rule applies only to packets with the specified source and + destination addresses and ports. + <p class="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:</p> + <p class="Pp"></p> + <dl class="Bl-tag Bl-compact"> + <dt><var class="Ar">any</var></dt> + <dd>Any address.</dd> + <dt><var class="Ar">no-route</var></dt> + <dd>Any address which is not currently routable.</dd> + <dt><var class="Ar">urpf-failed</var></dt> + <dd>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.</dd> + <dt><var class="Ar">self</var></dt> + <dd>Expands to all addresses assigned to all interfaces.</dd> + <dt>⟨<var class="Ar">table</var>⟩</dt> + <dd>Any address that matches the given table.</dd> + </dl> + <p class="Pp">Ranges of addresses are specified by using the + ‘-’ operator. For instance: “10.1.1.10 - + 10.1.1.12” means all addresses from 10.1.1.10 to 10.1.1.12, hence + addresses 10.1.1.10, 10.1.1.11, and 10.1.1.12.</p> + <p class="Pp">Interface names and interface group names, and + <var class="Ar">self</var> can have modifiers appended:</p> + <p class="Pp"></p> + <dl class="Bl-tag Bl-compact"> + <dt><var class="Ar">:network</var></dt> + <dd>Translates to the network(s) attached to the interface.</dd> + <dt><var class="Ar">:broadcast</var></dt> + <dd>Translates to the interface's broadcast address(es).</dd> + <dt><var class="Ar">:peer</var></dt> + <dd>Translates to the point-to-point interface's peer address(es).</dd> + <dt><var class="Ar">:0</var></dt> + <dd>Do not include interface aliases.</dd> + </dl> + <p class="Pp">Host names may also have the <var class="Ar">:0</var> option + appended to restrict the name resolution to the first of each v4 and + non-link-local v6 address found.</p> + <p class="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 <var class="Ar">nat</var>.</p> + <p class="Pp" id="www">Ports can be specified either by number or by name. + For example, port 80 can be specified as + <a class="permalink" href="#www"><i class="Em">www</i></a>. For a list + of all port name to number mappings used by <a class="Xr">pfctl(8)</a>, + see the file <span class="Pa">/etc/services</span>.</p> + <p class="Pp">Ports and ranges of ports are specified by using these + operators:</p> + <div class="Bd Pp Bd-indent Li"> + <pre>= (equal) +!= (unequal) +< (less than) +<= (less than or equal) +> (greater than) +>= (greater than or equal) +: (range including boundaries) +>< (range excluding boundaries) +<> (except range)</pre> + </div> + <p class="Pp">‘><’, ‘<>’ and + ‘:’ are binary operators (they take two arguments). For + instance:</p> + <dl class="Bl-tag"> + <dt><var class="Ar">port 2000:2004</var></dt> + <dd>means ‘all ports >= 2000 and <= 2004’, hence ports + 2000, 2001, 2002, 2003 and 2004.</dd> + <dt><var class="Ar">port 2000 >< 2004</var></dt> + <dd>means ‘all ports > 2000 and < 2004’, hence ports + 2001, 2002 and 2003.</dd> + <dt><var class="Ar">port 2000 <> 2004</var></dt> + <dd>means ‘all ports < 2000 or > 2004’, hence ports + 1-1999 and 2005-65535.</dd> + </dl> + <p class="Pp">The operating system of the source host can be specified in + the case of TCP rules with the <var class="Ar">OS</var> modifier. See + the <a class="Sx" href="#OPERATING_SYSTEM_FINGERPRINTING">OPERATING + SYSTEM FINGERPRINTING</a> section for more information.</p> + <p class="Pp">The host, port and OS specifications are optional, as in the + following examples:</p> + <div class="Bd Pp Bd-indent Li"> + <pre>pass in all +pass in from any to any +pass in proto tcp from any port < 1024 to any +pass in proto tcp from any to any port 25 +pass in proto tcp from 10.0.0.0/8 port >= 1024 \ + to ! 10.1.2.3 port != ssh +pass in proto tcp from any os "OpenBSD"</pre> + </div> + </dd> + <dt><var class="Ar">all</var></dt> + <dd>This is equivalent to "from any to any".</dd> + <dt><var class="Ar">group</var> + ⟨<var class="Ar">group</var>⟩</dt> + <dd>Similar to <var class="Ar">user</var>, this rule only applies to packets + of sockets owned by the specified group.</dd> + <dt><var class="Ar">user</var> ⟨<var class="Ar">user</var>⟩</dt> + <dd>This rule only applies to packets of sockets owned by the specified user. + For outgoing connections initiated from the firewall, this is the user + that opened the connection. For incoming connections to the firewall + itself, this is the user that listens on the destination port. For + forwarded connections, where the firewall is not a connection endpoint, + the user and group are <i class="Em">unknown</i>. + <p class="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; for other protocols these parameters are + ignored.</p> + <p class="Pp">User and group refer to the effective (as opposed to the real) + IDs, in case the socket is created by a setuid/setgid process. User and + group IDs are stored when a socket is created; when a process creates a + listening socket as root (for instance, by binding to a privileged port) + and subsequently changes to another user ID (to drop privileges), the + credentials will remain root.</p> + <p class="Pp">User and group IDs can be specified as either numbers or + names. The syntax is similar to the one for ports. The value + <i class="Em">unknown</i> matches packets of forwarded connections. + <i class="Em">unknown</i> can only be used with the operators + <code class="Cm">=</code> and <code class="Cm">!=</code>. Other + constructs like <code class="Cm">user ≥ unknown</code> are + invalid. Forwarded packets with unknown user and group ID match only + rules that explicitly compare against <i class="Em">unknown</i> with the + operators <code class="Cm">=</code> or <code class="Cm">!=</code>. For + instance <code class="Cm">user ≥ 0</code> does not match + forwarded packets. The following example allows only selected users to + open outgoing connections:</p> + <div class="Bd Pp Bd-indent Li"> + <pre>block out proto { tcp, udp } all +pass out proto { tcp, udp } all user { < 1000, dhartmei }</pre> + </div> + <p class="Pp">The example below permits users with uid between 1000 and 1500 + to open connections:</p> + <div class="Bd Pp Bd-indent Li"> + <pre>block out proto tcp all +pass out proto tcp from self user { 999 >< 1501 }</pre> + </div> + <p class="Pp">The ‘:’ operator, which works for port number + matching, does not work for <code class="Cm">user</code> and + <code class="Cm">group</code> match.</p> + </dd> + <dt><var class="Ar">flags</var> ⟨<var class="Ar">a</var>⟩ + /⟨<var class="Ar">b</var>⟩ | + <span class="No">/</span>⟨<var class="Ar">b</var>⟩ | + <span class="No">any</span></dt> + <dd>This rule only applies to TCP packets that have the flags + ⟨<var class="Ar">a</var>⟩ set out of set + ⟨<var class="Ar">b</var>⟩. Flags not specified in + ⟨<var class="Ar">b</var>⟩ are ignored. For stateful + connections, the default is <var class="Ar">flags S/SA</var>. To indicate + that flags should not be checked at all, specify <var class="Ar">flags + any</var>. The flags are: (F)IN, (S)YN, (R)ST, (P)USH, (A)CK, (U)RG, + (E)CE, and C(W)R. + <dl class="Bl-tag"> + <dt><var class="Ar">flags S/S</var></dt> + <dd>Flag SYN is set. The other flags are ignored.</dd> + <dt><var class="Ar">flags S/SA</var></dt> + <dd>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.</dd> + <dt><var class="Ar">flags /SFRA</var></dt> + <dd>If the first set is not specified, it defaults to none. All of SYN, + FIN, RST and ACK must be unset.</dd> + </dl> + <p class="Pp">Because <var class="Ar">flags S/SA</var> is applied by default + (unless <var class="Ar">no state</var> is specified), only the initial + SYN packet of a TCP handshake will create a state for a TCP connection. + It is possible to be less restrictive, and allow state creation from + intermediate (non-SYN) packets, by specifying <var class="Ar">flags + any</var>. This will cause <a class="Xr">pf(4)</a> 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 + <var class="Ar">af-to</var>, <var class="Ar">nat</var>, + <var class="Ar">binat or</var> <var class="Ar">rdr</var> rules, + <var class="Ar">modulate</var> <span class="No">or</span> + <var class="Ar">synproxy state</var> options, or scrubbed with + <var class="Ar">reassemble tcp</var> will also not be recoverable from + intermediate packets. Such connections will stall and time out.</p> + </dd> + <dt><var class="Ar">icmp-type</var> ⟨<var class="Ar">type</var>⟩ + <var class="Ar">file ...</var> [code + ⟨<var class="Ar">code</var>⟩]</dt> + <dd style="width: auto;"> </dd> + <dt><var class="Ar">icmp6-type</var> + ⟨<var class="Ar">type</var>⟩ <var class="Ar">file ...</var> + [code ⟨<var class="Ar">code</var>⟩]</dt> + <dd>This rule only applies to ICMP or ICMPv6 packets with the specified type + and code. Text names for ICMP types and codes are listed in + <a class="Xr">icmp(4)</a> and <a class="Xr">icmp6(4)</a>. This parameter + is only valid for rules that cover protocols ICMP or ICMP6. The protocol + and the ICMP type indicator (<var class="Ar">icmp-type</var> or + <var class="Ar">icmp6-type</var>) must match.</dd> + <dt><var class="Ar">tos</var> ⟨<var class="Ar">string</var>⟩ | + ⟨<var class="Ar">number</var>⟩</dt> + <dd>This rule applies to packets with the specified <i class="Em">TOS</i> bits + set. <i class="Em">TOS</i> may be given as one of + <var class="Ar">critical</var>, <var class="Ar">inetcontrol</var>, + <var class="Ar">lowdelay</var>, <var class="Ar">netcontrol</var>, + <var class="Ar">throughput</var>, <var class="Ar">reliability</var>, or + one of the DiffServ Code Points: <var class="Ar">ef</var>, + <var class="Ar">va</var>, <var class="Ar">af11</var> + <span class="No">...</span> <var class="Ar">af43</var>, + <var class="Ar">cs0</var> <span class="No">...</span> + <var class="Ar">cs7</var>; or as either hex or decimal. + <p class="Pp">For example, the following rules are identical:</p> + <div class="Bd Pp Bd-indent Li"> + <pre>pass all tos lowdelay +pass all tos 0x10 +pass all tos 16</pre> + </div> + </dd> + <dt><var class="Ar">allow-opts</var></dt> + <dd>By default, packets with IPv4 options or IPv6 hop-by-hop or destination + options header are blocked. When <var class="Ar">allow-opts</var> is + specified for a <var class="Ar">pass</var> 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 <var class="Ar">pass</var> 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.</dd> + <dt><var class="Ar">label</var> + ⟨<var class="Ar">string</var>⟩</dt> + <dd>Adds a label (name) to the rule, which can be used to identify the rule. + For instance, pfctl -s labels shows per-rule statistics for rules that + have labels. + <p class="Pp">The following macros can be used in labels:</p> + <p class="Pp"></p> + <div class="Bd-indent"> + <dl class="Bl-tag Bl-compact"> + <dt><var class="Ar">$if</var></dt> + <dd>The interface.</dd> + <dt><var class="Ar">$srcaddr</var></dt> + <dd>The source IP address.</dd> + <dt><var class="Ar">$dstaddr</var></dt> + <dd>The destination IP address.</dd> + <dt><var class="Ar">$srcport</var></dt> + <dd>The source port specification.</dd> + <dt><var class="Ar">$dstport</var></dt> + <dd>The destination port specification.</dd> + <dt><var class="Ar">$proto</var></dt> + <dd>The protocol name.</dd> + <dt><var class="Ar">$nr</var></dt> + <dd>The rule number.</dd> + </dl> + </div> + <p class="Pp">For example:</p> + <div class="Bd Pp Bd-indent Li"> + <pre>ips = "{ 1.2.3.4, 1.2.3.5 }" +pass in proto tcp from any to $ips \ + port > 1023 label "$dstaddr:$dstport"</pre> + </div> + <p class="Pp">expands to</p> + <div class="Bd Pp Bd-indent Li"> + <pre>pass in inet proto tcp from any to 1.2.3.4 \ + port > 1023 label "1.2.3.4:>1023" +pass in inet proto tcp from any to 1.2.3.5 \ + port > 1023 label "1.2.3.5:>1023"</pre> + </div> + <p class="Pp">The macro expansion for the <var class="Ar">label</var> + directive occurs only at configuration file parse time, not during + runtime.</p> + </dd> + <dt><var class="Ar">ridentifier</var> + ⟨<var class="Ar">number</var>⟩</dt> + <dd>Add an identifier (number) to the rule, which can be used to correlate the + rule to pflog entries, even after ruleset updates.</dd> + <dt id="max-pkt-rate"><a class="permalink" href="#max-pkt-rate"><code class="Cm">max-pkt-rate</code></a> + <var class="Ar">number</var>/<var class="Ar">seconds</var></dt> + <dd>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: + <div class="Bd Pp Bd-indent Li"> + <pre>block in proto icmp +pass in proto icmp max-pkt-rate 100/10</pre> + </div> + <p class="Pp">When the rate is exceeded, all ICMP is blocked until the rate + falls below 100 per 10 seconds again.</p> + </dd> + <dt><var class="Ar">max-pkt-size</var> + ⟨<var class="Ar">number</var>⟩</dt> + <dd>Limit each packet to be no more than the specified number of bytes. This + includes the IP header, but not any layer 2 header.</dd> + <dt><var class="Ar">once</var></dt> + <dd>Create a one shot rule. The first matching packet marks the rule as + expired. Expired rules are skipped and hidden, unless + <a class="Xr">pfctl(8)</a> is used in debug or verbose mode.</dd> + <dt><var class="Ar">queue</var> ⟨<var class="Ar">queue</var>⟩ | + (⟨<var class="Ar">queue</var>⟩, + ⟨<var class="Ar">queue</var>⟩)</dt> + <dd>Packets matching this rule will be assigned to the specified queue. If two + queues are given, packets which have a <i class="Em">TOS</i> of + <i class="Em">lowdelay</i> and TCP ACKs with no data payload will be + assigned to the second one. See + <a class="Sx" href="#QUEUEING">QUEUEING</a> for setup details. + <p class="Pp">For example:</p> + <div class="Bd Pp Bd-indent Li"> + <pre>pass in proto tcp to port 25 queue mail +pass in proto tcp to port 22 queue(ssh_bulk, ssh_prio)</pre> + </div> + </dd> + <dt id="set"><a class="permalink" href="#set"><code class="Cm">set + prio</code></a> <var class="Ar">priority</var> | + (<var class="Ar">priority</var>, <var class="Ar">priority</var>)</dt> + <dd>Packets matching this rule will be assigned a specific queueing priority. + Priorities are assigned as integers 0 through 7. If the packet is + transmitted on a <a class="Xr">vlan(4)</a> interface, the queueing + priority will be written as the priority code point in the 802.1Q VLAN + header. If two priorities are given, TCP ACKs with no data payload and + packets which have a TOS of <code class="Cm">lowdelay</code> will be + assigned to the second one. + <p class="Pp">For example:</p> + <div class="Bd Pp Bd-indent Li"> + <pre>pass in proto tcp to port 25 set prio 2 +pass in proto tcp to port 22 set prio (2, 5)</pre> + </div> + </dd> + <dt>[<code class="Cm">!</code>]<code class="Cm">received-on</code> + <var class="Ar">interface</var></dt> + <dd>Only match packets which were received on the specified + <var class="Ar">interface</var> (or interface group). + <var class="Ar">any</var> will match any existing interface except + loopback ones.</dd> + <dt><var class="Ar">tag</var> + ⟨<var class="Ar">string</var>⟩</dt> + <dd>Packets matching this rule will be tagged with the specified string. The + tag acts as an internal marker that can be used to identify these packets + later on. This can be used, for example, to provide trust between + interfaces and to determine if packets have been processed by translation + rules. Tags are "sticky", meaning that the packet will be tagged + even if the rule is not the last matching rule. Further matching rules can + replace the tag with a new one but will not remove a previously applied + tag. A packet is only ever assigned one tag at a time. Packet tagging can + be done during <var class="Ar">nat</var>, <var class="Ar">rdr</var>, + <var class="Ar">binat</var> or <var class="Ar">ether</var> rules in + addition to filter rules. Tags take the same macros as labels (see + above).</dd> + <dt><var class="Ar">tagged</var> + ⟨<var class="Ar">string</var>⟩</dt> + <dd>Used with filter, translation or scrub rules to specify that packets must + already be tagged with the given tag in order to match the rule.</dd> + <dt><var class="Ar">rtable</var> + ⟨<var class="Ar">number</var>⟩</dt> + <dd>Used to select an alternate routing table for the routing lookup. Only + effective before the route lookup happened, i.e. when filtering + inbound.</dd> + <dt><var class="Ar">divert-to</var> ⟨<var class="Ar">host</var>⟩ + <var class="Ar">port</var> ⟨<var class="Ar">port</var>⟩</dt> + <dd>Used to <a class="Xr">divert(4)</a> packets to the given divert + <var class="Ar">port</var>. Historically <span class="Ux">OpenBSD + pf</span> has another meaning for this, and <span class="Ux">FreeBSD + pf</span> uses this syntax to support <a class="Xr">divert(4)</a> instead. + Hence, <var class="Ar">host</var> has no meaning and can be set to + anything like 127.0.0.1. If a packet is re-injected and does not change + direction then it will not be re-diverted.</dd> + <dt><var class="Ar">divert-reply</var></dt> + <dd>It has no meaning in <span class="Ux">FreeBSD pf</span>.</dd> + <dt><var class="Ar">probability</var> + ⟨<var class="Ar">number</var>⟩</dt> + <dd>A probability attribute can be attached to a rule, with a value set + between 0 and 1, bounds not included. In that case, the rule will be + honoured using the given probability value only. For example, the + following rule will drop 20% of incoming ICMP packets: + <div class="Bd Pp Bd-indent Li"> + <pre>block in proto icmp probability 20%</pre> + </div> + </dd> + <dt id="state"><a class="permalink" href="#state"><code class="Cm">state + limiter</code></a> <var class="Ar">name</var> [<code class="Cm">(limiter + options)</code>]</dt> + <dd>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 <code class="Ic">no-match</code> option to + change default behavior such rule is ignored and ruleset evaluation + continues with next rule. See the + <a class="Sx" href="#State_Limiters">State Limiters</a> section for more + information.</dd> + <dt id="source"><a class="permalink" href="#source"><code class="Cm">source + limiter</code></a> <var class="Ar">name</var> [<code class="Cm">(limiter + options)</code>]</dt> + <dd>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 <code class="Ic">no-match</code> + option to change default behavior such rule is ignored and ruleset + evaluation continues with next rule. See the + <a class="Sx" href="#Source_Limiters">Source Limiters</a> section for more + information.</dd> + <dt><var class="Ar">prio</var> + ⟨<var class="Ar">number</var>⟩</dt> + <dd>Only match packets which have the given queueing priority assigned.</dd> +</dl> +</section> +</section> +<section class="Sh"> +<h1 class="Sh" id="ROUTING"><a class="permalink" href="#ROUTING">ROUTING</a></h1> +<p class="Pp">If a packet matches a rule with a route option set, the packet + filter will route the packet according to the type of route option. When + such a rule creates state, the route option is also applied to all packets + matching the same connection.</p> +<dl class="Bl-tag"> + <dt><var class="Ar">route-to</var></dt> + <dd>The <var class="Ar">route-to</var> option routes the packet to the + specified interface with an address for the next hop. When a + <var class="Ar">route-to</var> 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.</dd> + <dt><var class="Ar">reply-to</var></dt> + <dd>The <var class="Ar">reply-to</var> option is similar to + <var class="Ar">route-to</var>, but routes packets that pass in the + opposite direction (replies) to the specified interface. Opposite + direction is only defined in the context of a state entry, and + <var class="Ar">reply-to</var> is useful only in rules that create state. + It can be used on systems with multiple external connections to route all + outgoing packets of a connection through the interface the incoming + connection arrived through (symmetric routing enforcement).</dd> + <dt><var class="Ar">dup-to</var></dt> + <dd>The <var class="Ar">dup-to</var> option creates a duplicate of the packet + and routes it like <var class="Ar">route-to</var>. The original packet + gets routed as it normally would.</dd> +</dl> +<p class="Pp">Unlike the kernel's normal forwarding path, the route option + forwarding path does not drop broadcast or multicast traffic when the output + interface has been overridden by a route option. If a + <var class="Ar">route-to</var>, <var class="Ar">reply-to</var>, or + <var class="Ar">dup-to</var> rule matches traffic destined to a broadcast + address (either the limited broadcast or a subnet-directed broadcast) or to + an IPv4/IPv6 multicast address, the packet is forwarded out the specified + interface, which may cross broadcast domains.</p> +<p class="Pp">Rulesets that use <var class="Ar">route-to</var>, + <var class="Ar">reply-to</var>, or <var class="Ar">dup-to</var> with a + permissive destination (e.g. <code class="Li">from any to any</code>) can + plug this leak with explicit <var class="Ar">block out</var> rules on the + route option's target interface. To avoid blocking the router's own + broadcast or multicast traffic, scope the block rules to forwarded packets + with the <var class="Ar">received-on any</var> qualifier. For example, + assuming <code class="Li">$wan</code> is the <var class="Ar">route-to</var> + target interface:</p> +<div class="Bd Pp Bd-indent Li"> +<pre>block out quick on $wan inet from any to 255.255.255.255 received-on any +block out quick on $wan inet from any to ($wan:broadcast) received-on any +block out quick on $wan inet from any to 224.0.0.0/4 received-on any +block out quick on $wan inet6 from any to ff00::/8 received-on any</pre> +</div> +<p class="Pp">One block-out rule set is needed per interface that may be used as + a route option target.</p> +</section> +<section class="Sh"> +<h1 class="Sh" id="POOL_OPTIONS"><a class="permalink" href="#POOL_OPTIONS">POOL + OPTIONS</a></h1> +<p class="Pp">For <var class="Ar">nat</var> and <var class="Ar">rdr</var> rules, + (as well as for the <var class="Ar">route-to</var>, + <var class="Ar">reply-to</var> and <var class="Ar">dup-to</var> rule + options) for which there is a single redirection address which has a subnet + mask smaller than 32 for IPv4 or 128 for IPv6 (more than one IP address), a + variety of different methods for assigning this address can be used:</p> +<dl class="Bl-tag"> + <dt><var class="Ar">bitmask</var></dt> + <dd>The <var class="Ar">bitmask</var> option applies the network portion of + the redirection address to the address to be modified (source with + <var class="Ar">nat</var>, destination with + <var class="Ar">rdr</var>).</dd> + <dt><var class="Ar">random</var></dt> + <dd>The <var class="Ar">random</var> option selects an address at random + within the defined block of addresses.</dd> + <dt><var class="Ar">source-hash</var></dt> + <dd>The <var class="Ar">source-hash</var> option uses a hash of the source + address to determine the redirection address, ensuring that the + redirection address is always the same for a given source. An optional key + can be specified after this keyword either in hex or as a string; by + default <a class="Xr">pfctl(8)</a> randomly generates a key for + source-hash every time the ruleset is reloaded.</dd> + <dt><var class="Ar">round-robin</var></dt> + <dd>The <var class="Ar">round-robin</var> option loops through the redirection + address(es). + <p class="Pp">When more than one redirection address is specified, + <var class="Ar">bitmask</var> is not permitted as a pool type.</p> + </dd> + <dt><var class="Ar">static-port</var></dt> + <dd>With <var class="Ar">nat</var> rules, the + <var class="Ar">static-port</var> option prevents <a class="Xr">pf(4)</a> + from modifying the source port on TCP and UDP packets.</dd> + <dt><var class="Ar">map-e-portset</var> + ⟨<var class="Ar">psid-offset</var>⟩ <span class="No">/</span> + ⟨<var class="Ar">psid-len</var>⟩ <span class="No">/</span> + ⟨<var class="Ar">psid</var>⟩</dt> + <dd>With <var class="Ar">nat</var> rules, the + <var class="Ar">map-e-portset</var> option enables the source port + translation of MAP-E (RFC 7597) Customer Edge. In order to make the host + act as a MAP-E Customer Edge, setting up a tunneling interface and pass + rules for encapsulated packets are required in addition to the + map-e-portset nat rule. + <p class="Pp">For example:</p> + <div class="Bd Pp Bd-indent Li"> + <pre>nat on $gif_mape_if from $int_if:network to any \ + -> $ipv4_mape_src map-e-portset 6/8/0x34</pre> + </div> + <p class="Pp">sets PSID offset 6, PSID length 8, PSID 0x34.</p> + </dd> + <dt><var class="Ar">endpoint-independent</var></dt> + <dd>With <var class="Ar">nat</var> rules, the + <var class="Ar">endpoint-independent</var> option caues + <a class="Xr">pf(4)</a> to always map connections from a UDP source + address and port to the same NAT address and port. This feature implements + "full-cone" NAT behavior.</dd> +</dl> +<p class="Pp">Additionally, options <var class="Ar">sticky-address</var> and + <var class="Ar">prefer-ipv6-nexthop</var> can be specified to influence how + IP addresses selected from pools.</p> +<p class="Pp">The <var class="Ar">sticky-address</var> option can be specified + to help ensure that multiple connections from the same source are mapped to + the same redirection address. This option can be used with the + <var class="Ar">random</var> and <var class="Ar">round-robin</var> pool + options. Note that by default these associations are destroyed as soon as + there are no longer states which refer to them; in order to make the + mappings last beyond the lifetime of the states, increase the global options + with <var class="Ar">set timeout src.track</var>. See + <a class="Sx" href="#STATEFUL_TRACKING_OPTIONS">STATEFUL TRACKING + OPTIONS</a> for more ways to control the source tracking.</p> +<p class="Pp">The <var class="Ar">prefer-ipv6-nexthop</var> option allows for + IPv6 addresses to be used as the nexthop for IPv4 packets routed with the + <var class="Ar">route-to</var> rule option. If a table is used with IPv4 and + IPv6 addresses, first the IPv6 addresses will be used in round-robin + fashion, then IPv4 addresses.</p> +</section> +<section class="Sh"> +<h1 class="Sh" id="STATE_MODULATION"><a class="permalink" href="#STATE_MODULATION">STATE + MODULATION</a></h1> +<p class="Pp">Much of the security derived from TCP is attributable to how well + the initial sequence numbers (ISNs) are chosen. Some popular stack + implementations choose + <a class="permalink" href="#very"><i class="Em" id="very">very</i></a> poor + ISNs and thus are normally susceptible to ISN prediction exploits. By + applying a <var class="Ar">modulate state</var> rule to a TCP connection, + <a class="Xr">pf(4)</a> will create a high quality random sequence number + for each connection endpoint.</p> +<p class="Pp">The <var class="Ar">modulate state</var> directive implicitly + keeps state on the rule and is only applicable to TCP connections.</p> +<p class="Pp">For instance:</p> +<div class="Bd Pp Bd-indent Li"> +<pre>block all +pass out proto tcp from any to any modulate state +pass in proto tcp from any to any port 25 flags S/SFRA modulate state</pre> +</div> +<p class="Pp">Note that modulated connections will not recover when the state + table is lost (firewall reboot, flushing the state table, etc...). + <a class="Xr">pf(4)</a> 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 <var class="Ar">flags</var> settings (or a more + strict equivalent) should be used on <var class="Ar">modulate state</var> + rules to prevent ACK storms.</p> +<p class="Pp">Note that alternative methods are available to prevent loss of the + state table and allow for firewall failover. See <a class="Xr">carp(4)</a> + and <a class="Xr">pfsync(4)</a> for further information.</p> +</section> +<section class="Sh"> +<h1 class="Sh" id="SYN_PROXY"><a class="permalink" href="#SYN_PROXY">SYN + PROXY</a></h1> +<p class="Pp">By default, <a class="Xr">pf(4)</a> passes packets that are part + of a <a class="Xr">tcp(4)</a> handshake between the endpoints. The + <var class="Ar">synproxy state</var> option can be used to cause + <a class="Xr">pf(4)</a> itself to complete the handshake with the active + endpoint, perform a handshake with the passive endpoint, and then forward + packets between the endpoints.</p> +<p class="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.</p> +<p class="Pp">The proxy is transparent to both endpoints, they each see a single + connection from/to the other endpoint. <a class="Xr">pf(4)</a> 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. <var class="Ar">synproxy + state</var> includes <var class="Ar">modulate state</var>.</p> +<p class="Pp">Rules with <var class="Ar">synproxy</var> will not work if + <a class="Xr">pf(4)</a> operates on a <a class="Xr">bridge(4)</a>. Also they + act on incoming SYN packets only.</p> +<p class="Pp">Example:</p> +<div class="Bd Pp Bd-indent Li"> +<pre>pass in proto tcp from any to any port www synproxy state</pre> +</div> +<section class="Ss"> +<h2 class="Ss" id="State_Limiters"><a class="permalink" href="#State_Limiters">State + Limiters</a></h2> +<p class="Pp">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 <code class="Cm">set limit states</code>, but the number of states + created by a subset of rules can be provided by a state limiter.</p> +<p class="Pp">A state limiter is configured with the following statement:</p> +<p class="Pp"></p> +<dl class="Bl-tag Bl-compact"> + <dt id="state~2"><a class="permalink" href="#state~2"><code class="Cm">state + limiter</code></a> <var class="Ar">name</var></dt> + <dd>Each state limiter is identified by a unique name.</dd> +</dl> +<p class="Pp">State limiters support the following configuration:</p> +<p class="Pp"></p> +<dl class="Bl-tag Bl-compact"> + <dt id="id"><a class="permalink" href="#id"><code class="Cm">id</code></a> + <var class="Ar">number</var></dt> + <dd>A unique identifier between 1 and 255. This configuration is + required.</dd> + <dt id="limit"><a class="permalink" href="#limit"><code class="Cm">limit</code></a> + <var class="Ar">number</var></dt> + <dd>Specify the maximum number of states. This configuration is required.</dd> + <dt id="rate"><a class="permalink" href="#rate"><code class="Cm">rate</code></a> + <var class="Ar">number</var>/<var class="Ar">seconds</var></dt> + <dd>Limit the rate at which states can be created over a time interval. The + connection rate is an approximation calculated as a moving average.</dd> +</dl> +<p class="Pp">Pass rules can specify a state limiter using the + <code class="Cm">state limiter</code> <var class="Ar">name</var> option. If + the number of states allowed has hit the limit, the pass rule does not match + and ruleset evaluation continues past it.</p> +<p class="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:</p> +<p class="Pp"></p> +<div class="Bd Bd-indent Li"> +<pre>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"</pre> +</div> +</section> +<section class="Ss"> +<h2 class="Ss" id="Source_Limiters"><a class="permalink" href="#Source_Limiters">Source + Limiters</a></h2> +<p class="Pp">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 <code class="Cm">set limit + states</code>, but limits on states for a subset of source addresses and + rules can be provided with source limiters.</p> +<p class="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.</p> +<p class="Pp">A source limiter is configured with the following statement:</p> +<p class="Pp"></p> +<dl class="Bl-tag Bl-compact"> + <dt id="source~2"><a class="permalink" href="#source~2"><code class="Cm">source + limiter</code></a> <var class="Ar">name</var></dt> + <dd>Each source limiter is uniquely identified by the specified name.</dd> +</dl> +<p class="Pp">Source limiter support the following configuration:</p> +<p class="Pp"></p> +<dl class="Bl-tag Bl-compact"> + <dt id="id~2"><a class="permalink" href="#id~2"><code class="Cm">id</code></a> + <var class="Ar">number</var></dt> + <dd>A unique identifier between 1 and 255. This configuration is + required.</dd> + <dt id="entries"><a class="permalink" href="#entries"><code class="Cm">entries</code></a> + <var class="Ar">number</var></dt> + <dd>Specify the maximum number of source address entries. This configuration + is required.</dd> + <dt id="limit~2"><a class="permalink" href="#limit~2"><code class="Cm">limit</code></a> + <var class="Ar">number</var></dt> + <dd>Specify the maximum number of states for each source address entry. This + configuration is required.</dd> + <dt id="rate~2"><a class="permalink" href="#rate~2"><code class="Cm">rate</code></a> + <var class="Ar">number</var>/<var class="Ar">seconds</var></dt> + <dd>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.</dd> + <dt id="inet"><a class="permalink" href="#inet"><code class="Cm">inet + mask</code></a> <var class="Ar">prefixlen</var></dt> + <dd>Mask IPv4 source addresses using the prefix length specified with + <var class="Ar">prefixlen</var> when creating an address entry. The + default IPv4 prefix length is 32 bits.</dd> + <dt id="inet6"><a class="permalink" href="#inet6"><code class="Cm">inet6 + mask</code></a> <var class="Ar">prefixlen</var></dt> + <dd>Mask IPv6 source addresses using the prefix length specified with + <var class="Ar">prefixlen</var> when creating an address entry. The + default IPv6 prefix length is 128 bits.</dd> + <dt id="table"><a class="permalink" href="#table"><code class="Cm">table + <</code></a><var class="Ar">table</var>> <code class="Cm">above</code> + <var class="Ar">hwm</var> [<code class="Cm">below</code> + <var class="Ar">lwm</var>]</dt> + <dd>Add the address to the specified <var class="Ar">table</var> when the + number of states goes above the <var class="Ar">hwm</var> high water mark. + The address will be removed from the table when the number of states drops + below the <var class="Ar">lwm</var> low water mark. The default low water + mark is 0.</dd> +</dl> +<p class="Pp">Pass rules can specify a source limiter using the + <code class="Cm">source limiter</code> <var class="Ar">name</var> + option.</p> +<p class="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:</p> +<p class="Pp"></p> +<div class="Bd Bd-indent Li"> +<pre>source limiter "internet" id 1 entries 10000 \ + limit 1000 rate 100/10 \ + inet6 mask 64 + +block in on egress +pass in on egress source limiter "internet"</pre> +</div> +</section> +</section> +<section class="Sh"> +<h1 class="Sh" id="STATEFUL_TRACKING_OPTIONS"><a class="permalink" href="#STATEFUL_TRACKING_OPTIONS">STATEFUL + TRACKING OPTIONS</a></h1> +<p class="Pp">A number of options related to stateful tracking can be applied on + a per-rule basis. <var class="Ar">keep state</var>, <var class="Ar">modulate + state</var> and <var class="Ar">synproxy state</var> support these options, + and <var class="Ar">keep state</var> must be specified explicitly to apply + options to a rule.</p> +<p class="Pp"></p> +<dl class="Bl-tag Bl-compact"> + <dt><var class="Ar">max</var> + ⟨<var class="Ar">number</var>⟩</dt> + <dd>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.</dd> + <dt><var class="Ar">no-sync</var></dt> + <dd>Prevent state changes for states created by this rule from appearing on + the <a class="Xr">pfsync(4)</a> interface.</dd> + <dt>⟨<var class="Ar">timeout</var>⟩ + ⟨<var class="Ar">seconds</var>⟩</dt> + <dd>Changes the timeout values used for states created by this rule. For a + list of all valid timeout names, see + <a class="Sx" href="#OPTIONS">OPTIONS</a> above.</dd> + <dt><var class="Ar">sloppy</var></dt> + <dd>Uses a sloppy TCP connection tracker that does not check sequence numbers + at all, which makes insertion and ICMP teardown attacks way easier. This + is intended to be used in situations where one does not see all packets of + a connection, e.g. in asymmetric routing situations. Cannot be used with + modulate or synproxy state.</dd> + <dt><var class="Ar">pflow</var></dt> + <dd>States created by this rule are exported on the <a class="Xr">pflow(4)</a> + interface.</dd> + <dt><var class="Ar">allow-related</var></dt> + <dd>Automatically allow connections related to this one, regardless of rules + that might otherwise affect them. This currently only applies to SCTP + multihomed connection.</dd> +</dl> +<p class="Pp">Multiple options can be specified, separated by commas:</p> +<div class="Bd Pp Bd-indent Li"> +<pre>pass in proto tcp from any to any \ + port www keep state \ + (max 100, source-track rule, max-src-nodes 75, \ + max-src-states 3, tcp.established 60, tcp.closing 5)</pre> +</div> +<p class="Pp">When the <var class="Ar">source-track</var> keyword is specified, + the number of states per source IP is tracked.</p> +<p class="Pp"></p> +<dl class="Bl-tag Bl-compact"> + <dt><var class="Ar">source-track rule</var></dt> + <dd>The maximum number of states created by this rule is limited by the rule's + <var class="Ar">max-src-nodes</var> and + <var class="Ar">max-src-states</var> options. Only state entries created + by this particular rule count toward the rule's limits.</dd> + <dt><var class="Ar">source-track global</var></dt> + <dd>The number of states created by all rules that use this option is limited. + Each rule can specify different <var class="Ar">max-src-nodes</var> and + <var class="Ar">max-src-states</var> options, however state entries + created by any participating rule count towards each individual rule's + limits.</dd> +</dl> +<p class="Pp">The following limits can be set:</p> +<p class="Pp"></p> +<dl class="Bl-tag Bl-compact"> + <dt><var class="Ar">max-src-nodes</var> + ⟨<var class="Ar">number</var>⟩</dt> + <dd>Limits the maximum number of source addresses which can simultaneously + have state table entries.</dd> + <dt><var class="Ar">max-src-states</var> + ⟨<var class="Ar">number</var>⟩</dt> + <dd>Limits the maximum number of simultaneous state entries that a single + source address can create with this rule.</dd> +</dl> +<p class="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.</p> +<p class="Pp"></p> +<dl class="Bl-tag Bl-compact"> + <dt><var class="Ar">max-src-conn</var> + ⟨<var class="Ar">number</var>⟩</dt> + <dd>Limits the maximum number of simultaneous TCP connections which have + completed the 3-way handshake that a single host can make.</dd> + <dt><var class="Ar">max-src-conn-rate</var> + ⟨<var class="Ar">number</var>⟩ <span class="No">/</span> + ⟨<var class="Ar">seconds</var>⟩</dt> + <dd>Limit the rate of new connections over a time interval. The connection + rate is an approximation calculated as a moving average.</dd> +</dl> +<p class="Pp">When one of these limits is reached, further packets that would + create state are dropped until existing states time out.</p> +<p class="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 <var class="Ar">overload</var> + ⟨<var class="Ar">table</var>⟩ state option, source IP + addresses which hit either of the limits on established connections will be + added to the named table. This table can be used in the ruleset to block + further activity from the offending host, redirect it to a tarpit process, + or restrict its bandwidth.</p> +<p class="Pp">The optional <var class="Ar">flush</var> keyword kills all states + created by the matching rule which originate from the host which exceeds + these limits. The <var class="Ar">global</var> modifier to the flush command + kills all states originating from the offending host, regardless of which + rule created the state.</p> +<p class="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.</p> +<div class="Bd Pp Bd-indent Li"> +<pre>block quick from <bad_hosts> +pass in on $ext_if proto tcp to $webserver port www keep state \ + (max-src-conn-rate 100/10, overload <bad_hosts> flush global)</pre> +</div> +</section> +<section class="Sh"> +<h1 class="Sh" id="OPERATING_SYSTEM_FINGERPRINTING"><a class="permalink" href="#OPERATING_SYSTEM_FINGERPRINTING">OPERATING + SYSTEM FINGERPRINTING</a></h1> +<p class="Pp">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.</p> +<p class="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 <span class="Ux">OpenBSD</span> + for the <a class="Xr">pf(4)</a> firewall itself. The version of the oldest + available <span class="Ux">OpenBSD</span> release on the main FTP site would + be 2.6 and the fingerprint would be written</p> +<p class="Pp"></p> +<div class="Bd Bd-indent"><code class="Li">"OpenBSD 2.6"</code></div> +<p class="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 <span class="Ux">OpenBSD</span>, the only subtype is for a + fingerprint that was normalized by the <var class="Ar">no-df</var> scrub + option and would be specified as</p> +<p class="Pp"></p> +<div class="Bd Bd-indent"><code class="Li">"OpenBSD 3.3 + no-df"</code></div> +<p class="Pp">Fingerprints for most popular operating systems are provided by + <a class="Xr">pf.os(5)</a>. Once <a class="Xr">pf(4)</a> is running, a + complete list of known operating system fingerprints may be listed by + running:</p> +<p class="Pp"></p> +<div class="Bd Bd-indent"><code class="Li"># pfctl -so</code></div> +<p class="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.</p> +<p class="Pp">The <var class="Ar">unknown</var> class can also be used as the + fingerprint which will match packets for which no operating system + fingerprint is known.</p> +<p class="Pp">Examples:</p> +<div class="Bd Pp Bd-indent Li"> +<pre>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"</pre> +</div> +<p class="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.</p> +<p class="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.</p> +</section> +<section class="Sh"> +<h1 class="Sh" id="BLOCKING_SPOOFED_TRAFFIC"><a class="permalink" href="#BLOCKING_SPOOFED_TRAFFIC">BLOCKING + SPOOFED TRAFFIC</a></h1> +<p class="Pp">"Spoofing" is the faking of IP addresses, typically for + malicious purposes. The <var class="Ar">antispoof</var> 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.</p> +<p class="Pp">For example, the line</p> +<div class="Bd Pp Bd-indent Li"> +<pre>antispoof for lo0</pre> +</div> +<p class="Pp">expands to</p> +<div class="Bd Pp Bd-indent Li"> +<pre>block drop in on ! lo0 inet from 127.0.0.1/8 to any +block drop in on ! lo0 inet6 from ::1 to any</pre> +</div> +<p class="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, the line</p> +<div class="Bd Pp Bd-indent Li"> +<pre>antispoof for wi0 inet</pre> +</div> +<p class="Pp">expands to</p> +<div class="Bd Pp Bd-indent Li"> +<pre>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</pre> +</div> +<p class="Pp">Caveat: Rules created by the <var class="Ar">antispoof</var> + directive interfere with packets sent over loopback interfaces to local + addresses. One should pass these explicitly.</p> +</section> +<section class="Sh"> +<h1 class="Sh" id="FRAGMENT_HANDLING"><a class="permalink" href="#FRAGMENT_HANDLING">FRAGMENT + HANDLING</a></h1> +<p class="Pp">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 <a class="Xr">pf(4)</a> to filter on things such as TCP ports or + to perform NAT.</p> +<p class="Pp">Besides the use of <var class="Ar">set reassemble</var> option or + <var class="Ar">scrub</var> rules as described in + <a class="Sx" href="#TRAFFIC_NORMALIZATION">TRAFFIC NORMALIZATION</a> above, + there are three options for handling fragments in the packet filter.</p> +<p class="Pp">One alternative is to filter individual fragments with filter + rules. If no <var class="Ar">scrub</var> rule applies to a fragment or + <var class="Ar">set reassemble</var> is set to <code class="Cm">no</code> , + 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 <var class="Ar">fragment</var> option can be used to + restrict filter rules to apply only to fragments, but not complete packets. + Filter rules without the <var class="Ar">fragment</var> option still apply + to fragments, if they only specify IP header fields. For instance, the + rule</p> +<div class="Bd Pp Bd-indent Li"> +<pre>pass in proto tcp from any to any port 80</pre> +</div> +<p class="Pp">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.</p> +<p class="Pp">It's also possible to reassemble only certain fragments by + specifying source or destination addresses or protocols as parameters in + <var class="Ar">scrub</var> rules.</p> +<p class="Pp">In most cases, the benefits of reassembly outweigh the additional + memory cost, and it's recommended to use <var class="Ar">set + reassemble</var> option or <var class="Ar">scrub</var> rules with the + <var class="Ar">fragment reassemble</var> modifier to reassemble all + fragments.</p> +<p class="Pp">The memory allocated for fragment caching can be limited using + <a class="Xr">pfctl(8)</a>. 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.</p> +<p class="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.</p> +</section> +<section class="Sh"> +<h1 class="Sh" id="ANCHORS"><a class="permalink" href="#ANCHORS">ANCHORS</a></h1> +<p class="Pp">Besides the main ruleset, <a class="Xr">pfctl(8)</a> can load + rulesets into <var class="Ar">anchor</var> attachment points. An + <var class="Ar">anchor</var> is a container that can hold rules, address + tables, and other anchors.</p> +<p class="Pp">An <var class="Ar">anchor</var> has a name which specifies the + path where <a class="Xr">pfctl(8)</a> 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 + ‘/’ 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.</p> +<p class="Pp">An anchor can reference another <var class="Ar">anchor</var> + attachment point using the following kinds of rules:</p> +<dl class="Bl-tag"> + <dt><var class="Ar">nat-anchor</var> + ⟨<var class="Ar">name</var>⟩</dt> + <dd>Evaluates the <var class="Ar">nat</var> rules in the specified + <var class="Ar">anchor</var>.</dd> + <dt><var class="Ar">rdr-anchor</var> + ⟨<var class="Ar">name</var>⟩</dt> + <dd>Evaluates the <var class="Ar">rdr</var> rules in the specified + <var class="Ar">anchor</var>.</dd> + <dt><var class="Ar">binat-anchor</var> + ⟨<var class="Ar">name</var>⟩</dt> + <dd>Evaluates the <var class="Ar">binat</var> rules in the specified + <var class="Ar">anchor</var>.</dd> + <dt><var class="Ar">anchor</var> + ⟨<var class="Ar">name</var>⟩</dt> + <dd>Evaluates the filter rules in the specified + <var class="Ar">anchor</var>.</dd> + <dt><var class="Ar">load anchor</var> + ⟨<var class="Ar">name</var>⟩ <var class="Ar">from</var> + ⟨<var class="Ar">file</var>⟩</dt> + <dd>Loads the rules from the specified file into the anchor + <var class="Ar">name</var>.</dd> +</dl> +<p class="Pp">When evaluation of the main ruleset reaches an + <var class="Ar">anchor</var> rule, <a class="Xr">pf(4)</a> will proceed to + evaluate all rules specified in that anchor.</p> +<p class="Pp">Matching filter and translation rules marked with the + <var class="Ar">quick</var> option are final and abort the evaluation of the + rules in other anchors and the main ruleset. If the + <var class="Ar">anchor</var> itself is marked with the + <var class="Ar">quick</var> option, ruleset evaluation will terminate when + the anchor is exited if the packet is matched by any rule within the + anchor.</p> +<p class="Pp"><var class="Ar">anchor</var> rules are evaluated relative to the + anchor in which they are contained. For example, all + <var class="Ar">anchor</var> rules specified in the main ruleset will + reference anchor attachment points underneath the main ruleset, and + <var class="Ar">anchor</var> rules specified in a file loaded from a + <var class="Ar">load anchor</var> rule will be attached under that anchor + point.</p> +<p class="Pp">Rules may be contained in <var class="Ar">anchor</var> attachment + points which do not contain any rules when the main ruleset is loaded, and + later such anchors can be manipulated through <a class="Xr">pfctl(8)</a> + without reloading the main ruleset or other anchors. For example,</p> +<div class="Bd Pp Bd-indent Li"> +<pre>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</pre> +</div> +<p class="Pp">blocks all packets on the external interface by default, then + evaluates all rules in the <var class="Ar">anchor</var> named + "spam", and finally passes all outgoing connections and incoming + connections to port 25.</p> +<div class="Bd Pp Bd-indent Li"> +<pre># echo "block in quick from 1.2.3.4 to any" | \ + pfctl -a spam -f -</pre> +</div> +<p class="Pp">This loads a single rule into the <var class="Ar">anchor</var>, + which blocks all packets from a specific address.</p> +<p class="Pp">The anchor can also be populated by adding a <var class="Ar">load + anchor</var> rule after the <var class="Ar">anchor</var> rule:</p> +<div class="Bd Pp Bd-indent Li"> +<pre>anchor spam +load anchor spam from "/etc/pf-spam.conf"</pre> +</div> +<p class="Pp">When <a class="Xr">pfctl(8)</a> loads + <code class="Nm">pf.conf</code>, it will also load all the rules from the + file <span class="Pa">/etc/pf-spam.conf</span> into the anchor.</p> +<p class="Pp">Optionally, <var class="Ar">anchor</var> rules can specify packet + filtering parameters using the same syntax as filter rules. When parameters + are used, the <var class="Ar">anchor</var> rule is only evaluated for + matching packets. This allows conditional evaluation of anchors, like:</p> +<div class="Bd Pp Bd-indent Li"> +<pre>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</pre> +</div> +<p class="Pp">The rules inside <var class="Ar">anchor</var> spam are only + evaluated for <var class="Ar">tcp</var> packets with destination port 25. + Hence,</p> +<div class="Bd Pp Bd-indent Li"> +<pre># echo "block in quick from 1.2.3.4 to any" | \ + pfctl -a spam -f -</pre> +</div> +<p class="Pp">will only block connections from 1.2.3.4 to port 25.</p> +<p class="Pp">Anchors may end with the asterisk (‘*’) character, + which signifies that all anchors attached at that point should be evaluated + in the alphabetical ordering of their anchor name. For example,</p> +<div class="Bd Pp Bd-indent Li"> +<pre>anchor "spam/*"</pre> +</div> +<p class="Pp">will evaluate each rule in each anchor attached to the + <code class="Li">spam</code> anchor. Note that it will only evaluate anchors + that are directly attached to the <code class="Li">spam</code> anchor, and + will not descend to evaluate anchors recursively.</p> +<p class="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 “..” 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:</p> +<div class="Bd Pp Bd-indent Li"> +<pre># echo ' anchor "spam/allowed" ' | pfctl -f - +# echo -e ' anchor "../banned" \n pass' | \ + pfctl -a spam/allowed -f -</pre> +</div> +<p class="Pp">Evaluation of the main ruleset will lead into the + <code class="Li">spam/allowed</code> anchor, which will evaluate the rules + in the <code class="Li">spam/banned</code> anchor, if any, before finally + evaluating the <var class="Ar">pass</var> rule.</p> +<p class="Pp">An <var class="Ar">anchor</var> 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.</p> +<div class="Bd Pp Bd-indent Li"> +<pre>anchor "external" on $ext_if { + block + anchor out { + pass proto tcp from any to port { 25, 80, 443 } + } + pass in proto tcp to any port 22 +}</pre> +</div> +<p class="Pp">Since the parser specification for anchor names is a string, any + reference to an anchor name containing ‘/’ characters will + require double quote (‘"’) characters around the anchor + name.</p> +</section> +<section class="Sh"> +<h1 class="Sh" id="SCTP_CONSIDERATIONS"><a class="permalink" href="#SCTP_CONSIDERATIONS">SCTP + CONSIDERATIONS</a></h1> +<p class="Pp"><a class="Xr">pf(4)</a> supports <a class="Xr">sctp(4)</a> + connections. It can match ports, track state and NAT SCTP traffic. However, + it will not alter port numbers during nat or rdr translations. Doing so + would break SCTP multihoming.</p> +</section> +<section class="Sh"> +<h1 class="Sh" id="TRANSLATION_EXAMPLES"><a class="permalink" href="#TRANSLATION_EXAMPLES">TRANSLATION + EXAMPLES</a></h1> +<p class="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).</p> +<div class="Bd Pp Bd-indent Li"> +<pre># use a macro for the interface name, so it can be changed easily +ext_if = "ne3" + +# map daemon on 8080 to appear to be on 80 +match in on $ext_if proto tcp from any to any port 80 \ + rdr-to 127.0.0.1 port 8080</pre> +</div> +<p class="Pp">If a <var class="Ar">pass</var> rule is used with the + <var class="Ar">quick</var> modifier, packets matching the translation rule + are passed without inspecting subsequent filter rules:</p> +<div class="Bd Pp Bd-indent Li"> +<pre>pass in quick on $ext_if proto tcp from any to any port 80 \ + rdr-to 127.0.0.1 port 8080</pre> +</div> +<p class="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.)</p> +<div class="Bd Pp Bd-indent Li"> +<pre>match out on ! vlan12 from 192.168.168.0/24 to any nat-to 204.92.77.111</pre> +</div> +<p class="Pp">This longer example uses both a NAT and a redirection. The + external interface has the address 157.161.48.183. On localhost, we are + running <a class="Xr">ftp-proxy(8)</a>, waiting for FTP sessions to be + redirected to it. The three mandatory anchors for + <a class="Xr">ftp-proxy(8)</a> are omitted from this example; see the + <a class="Xr">ftp-proxy(8)</a> manpage.</p> +<div class="Bd Pp Bd-indent Li"> +<pre># NAT +# Translate outgoing packets' source addresses (any protocol). +# In this case, any address but the gateway's external address is mapped. +pass out on $ext_if inet from ! ($ext_if) to any nat-to ($ext_if) + +# NAT PROXYING +# Map outgoing packets' source port to an assigned proxy port instead of +# an arbitrary port. +# In this case, proxy outgoing isakmp with port 500 on the gateway. +pass out on $ext_if inet proto udp from any port = isakmp to any \ + nat-to ($ext_if) port 500 + +# BINAT +# Translate outgoing packets' source address (any protocol). +# Translate incoming packets' destination address to an internal machine +# (bidirectional). +pass on $ext_if from 10.1.2.150 to any binat-to $ext_if + +# Translate packets arriving on $peer_if addressed to 172.22.16.0/20 +# to the corresponding address in 172.21.16.0/20 (bidirectional). +pass on $peer_if from 172.21.16.0/20 to any binat-to 172.22.16.0/20 + +# RDR +# Translate incoming packets' destination addresses. +# As an example, redirect a TCP and UDP port to an internal machine. +pass in on $ext_if inet proto tcp from any to ($ext_if) port 8080 \ + rdr-to 10.1.2.151 port 22 +pass in on $ext_if inet proto udp from any to ($ext_if) port 8080 \ + rdr-to 10.1.2.151 port 53 + +# RDR +# Translate outgoing ftp control connections to send them to localhost +# for proxying with ftp-proxy(8) running on port 8021. +pass in on $int_if proto tcp from any to any port 21 \ + rdr-to 127.0.0.1 port 8021</pre> +</div> +<p class="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) and to redirect + incoming web server connections to a group of web servers on the internal + network.</p> +<div class="Bd Pp Bd-indent Li"> +<pre># NAT LOAD BALANCE +# Translate outgoing packets' source addresses using an address pool. +# A given source address is always translated to the same pool address by +# using the source-hash keyword. +pass out on $ext_if inet from any to any nat-to 192.0.2.16/28 source-hash + +# RDR ROUND ROBIN +# Translate incoming web server connections to a group of web servers on +# the internal network. +pass in on $ext_if proto tcp from any to any port 80 \ + rdr-to { 10.1.2.155, 10.1.2.160, 10.1.2.161 } round-robin</pre> +</div> +</section> +<section class="Sh"> +<h1 class="Sh" id="COMPATIBILITY_TRANSLATION_EXAMPLES"><a class="permalink" href="#COMPATIBILITY_TRANSLATION_EXAMPLES">COMPATIBILITY + TRANSLATION EXAMPLES</a></h1> +<p class="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 + <var class="Ar">no nat</var> rule excludes protocol AH from being + translated.</p> +<div class="Bd Pp Bd-indent Li"> +<pre># NAT +no nat on $ext_if proto ah from 144.19.74.0/24 to any +nat on $ext_if from 144.19.74.0/24 to any -> 204.92.77.100</pre> +</div> +<p class="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.</p> +<div class="Bd Pp Bd-indent Li"> +<pre># RDR +no rdr on $int_if proto { tcp, udp } from any to $server port 80 +no rdr on $int_if proto { tcp, udp } from $sysadmins to any port 80 +rdr on $int_if proto { tcp, udp } from any to any port 80 \ + -> 127.0.0.1 port 80</pre> +</div> +</section> +<section class="Sh"> +<h1 class="Sh" id="FILTER_EXAMPLES"><a class="permalink" href="#FILTER_EXAMPLES">FILTER + EXAMPLES</a></h1> +<div class="Bd Bd-indent Li"> +<pre># The external interface is kue0 +# (157.161.48.183, the only routable address) +# and the private network is 10.0.0.0/8, for which we are doing NAT. + +# Reassemble incoming traffic +set reassemble yes + +# use a macro for the interface name, so it can be changed easily +ext_if = "kue0" + +# block and log everything by default +block return log on $ext_if all + +# block anything coming from source we have no back routes for +block in from no-route to any + +# block packets whose ingress interface does not match the one in +# the route back to their source address +block in from urpf-failed to any + +# block and log outgoing packets that do not have our address as source, +# they are either spoofed or something is misconfigured (NAT disabled, +# for instance), we want to be nice and do not send out garbage. +block out log quick on $ext_if from ! 157.161.48.183 to any + +# silently drop broadcasts (cable modem noise) +block in quick on $ext_if from any to 255.255.255.255 + +# block and log incoming packets from reserved address space and invalid +# addresses, they are either spoofed or misconfigured, we cannot reply to +# them anyway (hence, no return-rst). +block in log quick on $ext_if from { 10.0.0.0/8, 172.16.0.0/12, \ + 192.168.0.0/16, 255.255.255.255/32 } to any + +# ICMP + +# pass out/in certain ICMP queries and keep state (ping) +# state matching is done on host addresses and ICMP id (not type/code), +# so replies (like 0/0 for 8/0) will match queries +# ICMP error messages (which always refer to a TCP/UDP packet) are +# handled by the TCP/UDP states +pass on $ext_if inet proto icmp all icmp-type 8 code 0 + +# UDP + +# pass out all UDP connections and keep state +pass out on $ext_if proto udp all + +# pass in certain UDP connections and keep state (DNS) +pass in on $ext_if proto udp from any to any port domain + +# TCP + +# pass out all TCP connections and modulate state +pass out on $ext_if proto tcp all modulate state + +# pass in certain TCP connections and keep state (SSH, SMTP, DNS, IDENT) +pass in on $ext_if proto tcp from any to any port { ssh, smtp, domain, \ + auth } + +# Do not allow Windows 9x SMTP connections since they are typically +# a viral worm. Alternately we could limit these OSes to 1 connection each. +block in on $ext_if proto tcp from any os {"Windows 95", "Windows 98"} \ + to any port smtp + +# IPv6 +# pass in/out all IPv6 traffic: note that we have to enable this in two +# different ways, on both our physical interface and our tunnel +pass quick on gif0 inet6 +pass quick on $ext_if proto ipv6 + +# Packet Tagging + +# three interfaces: $int_if, $ext_if, and $wifi_if (wireless). NAT is +# being done on $ext_if for all outgoing packets. tag packets in on +# $int_if and pass those tagged packets out on $ext_if. all other +# outgoing packets (i.e., packets from the wireless network) are only +# permitted to access port 80. + +pass in on $int_if from any to any tag INTNET +pass in on $wifi_if from any to any + +block out on $ext_if from any to any +pass out quick on $ext_if tagged INTNET +pass out on $ext_if proto tcp from any to any port 80 + +# tag incoming packets as they are redirected to spamd(8). use the tag +# to pass those packets through the packet filter. + +rdr on $ext_if inet proto tcp from <spammers> to port smtp \ + tag SPAMD -> 127.0.0.1 port spamd + +block in on $ext_if +pass in on $ext_if inet proto tcp tagged SPAMD</pre> +</div> +<p class="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:</p> +<div class="Bd Pp Bd-indent Li"> +<pre>pass in on $v4_if inet af-to inet6 from ($v6_if) to 64:ff9b::/96</pre> +</div> +<p class="Pp">Paired with the example above, the example below can be used on + another router handling both address families to translate back to IPv4:</p> +<div class="Bd Pp Bd-indent Li"> +<pre>pass in on $v6_if inet6 to 64:ff9b::/96 af-to inet from ($v4_if)</pre> +</div> +</section> +<section class="Sh"> +<h1 class="Sh" id="GRAMMAR"><a class="permalink" href="#GRAMMAR">GRAMMAR</a></h1> +<p class="Pp">Syntax for <code class="Nm">pf.conf</code> in BNF:</p> +<div class="Bd Pp Li"> +<pre>line = ( option | ether-rule | pf-rule | nat-rule | binat-rule | + rdr-rule | antispoof-rule | altq-rule | queue-rule | + trans-anchors | anchor-rule | anchor-close | load-anchor | + table-rule | include ) + +option = "set" ( [ "timeout" ( timeout | "{" timeout-list "}" ) ] | + [ "ruleset-optimization" [ "none" | "basic" | "profile" ]] | + [ "optimization" [ "default" | "normal" | + "high-latency" | "satellite" | + "aggressive" | "conservative" ] ] + [ "limit" ( limit-item | "{" limit-list "}" ) ] | + [ "loginterface" ( interface-name | "none" ) ] | + [ "block-policy" ( "drop" | "return" ) ] | + [ "state-policy" ( "if-bound" | "floating" ) ] + [ "state-defaults" state-opts ] + [ "require-order" ( "yes" | "no" ) ] + [ "fingerprints" filename ] | + [ "skip on" ifspec ] | + [ "debug" ( "none" | "urgent" | "misc" | "loud" ) ] + [ "keepcounters" ] ) + +ether-rule = "ether" etheraction [ ( "in" | "out" ) ] + [ "quick" ] [ "on" ifspec ] [ "bridge-to" interface-name ] + [ etherprotospec ] [ etherhosts ] [ "l3" hosts ] + [ etherfilteropt-list ] + +pf-rule = action [ ( "in" | "out" ) ] + [ "log" [ "(" logopts ")"] ] [ "quick" ] + [ "on" ifspec ] [ route ] [ af ] [ protospec ] + [ hosts ] [ filteropt-list ] + +logopts = logopt [ "," logopts ] +logopt = "all" | "matches" | "user" | "to" interface-name + +etherfilteropt-list = etherfilteropt-list etherfilteropt | etherfilteropt +etherfilteropt = "tag" string | "tagged" string | "queue" ( string ) | + "ridentifier" number | "label" string + +filteropt-list = filteropt-list filteropt | filteropt +filteropt = user | group | flags | icmp-type | icmp6-type | "tos" tos | + "af-to" af "from" ( redirhost | "{" redirhost-list "}" ) + [ "to" ( redirhost | "{" redirhost-list "}" ) ] | + ( "no" | "keep" | "modulate" | "synproxy" ) "state" + [ "(" state-opts ")" ] | + "fragment" | "no-df" | "min-ttl" number | "set-tos" tos | + "max-mss" number | "random-id" | "reassemble tcp" | + fragmentation | "allow-opts" | "once" | + "label" string | "tag" string | [ "!" ] "tagged" string | + "max-pkt-rate" number "/" seconds | + "set prio" ( number | "(" number [ [ "," ] number ] ")" ) | + "max-pkt-size" number | + "queue" ( string | "(" string [ [ "," ] string ] ")" ) | + "rtable" number | "probability" number"%" | "prio" number | + "state limiter" name | + "state limiter" name "(" limiter-opts ")" | + "source limiter" name | + "source limiter" name "(" limiter-opts ")" | "prio" number | + "dnpipe" ( number | "(" number "," number ")" ) | + "dnqueue" ( number | "(" number "," number ")" ) | + "ridentifier" number | + "binat-to" ( redirhost | "{" redirhost-list "}" ) + [ portspec ] [ pooltype ] | + "rdr-to" ( redirhost | "{" redirhost-list "}" ) + [ portspec ] [ pooltype ] | + "nat-to" ( redirhost | "{" redirhost-list "}" ) + [ portspec ] [ pooltype ] [ "static-port" ] | + [ ! ] "received-on" ( interface-name | interface-group ) + +nat-rule = [ "no" ] "nat" [ "pass" [ "log" [ "(" logopts ")" ] ] ] + [ "on" ifspec ] [ af ] + [ protospec ] hosts [ "tag" string ] [ "tagged" string ] + [ "->" ( redirhost | "{" redirhost-list "}" ) + [ portspec ] [ pooltype ] [ "static-port" ] + [ "map-e-portset" number "/" number "/" number ] ] + +binat-rule = [ "no" ] "binat" [ "pass" [ "log" [ "(" logopts ")" ] ] ] + [ "on" interface-name ] [ af ] + [ "proto" ( proto-name | proto-number ) ] + "from" address [ "/" mask-bits ] "to" ipspec + [ "tag" string ] [ "tagged" string ] + [ "->" address [ "/" mask-bits ] ] + +rdr-rule = [ "no" ] "rdr" [ "pass" [ "log" [ "(" logopts ")" ] ] ] + [ "on" ifspec ] [ af ] + [ protospec ] hosts [ "tag" string ] [ "tagged" string ] + [ "->" ( redirhost | "{" redirhost-list "}" ) + [ portspec ] [ pooltype ] ] + +antispoof-rule = "antispoof" [ "log" ] [ "quick" ] + "for" ifspec [ af ] [ "label" string ] + [ "ridentifier" number ] + +table-rule = "table" "<" string ">" [ tableopts-list ] +tableopts-list = tableopts-list tableopts | tableopts +tableopts = "persist" | "const" | "counters" | "file" string | + "{" [ tableaddr-list ] "}" +tableaddr-list = tableaddr-list [ "," ] tableaddr-spec | tableaddr-spec +tableaddr-spec = [ "!" ] tableaddr [ "/" mask-bits ] +tableaddr = hostname | ifspec | "self" | + ipv4-dotted-quad | ipv6-coloned-hex + +altq-rule = "altq on" interface-name queueopts-list + "queue" subqueue +queue-rule = "queue" string [ "on" interface-name ] queueopts-list + subqueue + +anchor-rule = "anchor" [ string ] [ ( "in" | "out" ) ] [ "on" ifspec ] + [ af ] [ protospec ] [ hosts ] [ filteropt-list ] [ "{" ] + +anchor-close = "}" + +trans-anchors = ( "nat-anchor" | "rdr-anchor" | "binat-anchor" ) string + [ "on" ifspec ] [ af ] [ "proto" ] [ protospec ] [ hosts ] + +load-anchor = "load anchor" string "from" filename + +queueopts-list = queueopts-list queueopts | queueopts +queueopts = [ "bandwidth" bandwidth-spec ] | + [ "qlimit" number ] | [ "tbrsize" number ] | + [ "priority" number ] | [ schedulers ] +schedulers = ( cbq-def | priq-def | hfsc-def ) +bandwidth-spec = "number" ( "b" | "Kb" | "Mb" | "Gb" | "%" ) + +etheraction = "pass" | "block" +action = "pass" | "match" | "block" [ return ] | [ "no" ] "scrub" +return = "drop" | "return" | "return-rst" [ "( ttl" number ")" ] | + "return-icmp" [ "(" icmpcode [ [ "," ] icmp6code ] ")" ] | + "return-icmp6" [ "(" icmp6code ")" ] +icmpcode = ( icmp-code-name | icmp-code-number ) +icmp6code = ( icmp6-code-name | icmp6-code-number ) + +ifspec = ( [ "!" ] ( interface-name | interface-group ) ) | + "{" interface-list "}" +interface-list = [ "!" ] ( interface-name | interface-group ) + [ [ "," ] interface-list ] +route = ( "route-to" | "reply-to" | "dup-to" ) + ( routehost | "{" routehost-list "}" ) + [ pooltype ] +af = "inet" | "inet6" + +etherprotospec = "proto" ( proto-number | "{" etherproto-list "}" ) +etherproto-list = proto-number [ [ "," ] etherproto-list ] +protospec = "proto" ( proto-name | proto-number | + "{" proto-list "}" ) +proto-list = ( proto-name | proto-number ) [ [ "," ] proto-list ] + +etherhosts = "from" macaddress "to" macaddress +macaddress = mac | mac "/" masklen | mac "&" mask + +hosts = "all" | + "from" ( "any" | "no-route" | "urpf-failed" | "self" | host | + "{" host-list "}" ) [ port ] [ os ] + "to" ( "any" | "no-route" | "self" | host | + "{" host-list "}" ) [ port ] + +ipspec = "any" | host | "{" host-list "}" +host = [ "!" ] ( address [ "/" mask-bits ] | "<" string ">" ) +redirhost = address [ "/" mask-bits ] +routehost = "(" interface-name address [ "/" mask-bits ] ")" +address = ( interface-name | interface-group | + "(" ( interface-name | interface-group ) ")" | + hostname | ipv4-dotted-quad | ipv6-coloned-hex ) +host-list = host [ [ "," ] host-list ] +redirhost-list = redirhost [ [ "," ] redirhost-list ] +routehost-list = routehost [ [ "," ] routehost-list ] + +port = "port" ( unary-op | binary-op | "{" op-list "}" ) +portspec = "port" ( number | name ) [ ":" ( "*" | number | name ) ] +os = "os" ( os-name | "{" os-list "}" ) +user = "user" ( unary-op | binary-op | "{" op-list "}" ) +group = "group" ( unary-op | binary-op | "{" op-list "}" ) + +unary-op = [ "=" | "!=" | "<" | "<=" | ">" | ">=" ] + ( name | number ) +binary-op = number ( "<>" | "><" | ":" ) number +op-list = ( unary-op | binary-op ) [ [ "," ] op-list ] + +os-name = operating-system-name +os-list = os-name [ [ "," ] os-list ] + +flags = "flags" ( [ flag-set ] "/" flag-set | "any" ) +flag-set = [ "F" ] [ "S" ] [ "R" ] [ "P" ] [ "A" ] [ "U" ] [ "E" ] + [ "W" ] + +icmp-type = "icmp-type" ( icmp-type-code | "{" icmp-list "}" ) +icmp6-type = "icmp6-type" ( icmp-type-code | "{" icmp-list "}" ) +icmp-type-code = ( icmp-type-name | icmp-type-number ) + [ "code" ( icmp-code-name | icmp-code-number ) ] +icmp-list = icmp-type-code [ [ "," ] icmp-list ] + +tos = ( "lowdelay" | "throughput" | "reliability" | + [ "0x" ] number ) + +state-opts = state-opt [ [ "," ] state-opts ] +state-opt = ( "max" number | "no-sync" | timeout | "sloppy" | + "source-track" [ ( "rule" | "global" ) ] | + "max-src-nodes" number | "max-src-states" number | + "max-src-conn" number | + "max-src-conn-rate" number "/" number | + "overload" "<" string ">" [ "flush" ] | + "if-bound" | "floating" | "pflow" ) + +fragmentation = [ "fragment reassemble" ] + +timeout-list = timeout [ [ "," ] timeout-list ] +timeout = ( "tcp.first" | "tcp.opening" | "tcp.established" | + "tcp.closing" | "tcp.finwait" | "tcp.closed" | "tcp.tsdiff" | + "sctp.first" | "sctp.opening" | "sctp.established" | + "sctp.closing" | "sctp.closed" | + "udp.first" | "udp.single" | "udp.multiple" | + "icmp.first" | "icmp.error" | + "other.first" | "other.single" | "other.multiple" | + "frag" | "interval" | "src.track" | + "adaptive.start" | "adaptive.end" ) number + +limit-list = limit-item [ [ "," ] limit-list ] +limit-item = ( "states" | "frags" | "src-nodes" ) number + +pooltype = ( "bitmask" | "random" | + "source-hash" [ ( hex-key | string-key ) ] | + "round-robin" ) [ sticky-address | prefer-ipv6-nexthop ] + +subqueue = string | "{" queue-list "}" +queue-list = string [ [ "," ] string ] +cbq-def = "cbq" [ "(" cbq-opt [ [ "," ] cbq-opt ] ")" ] +priq-def = "priq" [ "(" priq-opt [ [ "," ] priq-opt ] ")" ] +hfsc-def = "hfsc" [ "(" hfsc-opt [ [ "," ] hfsc-opt ] ")" ] +cbq-opt = ( "default" | "borrow" | "red" | "ecn" | "rio" ) +priq-opt = ( "default" | "red" | "ecn" | "rio" ) +hfsc-opt = ( "default" | "red" | "ecn" | "rio" | + linkshare-sc | realtime-sc | upperlimit-sc ) +linkshare-sc = "linkshare" sc-spec +realtime-sc = "realtime" sc-spec +upperlimit-sc = "upperlimit" sc-spec +sc-spec = ( bandwidth-spec | + "(" bandwidth-spec number bandwidth-spec ")" ) +limiter-opts = "block" | "no-match" +include = "include" filename</pre> +</div> +</section> +<section class="Sh"> +<h1 class="Sh" id="FILES"><a class="permalink" href="#FILES">FILES</a></h1> +<dl class="Bl-tag Bl-compact"> + <dt><span class="Pa">/etc/hosts</span></dt> + <dd>Host name database.</dd> + <dt><span class="Pa">/etc/pf.conf</span></dt> + <dd>Default location of the ruleset file. The file has to be created manually + as it is not installed with a standard installation.</dd> + <dt><span class="Pa">/etc/pf.os</span></dt> + <dd>Default location of OS fingerprints.</dd> + <dt><span class="Pa">/etc/protocols</span></dt> + <dd>Protocol name database.</dd> + <dt><span class="Pa">/etc/services</span></dt> + <dd>Service name database.</dd> +</dl> +</section> +<section class="Sh"> +<h1 class="Sh" id="SEE_ALSO"><a class="permalink" href="#SEE_ALSO">SEE + ALSO</a></h1> +<p class="Pp"><a class="Xr">altq(4)</a>, <a class="Xr">carp(4)</a>, + <a class="Xr">icmp(4)</a>, <a class="Xr">icmp6(4)</a>, + <a class="Xr">ip(4)</a>, <a class="Xr">ip6(4)</a>, <a class="Xr">pf(4)</a>, + <a class="Xr">pflow(4)</a>, <a class="Xr">pfsync(4)</a>, + <a class="Xr">sctp(4)</a>, <a class="Xr">tcp(4)</a>, + <a class="Xr">udp(4)</a>, <a class="Xr">hosts(5)</a>, + <a class="Xr">pf.os(5)</a>, <a class="Xr">protocols(5)</a>, + <a class="Xr">services(5)</a>, <a class="Xr">ftp-proxy(8)</a>, + <a class="Xr">pfctl(8)</a>, <a class="Xr">pflogd(8)</a></p> +</section> +<section class="Sh"> +<h1 class="Sh" id="HISTORY"><a class="permalink" href="#HISTORY">HISTORY</a></h1> +<p class="Pp">The <code class="Nm">pf.conf</code> file format first appeared in + <span class="Ux">OpenBSD 3.0</span>.</p> +</section> +</div> +<table class="foot"> + <tr> + <td class="foot-date">April 22, 2026</td> + <td class="foot-os">FreeBSD 15.0</td> + </tr> +</table> |
