PF Port(s) Match Invert (!; NOT)

Would be nice if the packet filter port(s) match could be inverted (!; NOT), similar to how it is for the from and to addresses.

That would allow rules like this...
block in quick on re0_vlan99 reply-to ( re0_vlan99 x.x.x.x ) inet proto {tcp udp} from {any} to {(re0_vlan99:network)} port ! { 1194 8086 22 443 }

Instead of this...
block in quick on re0_vlan99 reply-to ( re0_vlan99 x.x.x.x ) inet proto {tcp udp} from {any} to {(re0_vlan99:network)} port { 0:21 23:442 444:1193 1195:8085 8087:65535 }
 
You can use block on top of your rules and simply pass only needed traffic later:
Code:
block log all
....
pass in quick on re0_vlan99 reply-to ( re0_vlan99 x.x.x.x ) inet proto {tcp udp} from {any} to {(re0_vlan99:network)} port  { 1194 8086 22 443 }
 
The solution pointed out by shurik is pretty much "best practice" for firewalls. "Default deny" stance then allow what need.

It's easy to do in pf because rules are "last match wins" and the quick keyword short circuits on a match.
In my opinion it also makes the ruleset smaller and easier to follow.
 
That doesn't work with quick and is no different than having block all at the bottom of the rules. Both are default deny. But only after having been processed through all the rules. Defeating the purpose of using quick to prevent further processing of traffic through the rules that has no possibility of matching.
 
That doesn't work with quick and is no different than having block all at the bottom of the rules.

PF is last match wins.

block all at the top of the ruleset is "default deny" which means "if no subsequent rules match block the packet".

pass quick after that will stop processing when it matches. It only processes as many rules as it needs to.
 
"PF is last match wins."

Only without quick.


"block all at the top of the ruleset is "default deny" which means "if no subsequent rules match block the packet"."

Block all at the bottom of the ruleset does the same thing. If no preceding rule, with quick option, matched then block the packet.


"pass quick after that will stop processing when it matches. It only processes as many rules as it needs to."

That first block rule would be the only one that needs to be processed if it does not match any of the specified ports. There would be no point in processing any subsequent rules as there is no possibility of a match. Immediate default deny with no further processing.

The point is to block all except for a specified set of tcp/udp ports at the top of the list and immediately drop the packet without processing any more rules.
 
Invert match works on the ip address but I don't think it works on anything else.
We are trying to tell you how to achieve what you want within the confines of how pf currently works.
What you want currently doesn't work, so I don't know what else anyone can tell you
 
Correct. Invert only works on IP address. As I mentioned in the opening post.
I already know how to achieve what I want within the confines of how pf currently works. That's why I did not ask how, but rather stated what would be nicer. i.e. capability to invert the sense of the ports match.
 
That only works with a single port. Doesn't work with a list of ports. i.e. { 1194 8086 22 443 }
The ports list match logic is OR. So { !=1194 !=8086 !=22 !=443 } is always true.
What is desired is port ! { 1194 8086 22 443 }. So if port is any of those the result is TRUE and inverted to FALSE (NOT).
 
Your desired configuration may be presented by two rules:
Code:
match in quick on re0_vlan99 inet proto {tcp udp} from {any} to {(re0_vlan99:network)} port { 1194 8086 22 443 } tag MATCHED
block in quick ! tagged MATCHED
Note, when you group ports together by {port1 port2 ... } syntax, pf's engine splits it into multiple rules. And second, reply-to with block statement has no sense.
 
Seems that would be more processing than the single rule with anti-ports ranges.

In pf engine, 5 rules, plus tagging the packet, vs. 1 to 5 rules (immediately drop on first match) without tagging packet.

In my usage the anti-ports ranges rule is presented in a GUI as; ! 22 443 1194 8086.

Considering what has been posted here so far, prefer the single anti-ports rule; port { 0:21 23:442 444:1193 1195:8085 8087:65535 }. But think supporting a NOT syntax, port ! { 1194 8086 22 443 }, would be nicer.

Goal
Drop packets as soon as possible which have no possibility of matching a pass rule. Preventing evaluation of subsequent block rules which are based on other criteria.
 
Back
Top