Closed slimhazard closed 7 years ago
Ugh, the test for blocking has some timing dependencies, which probably accounts for the travis fail. I'll try to build in longer delays -- it'll make the test last longer, but I'm guessing that's what it needs.
I don't suppose there's any way to look inside the test log after a Travis run?
OK that did it, I hadn't been testing against Varnish 4.1.
Merged.
Thanks @slimhazard
This changes the signature of
is_denied()
to add theblock
parameter:When
block
> 0s, then after the threshold is reached, always return true for the duration ofblock
. This is a way to completely lock out a particularly troublesome client for a period of time, rather than letting them slip back in occasionally when the request rate slips below the threshold.The default value of
block
is 0s. So existing deployments of the VMOD can continue using it without changes.block
becomes one of the hashed elements that identify a token bucket. (Otherwise, different invocations with the same values for the other three params but with different blocks could pick up someone else's block, and get blocked spuriously.) Soblock
is also a new optional param forremaining()
, also with the default value 0s.Further add a new function
blocked()
:For the token bucket identified by the four params, return the amount of time remaining in a pending block, or 0s if no block is pending.
We had to cook this up in a pinch to help a customer who was facing a DOS attack. The VMOD with these additions is running in production now and is doing what it's expected to do.
This PR contains a bit more commits than it needs to, and I'm willing to squash a few of them if you decide to accept it. You could also pick what parts you like.
The first commit adds the new param to
is_denied()
andremaining()
, and the third commit is a bugfix for it. These can be squashed.The second commit adds the
blocked()
function, and the 5th and 6th commits are bugfixes that can be squashed with it.The fourth commit changes the algorithm when a block is in effect. Originally, I had it just stop counting down tokens during that time, so the token countdown began anew when the block expired. With this change, the token countdown goes on during the block, so that if the request rate is high enough, a client may be immediately denied and blocked again after a block expires. So this aggressively locks out a client who keeps up a high request rate.
If you like it that way, the fourth commit can be squashed with the other ones for
is_denied()
andremaining()
.So your choices are:
is_denied()
andremaining()
, with or without the more aggressive blocking strategy.blocked()
function as well.But I hope you like it. %^)