I would like to have a pf.conf similar to the following: table <bruteforce> persist block log quick from <bruteforce> ... more rules anchor "external" on $interface { ... more rules pass in proto tcp from any to ($interface) port ${tcp_services} keep state \ (max-src-conn 10, max-src-conn-rate 1/4, \ overload <bruteforce> flush global) ... more rules } ...more anchor/rules If I try the above, when I load the rules I get: pfctl: warning: namespace collision with <bruteforce> global table. I then tried the following in pf.conf: ... some rules anchor "external" on $interface { table <bruteforce> persist block log quick from <bruteforce> ... more rules pass in proto tcp from any to ($interface) port ${tcp_services} keep state \ (max-src-conn 10, max-src-conn-rate 1/4, \ overload <bruteforce> flush global) ... more rules } ... more rules And I got "syntax error" on the line where "table <bruteforce> persist" is and on the line where the closing bracket of the anchor "external is. It is unclear to whether I am making a mistake, or whether the first and/or the second should actually work (and I would prefer at least the first to work, if possible). (This issue maybe, but perhaps not, related to #183198. This forum post (https://forums.freebsd.org/threads/inline-anchor-table-fail.61116/) also shows something similar to what I am experiencing)
Actually, it seems that the namespace collision warning also happens with a pf.conf that does not use anchors and contains table <bruteforce> persist block log quick from <bruteforce> pass in proto tcp from any to ($interface) port ${tcp_services} keep state \ (max-src-conn 10, max-src-conn-rate 1/4, \ overload <bruteforce> flush global) This set of rules is inspired by the very similar one from https://www.openbsd.org/faq/pf/filter.html#stateopts, thus one would expect it to work.
Some more investigation: it turns out that the problem is more subtle than I thought. My previous examples of pf.conf were "slimmed down" versions of what I actually tried. The following does not work: table <bruteforce> persist block log quick from <bruteforce> label "bruteforceblock" pass in proto tcp from any to ($interface) port ${tcp_services} keep state \ (max-src-conn 10, max-src-conn-rate 1/4, \ overload <bruteforce> flush global) The following works: table <bruteforce> persist block log quick from <bruteforce> label "mybruteforceblock" pass in proto tcp from any to ($interface) port ${tcp_services} keep state \ (max-src-conn 10, max-src-conn-rate 1/4, \ overload <bruteforce> flush global) The only difference is the label in the block rule.
Actually, it is even weirder. Sometimes it works, sometimes it doesn't. I'm confused, at this point.