5

I'd like to block access to Google search using PF after the threshold of 17500 requests (connection established) in 24h, from a host running FreeBSD 9.

What I came up with, after reading pf-faq is this rule:

pass out on $net proto tcp from any to 'www.google.com' port www flags S/SA keep state (max-src-conn 200, max-src-conn-rate 17500/86400)

NOTE: 86400 are 24h in seconds.

The rule should work, but PF is smart enough to know that www.google.com resolves in 5 different IPs. So my pfctl -sr output gives me this:

pass out on vte0 inet proto tcp from any to 173.194.44.81 port = http flags S/SA keep state (source-track rule, max-src-conn 200, max-src-conn-rate 17500/86400, src.track 86400)
pass out on vte0 inet proto tcp from any to 173.194.44.82 port = http flags S/SA keep state (source-track rule, max-src-conn 200, max-src-conn-rate 17500/86400, src.track 86400)
pass out on vte0 inet proto tcp from any to 173.194.44.83 port = http flags S/SA keep state (source-track rule, max-src-conn 200, max-src-conn-rate 17500/86400, src.track 86400)
pass out on vte0 inet proto tcp from any to 173.194.44.80 port = http flags S/SA keep state (source-track rule, max-src-conn 200, max-src-conn-rate 17500/86400, src.track 86400)
pass out on vte0 inet proto tcp from any to 173.194.44.84 port = http flags S/SA keep state (source-track rule, max-src-conn 200, max-src-conn-rate 17500/86400, src.track 86400)

PF creates 5 different rules, 1 for each IP that Google resolves. However I have the sense - without being 100% sure, I didn't had the chance to test it - that the number 17500/86400 applies for each IP. If that's the case - please confirm - then it's not what I want.

In pf-faq there's another option called source-track-global:

source-track

This option enables the tracking of number of states created per source IP
address. This option has two formats:

  + source-track rule - The maximum number of states created by this rule
    is limited by the rule's max-src-nodes and max-src-states options.
    Only state entries created by this particular rule count toward the
    rule's limits.

  + source-track global - The number of states created by all rules that
    use this option is limited. Each rule can specify different
    max-src-nodes and max-src-states options, however state entries
    created by any participating rule count towards each individual rule's
    limits.

The total number of source IP addresses tracked globally can be controlled
via the src-nodes runtime option.

I tried to apply source-track-global in the above rule without success. How can I use this option in order to achieve my goal?

Any thoughts or comments are more than welcome since I'm an amateur and don't fully understand PF yet.

Thanks

atmosx
  • 189
  • 1
  • 9
  • Can you elaborate on *without success*? Do you get error message? Or does it has no effect? Post your pf.conf if possible (mask all real external ip). – John Siu Nov 10 '12 at 01:39
  • "source-track-global" is not made for that sort of thing. It doesn't work by accumulating data from each different ip. I changed my pf.conf since then, but I can look at my backups if you wanna know the details. – atmosx Nov 12 '12 at 13:23

1 Answers1

4

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
michele
  • 575
  • 3
  • 7