Chapter 19: Managing PF


Blowfish guard the gates.
You may pass, vermin may not:
"Get your own network!"

Now that you can configure the packet filter, let's take a look at how to actually manage the PF system. The pfctl program does most of the basic management of the packet filter and gives you a window into the entire system. You can examine and edit the state and address tables separately. Finally, PF will allow you to authenticate users to the packet filter, giving Internet access only after a successful login.

pfctl(8)

All PF actions are controlled by the packet filter control program pfctl(8). You can manage your configuration as a whole, or each of the sub-functions independently. You can also kill individual connections or display statistics. Stateful inspection has different management requirements, so we're going to consider those in "Managing State Tables"; here, we'll look at managing every other part of PF.

pfctl(8) has many different functions, which are documented in the manual page. New functions are being added all the time, and the syntax occasionally changes, so be sure to check the manual page if you have trouble.

General Commands

To disable PF and all its functions, run "pfctl -d". Note that this will not turn off packet forwarding, so if you're running a PF firewall without NAT you have just exposed your network to the world. If you're using NAT, of course, disabling NAT turns off your private network's access to the Internet. To enable PF again, run "pfctl -e".

Many pfctl(8) commands produce output when everything runs correctly. To make pfctl(8) run more quietly, only printing errors and warnings, add "-q" to your command line. Similarly, to produce more information add "-v" to the command. You can make pfctl(8) even more verbose by adding a second or third "-v."

Loading Rules

PF handles rule switching in such a way that there is no "window" where the system is not protected by packet filtering, unlike some older packet filters. The rules are loaded into system memory, then the switch between the old ruleset and the new ruleset is made in a single operation. If you want to load an entire rules file, use the "-f" flag and give the name of your rules file. Here, we load in the rules from /etc/pf.conf:

 # pfctl -f /etc/pf.conf 

If your configuration file has a syntax error, pfctl(8) will complain and won't load the rules. Your old rules will remain in effect.

 # pfctl -f /etc/pf.conf pf.conf: 1 6: syntax error pfctl: Syntax error in file: pf rules not loaded # 

In this example, there's an 1 error on line 6 of the configuration. Personally, I like to know that my edited packet filter configuration is correct before the scheduled time to put it into production. (It's quite embarrassing to announce to the development team that "the new firewall configuration will be active during lunch," and then spend the whole time tracking down a misplaced comma or a parenthesis where you should have put in a curly brace.) You can parse your configuration file without loading it into the kernel with the "-n" flag.

 # pfctl -n -f /etc/pf.conf # 

Loading a new ruleset will not remove any existing open connections. If my ruleset allows outbound SSH connections, and I remove that permission from the rules and reload them, existing SSH connections will remain. I can either specifically kill that connection or flush the state table as well.

If you want to reload your packet-handling rules without touching any of the other rules in your configuration file, you can use the "-R" option.

 # pfctl -R -f /etc/pf.conf 

This leaves the rules for all options, NAT, and other PF features unchanged, and only reads the packet-filtering rules. You can change filter rules all you want, and the other functions will be unaffected. Of course, if you load rules that are incompatible with the configuration of those other functions, such as referring to nonexistent queues, you'll have other problems.

Similarly, you can load only the NAT rules with "-N," and only the option rules with "-O."

 # pfctl -N -f /etc/pf.conf # pfctl -O -f /etc/pf.conf 

Flushing Rules

You can blow away all the existing configuration information with the "-F" (flush) flag. The "-F" flag takes an argument that indicates which part of the configuration should be flushed.

To flush all the configuration you must add the "all" argument. Your NAT rules will go away, existing state entries will disappear, and your queue configuration will vanish. If this is your firewall, your internal network's access to the Internet will fail and all existing connections will drop. This will pretty much hose your network, your connectivity, and your security. The flush command will identify each component as it flushes the information.

 # pfctl -F all rules cleared nat cleared altq cleared states cleared pf: statistics cleared # 

You can also flush only the packet-filtering rules, leaving all traffic free to go in any direction. Although any queues will still be in place, you won't have any rules to direct traffic to those queues. NAT will remain in place. Also, just flushing the rules will not interrupt any existing stateful connections.

 # pfctl -F rules rules cleared # 

The most common situation where I've had to flush the filtering rules is when troubleshooting a connection problem. It's neither pretty nor secure, but it's nice to have the option.

Flushing queues leaves you without any bandwidth management. PF will not complain if packet-filtering rules direct packets at nonexistent queues, it will just process the packets as best it can. Flush your queues with the "queue" argument.

 # pfctl -F queue altq cleared # 

If you want to remove your NAT ability, you could flush your NAT rules. This will not interrupt existing connections in the state table, but will prevent further connections that require NAT.

 # pfctl -F nat nat cleared # 

Finally, PF also keeps statistics that are not part of any rule. You can reset all those counters to zero by running "-F info".

Viewing PF Information

You can check various information PF keeps with the "-s" (show) flag. You might also look at the configuration file to see what you loaded, but this might change if you're using authpf (see "Authenticated Access") or other anchor functions. The show function takes an argument, the part of the system whose rules you want to see.

Viewing Current Packet Filter Rules

To view the current PF rules, run "pfctl -s rules."

 # pfctl -s rules scrub in all fragment reassemble pass in inet proto tcp from any to 192.168.1.4 port = www pass in inet proto tcp from any to 192.168.1.4 port = https pass in inet proto tcp from any to 192.168.1.5 port = www pass in inet proto tcp from any to 192.168.1.5 port = https ... 

If you use verbose output ("-v") when viewing the rules, pfctl(8) will show how often a given rule is hit. This is extremely useful when debugging packet filter issues.

 # pfctl -v -s rules ... block drop in on fxp1 inet all [ Evaluations:   1 34984     2 Packets: 21      3 Bytes: 16330      4 States: 0 ] ... 

Each rule is displayed with four numbers: 1 how many times this rule has been evaluated, 2 the number of packets that have matched the rule, the 3 number of bytes that the rule has processed through this rule, and the number of 4 states that are maintained via stateful inspection by this rule. Since the counters were last cleared, this generic "block all incoming traffic" rule has matched 21 out of 34,984 packets, containing 16330 bytes. To see what was in those packets, examine them via tcpdump (see "Logging").

Viewing Current NAT Rules

View the current NAT rules by running "pfctl -s nat".

 # pfctl -s nat nat on fxp1 inet from 192.168.1.0/24 to any -> (fxp1) # 

If you want to see more on how your NAT rules are processed, add the "-v" flag. The output is almost identical to the rule output, so we're not going to repeat it.

Viewing Current Queues

You can view the current queues with "-s queue". Verbosity has no effect upon viewing queues.

 # pfctl -s queue altq on fxp1 cbq bandwidth 100.00Mb tbrsize 12000 queue root_fxp1 bandwidth 100.00Mb priority 0 cbq(wrr root) {t1, local} queue  t1 bandwidth 1.54Mb {ssh, http-in, http-out, mail, dns, ftp, misc} queue   ssh bandwidth 1 77.20Kb cbq(borrow) ... 

No matter how we specified bandwidth allowances, they are converted to a bits, kilobits, or megabits in this output. If you recall, in our examples we divided up the bandwidth of our T1 by percentages, but here our individual queue sizes are shown in 1 kilobits. PF does all of its internal operations in bits, of course.

Viewing Labels

Back when we set up labels, it was with the promise that you could view rule statistics per label. Do this with the "pfctl -s labels" command.

 # pfctl -s label ssh-out 1 38 2 126 3 24333 browsing 38 253 59599 browsing 26 0 0 # 

The 1 first column is the number of times this rule has been evaluated. The 2 second is the number of packets that have been affected by this rule, and the 3 third is the number of bytes that have been affected by this rule.

One odd thing is this output is that we have two labels called "browsing!" What's more, they have different statistics. This can happen when you use braces within a rule and don't use a macro to label the differences between those rules. The "browsing" label was created by this rule.

 pass out proto tcp from ($ExtIf) to any port {80, 443} label browsing 

We are allowing two different ports, with two different statistics, and giving them the same label. See Chapter 18 for how to properly differentiate between these connections with labels.

View State and Normalization Statistics

PF maintains statistics for state tables and packet normalization. You can view both of these statistics lists with "pfctl -s info". These statistics may be in terms of packets, or fragments, or entries in a table, or a number of times an action has been performed, as appropriate.

 # pfctl -s info Status: Enabled for 0 days 21:49:18 1             Debug: None 2 State Table                       3 Total            4 Rate 5 current entries                         6 6 searches                           487527             6.2/s 7 inserts                              1118             0.0/s 8 removals                             1112             0.0/s 

The "enabled for" entry shows how long PF has been running for. This is usually the time since boot, although if someone has enabled and disabled the packet filter with pfctl(8) commands it will be reflected here as well.

The first half of the output shows the statistics for the 2 state table. We also display the number of 3 items that match a particular entry and the number of 4 items per second that PF processes. While state table entries per second is a largely meaningless value, we can see the number of 5 current state table entries. (We discuss viewing the actual state table entries in "Managing Stateful Inspection.")

The 6 "searches" line indicates the number of times a packet has been compared to the state table. The state table is searched every time a packet passes an interface, so if you're forwarding packets between interfaces this is probably about twice the number of packets your system has passed. (Packets that originate on or terminate at your system are only searched once, of course.)

The 7 "inserts" entry shows how many times states have been created, and 8 "removals" shows how many have been destroyed. The difference between the two should equal the number of current states. As your system stays up the number of insertions and removals should get very close to each other — even if you have a few hundred entries in your state table, that's fairly insignificant compared to millions of states that will be created and destroyed over the state table's lifetime.

 Counters 1 match                                  1847           0.0/s 2 bad-offset                                0           0.0/s 3 fragment                                  0           0.0/s 4 short                                     0           0.0/s 5 normalize                                 0           0.0/s 6 memory                                    0           0.0/s 

The "Counters" section tells how many times a packet has matched a particular rule. For example, the 1 "match" entry says how many packets find a last matching rule in PF. This should be a total of the number of packets that have passed through the system, unless you're relying on PF's implicit "pass all" to manage traffic. The 2 "bad-offset" entry shows how many packets were received with a bad offset, the 3 "fragment" column shows how many fragments have been received, and the 4 "short" entry tells how many unusually short packets were received.

If a packet cannot be coherently reassembled, PF will drop the pieces. 5 "Normalize" shows how many packets have been dropped after scrubbing. Similarly, the 6 "memory" entry shows how many packets have been dropped because PF doesn't have enough memory to hold on to the packet fragments before reassembling them. If you start to lose packets due to memory shortages, you need to increase the memory you have allocated to PF (see "PF Memory Limits").

Viewing Everything at Once

As this command also works for many different functions of PF, to view the entire configuration add the "all" argument.

 # pfctl -s all 

This provides a complete listing of the configuration for NAT, packet-filtering rules, queues, and statistics.

Clearing PF Statistics

Finally, PF keeps statistics on just about everything it does. You can clear these statistics with the "-z" (zero) flag.

 # pfctl -z pf: rule counters cleared # 




Absolute Openbsd(c) Unix for the Practical Paranoid
Absolute OpenBSD: Unix for the Practical Paranoid
ISBN: 1886411999
EAN: 2147483647
Year: 2005
Pages: 298

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net