BSD DevCenter
oreilly.comSafari Books Online.Conferences.

advertisement


NAT with pf
Pages: 1, 2, 3, 4

Options

The early release of pfctl(8) included with OpenBSD 3.0 (and 3.1) used the -O command-line option to specify the algorithm for filter rules optimization. Because the new version of pf(4) included with OpenBSD 3.2 allows more influence over the filtering engine behavior, these options have moved to the rules file. It is simply more convenient this way.



There are four categories of options that you may define in your packet filter rules file:

  • limit
  • loginterface
  • optimization
  • timeout

The -O option is still available, but its purpose has changed. It tells pfctl(8) to load only the options section from the rules file, as in

$ sudo pfctl -f /etc/pf.conf -O

The already loaded NAT or filter rules will not be modified. Remember that if you disable or remove an option that was defined before, that option will be reset to its default value.

limit

The limit frags n and the limit states m options set hard limits on the number of memory pools used by the packet filter. They tell pf(4) how much memory it can use to store packet fragments (fragments are stored in memory before reassembly and are reassembled when you use scrub rules) and state table entries (for stateful filtering; enable it with the keep state rules in the filter section). If you set this option, pf(4) will store only n fragments or m state table entries. Administrators use this option to avoid performance hits and to prevent attacks from overwhelming the firewall's resources. Both limits are independent. You may set either or both, or you may combine both in a single rule:

#################################################################
# macro definitions

#################################################################
# options: "set"

# ex. 1: limit the number of fragments kept in memory to 30000
set limit frags 30000

# ex. 2: limit the number of state table entries to 25000
set limit states 25000

# ex. 3: combine  
set limit { frags 30000, states 25000 }

You can check the current limits:

$ sudo pfctl -s memory
states     hard limit   25000
frags      hard limit   30000

If a limit is unset, you'll see output similar to this one:

$ sudo pfctl -s memory
states     unlimited
frags      unlimited

Note that there is no way to unset these limits in OpenBSD 3.2. You can change the values of limits, if you can change and reload /etc/pf.conf:

$ sudo vi /etc/pf.conf
$ sudo pfctl -f /etc/pf.conf

To reset limits to their unlimited state, you have to comment out or remove set limit ... rules in /etc/pf.conf, and reboot your firewall:

$ sudo vi /etc/pf.conf
$ sudo reboot

This behavior has been fixed in the -current branch and is expected to appear in OpenBSD 3.3.

For more information about packet fragmentation and reassembly, including the issue of timeouts, consult RFC815 [Clark 1982]. If that doesn't answer your questions, read [Stevens 1994, 2:275-300].

loginterface

The new loginterface ifname option specifies the name of the network interface on which pf(4) will collect statistics. These statistics are

  • bytes received
  • bytes sent
  • packets received (passed and blocked)
  • packets sent (passed and blocked)

The following example shows how to activate this option:

#################################################################
# macro definitions

ext_if = "ne1"

#################################################################
# options: "set"

# ex. 1: collect statistics on ne1
set loginterface $ext_if

pfctl(8) can display these statistics:

$ sudo pfctl -s info

...
Interface Stats for ne1               IPv4             IPv6
  Bytes In                             760                0
  Bytes Out                            696                0
  Packets In
    Passed                              10                0
    Blocked                              0                0
  Packets Out
    Passed                               6                0
    Blocked                              0                0
...

You can collect statistics for only one interface, even if you use multiple set loginterface rules. This snippet

set loginterface ne1
set loginterface ne2

will only collect statistics on ne2 because it was the last loginterface rule. To switch it off, you must add the set interface none rule (as the last set loginterface rule) to /etc/pf.conf and reload the options with

$ sudo pfctl -O -f /etc/pf.conf

optimization

This rule controls the packet filter engine optimization options. The old optimization options -O found in earlier version of have been replaced with the optimization algorithm rule. There are six values of the algorithm argument:

  • default: as its name says, it's the default optimization algorithm
  • normal: same as default
  • high-latency: used for high-latency links, such as satellite links
  • satellite: same as high-latency
  • aggressive: expires idle connections earlier than default; using less memory and CPU time while possibly dropping some legitimate connections
  • conservative: tries to avoid dropping any legitimate connections at the expense of increased memory usage and CPU utilization

Don't forget to reload the new options after changing the optimization algorithm:

$ sudo pfctl -O -f /etc/pf.conf

Before you rush to enable these optimization rules, you should know that these algorithms make a difference in special cases like high-latency connections, or very busy corporate, government, or education networks. Small networks and networks with low traffic will see no noticeable performance improvements.

The optimization rule is a shortcut for setting a bunch of timeout rules quickly. If none of them seem to work in your particular setup, consider adjusting the timeout values yourself, as described below.

timeout

The timeout option rule adjusts the expiration time of stateful connections. These rules only apply to packets matching stateful connections (established with the keep state keyword in pass filter rules). The general syntax of this rule is set timeout protocol.connectionstate timeout, for example:

#################################################################
# options: "set"

# ex. 1 sets timeout of the stateful connection to 20 seconds
# after receiving the first packet from the host initializing
# this connection.
set timeout tcp.first 20

# ex. 2 sets timeout of the stateful connection to 20 seconds
# after receiving the first packet from the host initializing
# this connection, then, if the connection is established, 
# every packet that matches the established state of a TCP 
# connection resets the timeout of the TCP connection it is a
# part of to 10 seconds.  This is very aggressive, and will result
# in a high percentage of lost valid connections on slow links. 
set timeout tcp.first 20
set timeout tcp.established 10

# ex. 3 same as ex. 2, but both rules have been combined on a
# single line (the order of protocol.state rules is not relevant)
set timeout { tcp.first 20, tcp.established 10 }

Example 1 above sets a very aggressive rule. If the connection is not established in 20 seconds, it will be dropped. In example 2, the connection will be dropped if the firewall does not receive a packet that is a part of the established TCP connection in 10 seconds. This is a very aggressive setting.

The protocol.connectionstate can be one of these values:

  • tcp.first
  • tcp.opening
  • tcp.established
  • tcp.closing
  • tcp.finwait
  • tcp.closed

All of the above values match various states of a TCP connection cycle. (To learn more about the TCP connection state transition cycle, consult RFC761 [Postel 1980], and if you are still looking for more information, read [Stevens 1994, 1:240-242, 2:805-807].)

You can check global timeout settings with

$ sudo pfctl -s timeouts
tcp.first                   120s
tcp.opening                  30s
tcp.established           86400s
tcp.closing                 900s
tcp.finwait                  45s
tcp.closed                   90s
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

As you can see, it is possible to control other protocols, like UDP, or ICMP, but the number of protocol.state matches is more limited:

  • udp.first
  • udp.single
  • udp.multiple
  • icmp.first
  • icmp.error
  • other.first
  • other.single
  • other.multiple

other is a catch-all category for protocols which are neither TCP, UDP, nor ICMP.

The last two timeouts (interval and frag) specify the interval between flushing expired states and fragments and the time before unassembled fragments are flushed.

#################################################################
# options: "set"

# this connection.
set timeout interval 20
set timeout frags 20

Because optimization rules reset various timeout settings, you should always list optimization rules before your timeout rules; otherwise your timeout settings will be overwritten the values introduced by optimization rules.

Pages: 1, 2, 3, 4

Next Pagearrow





Sponsored by: