I just read a book about PF (The Book Of PF, No Starch), but there's one question not answered by it.

If I have a gateway machine using two interfaces, $int_if and $ext_if, and I NAT the packages coming from $int_if:net (which is, let's say, to $ext_if using match, when gets the NAT applied? Before or after the filtering rules?


match out on $ext_if from nat-to ($ext_if)
pass out on $ext_if from
block drop out on $ext_if from

Does that work? Or gets the source IP of a packet coming from NATed to the address of $ext_if before the check if it's from gets evaluated?

This diagram is not helpful to answer this question, I think, but it's interesting nevertheless: [http://www.benzedrine.cx/pf_flow.png]

If you read the PF NAT FAQ [http://www.openbsd.org/faq/pf/nat.html], especially the section "Configuring NAT", you'll come across this sentences:

When a packet is selected by a match rule, parameters (e.g. nat-to) in that rule are remembered and are applied to the packet when a pass rule matching the packet is reached. This permits a whole class of packets to be handled by a single match rule and then specific decisions on whether to allow the traffic can be made with block and pass rules.

I think that sounds as if it's not as I stated in the paragraph above, so the source IP gets "remembered" until there's a decision about the action to be done with the packet. If the decision is made, the NATting gets applied.

What do you think?

P.S.: This is a quite theoretic question. If you're a little bit pragmatic, you'll do it this way:

match out on $ext_if from nat-to ($ext_if)
block drop from
# or, explicitly,
# block drop in on $int_if from

So the block rule gets already applied when the packet comes in on $int_if.

EDIT: Another possibility is, of course, to decide before NAT:

pass from
block drop from
match out on $ext_if from nat-to ($ext_if)

If a packet from .23 arrives, it first matches the first rule, then matches the second rule and the third "rule". But as the second rule is the last deciding about passing/blocking, the packet gets blocked. Right?


Yes, it is quite theoretical, what you asked, but a very interesting question.

The match rule will get applied when it is acting on the last matching rule. match rules are "sticky", like you mentioned. The main purpose of them is to be able to set things like a NAT rule once, and not have to put nat-to on the end of a bunch of rules you have about outbound traffic.

In your example the packet will get dropped. I'd have to look at the code or ask Henning Brauer to be certain if they skip the NAT check completely in the drop case, but it would not get NATted out.

I think your rule is covered by the Book of PF (got the 2nd edition?), but I don't think they are explicit about it with the match rule.

| improve this answer | |

Please correct me if I was wrong, you want to pass all the outgoing packets from but you want to block If so change your rule to:

match out on $ext_if from nat-to ($ext_if)
block drop out quick on $ext_if from
pass out on $ext_if from

Simply use quick to prevent the firewall from continuing filtering (similar to break in some programming languages).


The quick Keyword

As indicated earlier, each packet is evaluated against the filter ruleset from top to bottom. By default, the packet is marked for passage, which can be changed by any rule, and could be changed back and forth several times before the end of the filter rules. The last matching rule "wins". There is an exception to this: The quick option on a filtering rule has the effect of canceling any further rule processing and causes the specified action to be taken. Let's look at a couple examples:


block in on fxp0 proto tcp to port ssh
pass  in all 

In this case, the block line may be evaluated, but will never have any effect, as it is then followed by a line which will pass everything.


block in quick on fxp0 proto tcp to port ssh
pass  in all 

These rules are evaluated a little differently. If the block line is matched, due to the quick option, the packet will be blocked, and the rest of the ruleset will be ignored.

| improve this answer | |
  • I'm aware of the quick keyword but I don't really like it - I always try to use pf's evaluation order ;) Btw, I found the answer on an OpenBSD FAQ page: " NAT is specified as an optional nat-to parameter to an outbound pass rule. Often, rather than being set directly on the pass rule, a match rule is used. When a packet is selected by a match rule, parameters (e.g. nat-to) in that rule are remembered and are applied to the packet when a pass rule matching the packet is reached.". So my ruleset would not cause any problems and correctly block .23 – dermesser Apr 3 '13 at 7:57
  • (the matching rule in line 2 let the packets pass after going through all rules and then NAT is applied) – dermesser Apr 3 '13 at 8:00

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.