• No results found

The state-policy option specifies how PF matches packets to the state table. The possible values are floating and if-bound. The differences between the two lie in how subsequent packets are treated once a state table entry has been created.

With the default floating state policy, traffic can match state on all inter- faces, not just the interface where the state was created. With an if-bound policy, traffic will match only on the interface where the state is created. Traffic on other interfaces or groups will not match the existing state. Like block-policy, this option specifies the global state-matching policy. You can override state policy on a per-rule basis if needed. For example, in a rule set with the default floating state policy, you could have a rule like this:

pass out on egress inet proto tcp to any port $allowed modulate state (if-bound)

With this rule, any return traffic trying to pass back in would need to pass on the same interface where the state was created in order to match the state table entry.

WARNING The situations in which state-policy if-bound is useful are rare enough that the

general recommendation is to leave this setting at the default.

timeout

The timeout option sets the timeouts and related options for various inter- actions with the state table entries. The majority of the parameters are protocol-specific values stored in seconds and prefixed tcp., udp., icmp., andother.. However, adaptive.start and adaptive.end denote the number of state table entries.

WARNING These options can be used for optimizing your setup for performance, but changing the protocol-specific settings from the default values creates a significant risk that valid but idle connections might be dropped prematurely or blocked outright.

The timeout options you are most likely to change are the following:

adaptive.start and adaptive.end

These values set the limits for scaling down timeout values once the num- ber of state entries reaches the adaptive.start value. When the number of states reaches adaptive.end, all timeouts are set to zero, essentially expiring all states immediately. The default values are 6000 and 12000 (calculated as 80 percent and 120 percent of the state limit), respectively. These settings are intimately related to the memory pool limit parameters you set via the limit option discussed in the next section.

interval

This value denotes the number of seconds between purges of expired states and fragments. The default value is 10 seconds.

frag

The frag value denotes the number of seconds a fragment will be kept in an unassembled state before it is discarded. The default value is 30 seconds.

src.track

When set, src.track denotes the number of seconds source-tracking data will be kept after the last state has expired. The default value is 0 seconds. You can inspect the current settings for all timeout parameters with pfctl -s timeouts. This display shows a system running with default values.

$ sudo pfctl -s timeouts tcp.first 120s tcp.opening 30s tcp.established 86400s tcp.closing 900s tcp.finwait 45s tcp.closed 90s tcp.tsdiff 30s udp.first 60s udp.single 30s udp.multiple 60s icmp.first 20s icmp.error 10s other.first 60s other.single 30s other.multiple 60s frag 30s interval 10s adaptive.start 6000 states adaptive.end 12000 states src.track 0s

limit

The limit option sets the size of the memory pools PF uses for state tables and address tables. These are hard limits, so you may need to increase or tune the values for a variety of reasons. If your network is a busy one with larger numbers than the default values allow, or if your setup requires large address tables or a large number of tables, then this section will be very relevant for you.

It is important to keep in mind that the total amount of memory available through memory pools is taken from the kernel memory space, and the amount available is a function of the total available kernel memory. The kernel allocates a fixed amount of memory for its own use at system startup; however, since kernel memory is never swapped, the amount of memory allocated for the kernel’s own use can never equal or exceed the physical memory in the system. If that happened, there would be no space for user-mode programs to run. The exact amount of pool memory available depends on which hard- ware platform you use as well as on a number of hard-to-predict variables specific to the local system. On the i386 architecture the maximum kernel memory is in the 768MB to 1GB range, depending on a number of factors, including the exact number and kind of hardware devices in the system. The amount actually available for allocation to memory pools comes out of this total, again depending on a number of system-specific variables.

You can inspect the current limit settings using pfctl -sm. Typical output looks like this:

$ sudo pfctl -sm

states hard limit 10000 src-nodes hard limit 10000 frags hard limit 5000 tables hard limit 1000 table-entries hard limit 200000

To change these values, you edit your pf.conf to include one or more lines with new limit values. For example, you would use these lines to raise the hard limit for number of states to 25,000 and table entries to 300,000:

set limit states 25000

set limit table-entries 300000

You can also set several limit parameters at a time in a single line by enclosing them in brackets, like this:

set limit { states 25000, src-nodes 25000, table-entries 300000 }

In the end, you almost certainly should not change the limits at all. If you do, however, it is important to watch your system logs for any indication that your changed limits do not have undesirable side effects or do not fit in available memory. Setting the debug level to a higher value is potentially quite useful for watching the effects of tuning limit parameters.

debug

The debug option determines what, if any, error information PF will generate at the kern.debug log level. The default value is urgent, which means that only serious errors will be logged. The other possible settings are none (no messages), misc (reporting slightly more than urgent), and finally loud (producing status messages for most operations). After I ran my home gate- way at debug level loud for a little while, this is what my /var/log/messages file looked like:

$ tail -f /var/log/messages

Oct 4 11:41:11 skapet /bsd: pf_map_addr: selected address 194.54.107.19

Oct 4 11:41:15 skapet /bsd: pf: loose state match: TCP 194.54.107.19:25 194.54.107.19:25 158.36.191.135:62458 [lo=3178647045 high=3178664421 win=33304 modulator=0 wscale=1] [lo=3111401744 high=3111468309 win=17376 modulator=0 wscale=0] 9:9 R seq=3178647045 (3178647044) ack=3111401744 len=0 ackskew=0 pkts=9:12

Oct 4 11:41:15 skapet /bsd: pf: loose state match: TCP 194.54.107.19:25 194.54.107.19:25 158.36.191.135:62458 [lo=3178647045 high=3178664421 win=33304 modulator=0 wscale=1] [lo=3111401744 high=3111468309 win=17376 modulator=0 wscale=0] 10:10 R seq=3178647045 (3178647044) ack=3111401744 len=0 ackskew=0 pkts=10:12

Oct 4 11:42:24 skapet /bsd: pf_map_addr: selected address 194.54.107.19

As you can see, the loud level gives you a level of detail where PF repeatedly reports the IP address for the interface it is currently handling. In between the selected address messages, PF warns twice for the same packet that the sequence number is at the very edge of the expected range. This level of detail seems almost breathtaking at first glance, but in some circumstances studying this kind of output is the best way to diagnose a problem and later check to see if your solution actually helped.

It is worth noting that this option can be set from the command line with pfctl -x, followed by the debug level you want. The command pfctl -x loud gives you maximum debugging info, while pfctl -x none turns off debug messages entirely. Keep in mind that the output of the loud debug setting can be large amounts of data—and in extreme cases could impact perfor- mance all the way to self-DoS level.