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