Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

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, 10.0.0.0/24) to $ext_if using match, when gets the NAT applied? Before or after the filtering rules?

Example:

match out on $ext_if from 10.0.0.0/24 nat-to ($ext_if)
pass out on $ext_if from 10.0.0.0/24
block drop out on $ext_if from 10.0.0.23

Does that work? Or gets the source IP of a packet coming from 10.0.0.23 NATed to the address of $ext_if before the check if it's from 10.0.0.23 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 10.0.0.0/24 nat-to ($ext_if)
block drop from 10.0.0.23
# or, explicitly,
# block drop in on $int_if from 10.0.0.23

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 10.0.0.0/24
block drop from 10.0.0.23
match out on $ext_if from 10.0.0.0/24 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?

share|improve this question

2 Answers 2

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.

share|improve this answer

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

match out on $ext_if from 10.0.0.0/24 nat-to ($ext_if)
block drop out quick on $ext_if from 10.0.0.23
pass out on $ext_if from 10.0.0.0/24

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

http://www.openbsd.org/faq/pf/filter.html#quick

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:

Wrong:

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.

Better:

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.

share|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

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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