Block Google requests to 16k using pf firewall

The source-track option does apply per-rule, so you are not restricting "Google to X req/day", you are restricting each individual address to that limit.

I give you two solutions here. One is simple and approximate, the other is harder and sharper.

Solution 1

Transform the condition so as to match all servers of interest in one rule. The simplest approach is to use a CIDR specification, e.g.:

pass out on vte0 inet proto tcp from any to 173.194.44.80/29 port http keep state (source-track rule, max-src-conn 200, max-src-conn-rate 17500/86400, src.track 86400)

This matches hosts 173.194.44.80 through 173.194.44.86: two more than you want. You get 99% of the goal with 10% of the complexity. For most cases I would go this way. This specific case is particular because Google is one of the 2-3 organizations in the world to own a manifold netblocks and to often reappoint their addresses. For handling google, yahoo etc I wouldn't go for this solution.

Solution 2

Use tag, a very own beauty of PF. Tags allow you to stick a note on a packet and apply rules later on based on it. Here's an example for your case:

pass out on vte0 proto tcp from any to 'www.google.com' port http tag TOGOOGLE pass out quick on vte0 proto tcp tagged TOGOOGLE keep state (source-track rule, max-src-conn 200, max-src-conn-rate 17500/86400, src.track 86400)

Side notes

  • you need no longer flags S/SA: it's default for stateful connections
  • specifying firewall rules that match by hostname is dangerous