Anchors

In PF, an anchor is a sub-ruleset at a specific point in the filter rules that you can change without reloading the rules. It’s a spot marked “insert rules here,” letting you dynamically add and remove filter rules, tables, and other PF configurations.

The most common users of anchors are software programs. Human beings or sysadmins should probably just edit pf.conf and reload the rules.

OpenBSD includes several programs that take advantage of anchors, however, including the FTP proxy ftp-proxy(8), the authenticated firewall access system authpf(8), and the load balancer relayd(8). You could also use anchors to trigger conditional evaluation of rules.

A ruleset with an anchor might look something like the following, where the interface group egress faces the Internet, and the interface group lan faces a small office with the addresses 192.0.2.0/24.

block
pass in on egress from any to 192.0.2.45 port {25, 80}
anchor "antivirus/*"
pass in on lan from 192.0.2.0/27 to any

These rules block all traffic by default. Incoming traffic is allowed to a specific address on ports 25 and 80 because those are the mail and web servers. There’s an anchor in the middle of the rules. I don’t yet know what’s in the antivirus anchor, but any rules in it are processed next. Finally, a small subnet of the addresses is allowed out.

Now let’s add some rules to the anchor.

Adding Rules to Anchors

You can insert rules into anchors from a file, within pf.conf itself, or via pfctl.

Anchor Rules from Files

Adding rules to an anchor from a file is a good way to initialize your anchor when first starting the packet filter. You can set base rules here that you can expand later. Give the filename in pf.conf.

anchor dhcp
load anchor dhcp from "/etc/pf/dhcp-anchor.conf"

I created an /etc/pf/ directory because I didn’t want to have a whole bunch of PF configuration files scattered throughout /etc. I’m easily confused, after all. This file contains PF rules like this:

block from 192.0.2.192/26 to any

This is one way to load basic rules into an anchor when you start PF.

If you were paying attention, you probably noticed that my first example anchor had a /* after its name. This example doesn’t. I’ll explain why in Nested Anchors: /*.

Anchor Rules in pf.conf

You can place anchor rules directly inside pf.conf. If you don’t intend to dynamically alter the rules, you don’t even need to name the anchor. Just use curly braces to define the beginning and end of the anchor.

anchor "smtp" on egress {
    pass proto tcp from 192.0.2.12 to any port 25
    }

This is just slightly more complicated than the anchors in the default pf.conf.

Why would you want to do this? Read Conditional Filtering.

Anchor Rules via pfctl

To dynamically alter anchor rules with pfctl, you need the name of the anchor and the rule you want to put in its place. For example, suppose I want to add a rule to the antivirus anchor in the first anchor example.

# 1
echo "block in from 203.0.113.8 to any" 2
| pfctl 3
-a antivirus 4
-f -

Let’s look at this command slightly backwards. The -a argument to pfctl specifies an anchor name—in this case, the antivirus anchor 3. The -f argument normally gives a filename that contains the new anchor rule, much like -f when loading a PF ruleset, but rather than a path to a file, I use a single dash that tells pfctl to read the new rule from standard input, or the command line 4. I start everything by echoing the rule to be added 1, and then piping that into pfctl 2.

Taken as a whole, this adds the rule block in from 203.0.113.8 to any to the anchor antivirus.

You could also write the new rule to a file, and tell pfctl to load the rules from that file into the anchor.

# pfctl -a antivirus -f newrule.conf

If you’re writing rules to a file to load them into an anchor, however, chances are you’re better off editing pf.conf.

Note

Adding a rule to an anchor erases any rules already in the anchor. If you have a software package that updates anchor rules, your software needs to handle this behavior. If your desired behavior can be accomplished using a list of IP addresses, consider using a table instead of an anchor.

Viewing and Flushing Anchors

Use the pfctl view (-s), flush (-F), and load (-f) commands on anchors by specifying the anchor name with -a.

# pfctl -a antivirus -s rules
block drop in inet from 203.0.113.8 to any

To erase the rules from an anchor, flush the rules in the anchor.

# pfctl -a antivirus -F rules
rules cleared

Your anchor is now empty.

Rulesets within anchors are completely separate from each other, and also from the main ruleset. Flushing all the rules in a specific anchor does not affect the rules in any other anchor, or the rules in the main ruleset. For that matter, flushing the rules in the main ruleset does not impact the rules in the anchor. To destroy an anchor, you must remove everything in the anchor, including any child anchors.

“Child anchors?” I hear you cry. “What are you babbling about now, dude?”

Conditional Filtering

Consider the following pf.conf snippet:

…
anchor "office/*" in from lan to any {
    pass out proto tcp from any to {80, 443}
    }
…

The office/* anchor has a filter condition after it, and only traffic that matches the filter condition will pass through the anchor. In this case, only packets that come from the lan interface group will pass through the rules within the anchor. Your rules within the anchor might be easier to write, simply because everything in the anchor is already known to be originating from the lan interfaces.

If your packet filter is very heavily loaded, you might be able to reduce the amount of time it spends processing packets by careful conditional filtering.

Nested Anchors: /*

Anchors can contain other anchors.

anchor "office" in from lan to any{
    …
    anchor "ftp-proxy/*"
    pass in quick inet proto tcp to port ftp divert-to 127.0.0.1 port 8021
}
…

Only traffic that passes into the office anchor can pass through the ftp-proxy anchor. The FTP proxy can have its own sub-anchors as well. In fact, you might have several layers of anchors to support a complicated protocol, such as FTP.

This is where the /* after some anchor names comes in. An anchor name without this is executed all by itself. By adding the /*, you tell PF to evaluate all sub-anchors within this anchor, in alphabetical order.

Anchors and sub-anchors deliberately resemble a filesystem. You can have a file /office or a directory /office/ containing more files. If you list the files in a directory, they appear in alphabetical order. Anchors work much the same way.

All of this anchor stuff is very theoretical. How about a practical example? Read on to see how PF uses anchors to handle that most annoying of network protocols: FTP.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.218.3.204