1VMOD_VSTHROTTLE(3)                                          VMOD_VSTHROTTLE(3)
2
3
4

NAME

6       vmod_vsthrottle - Throttling VMOD
7

SYNOPSIS

9          import vsthrottle [as name] [from "path"]
10
11          BOOL is_denied(STRING key, INT limit, DURATION period, DURATION block)
12
13          VOID return_token(STRING key, INT limit, DURATION period, DURATION block)
14
15          INT remaining(STRING key, INT limit, DURATION period, DURATION block)
16
17          DURATION blocked(STRING key, INT limit, DURATION period, DURATION block)
18
19          VOID remove_bucket(STRING key, INT limit, DURATION period, DURATION block)
20

DESCRIPTION

22       A  Varnish  vmod  for rate-limiting traffic on a single Varnish server.
23       Offers a simple interface for throttling traffic on a per-key basis  to
24       a specific request rate.
25
26       Keys  can  be specified from any VCL string, e.g. based on client.ip, a
27       specific cookie value, an API token, etc.
28
29       The request rate is specified as the number of requests permitted  over
30       a period. To keep things simple, this is passed as two separate parame‐
31       ters, 'limit' and 'period'.
32
33       If an optional duration 'block' is specified, then access is denied al‐
34       together  for that period of time after the rate limit is reached. This
35       is a way to entirely turn away a  particularly  troublesome  source  of
36       traffic  for  a while, rather than let them back in as soon as the rate
37       slips back under the threshold.
38
39       This VMOD implements a token bucket algorithm.  State  associated  with
40       the token bucket for each key is stored in-memory using BSD's red-black
41       tree implementation.
42
43       Memory usage is around 100 bytes per key tracked.
44
45       Example:
46
47          vcl 4.0;
48          import vsthrottle;
49
50          backend default { .host = "192.0.2.11"; .port = "8080"; }
51
52          sub vcl_recv {
53              # Varnish will set client.identity for you based on client IP.
54
55              if (vsthrottle.is_denied(client.identity, 15, 10s, 30s)) {
56                  # Client has exceeded 15 reqs per 10s.
57                  # When this happens, block altogether for the next 30s.
58                  return (synth(429, "Too Many Requests"));
59              }
60
61              # There is a quota per API key that must be fulfilled.
62              if (vsthrottle.is_denied("apikey:" + req.http.Key, 30, 60s)) {
63                      return (synth(429, "Too Many Requests"));
64              }
65
66              # Only allow a few POST/PUTs per client.
67              if (req.method == "POST" || req.method == "PUT") {
68                  if (vsthrottle.is_denied("rw" + client.identity, 2, 10s)) {
69                      return (synth(429, "Too Many Requests"));
70                  }
71              }
72          }
73
74   BOOL is_denied(STRING key, INT limit, DURATION period, DURATION block)
75          BOOL is_denied(
76             STRING key,
77             INT limit,
78             DURATION period,
79             DURATION block=0
80          )
81
82       Arguments:
83
84          • key: A unique identifier to define what is being throttled -  more
85            examples below
86
87          • limit: How many requests in the specified period
88
89          • period: The time period
90
91          • block:  a  period  to deny all access after hitting the threshold.
92            Default is 0s
93
94       Description
95              Can be used to rate limit the traffic for a specific  key  to  a
96              maximum  of  'limit' requests per 'period' time. If 'block' is >
97              0s, (0s by default), then always deny for 'key' for that  length
98              of time after hitting the threshold.
99
100              Note:  A  token  bucket is uniquely identified by the 4-tuple of
101              its key, limit, period and block, so using the same key multiple
102              places with different rules will create multiple token buckets.
103
104       Example
105
106                 sub vcl_recv {
107                         if (vsthrottle.is_denied(client.identity, 15, 10s)) {
108                                 # Client has exceeded 15 reqs per 10s
109                                 return (synth(429, "Too Many Requests"));
110                         }
111
112                         # ...
113                 }
114
115   VOID return_token(STRING key, INT limit, DURATION period, DURATION block)
116          VOID return_token(
117             STRING key,
118             INT limit,
119             DURATION period,
120             DURATION block=0
121          )
122
123       Arguments:
124
125              • Same arguments as is_denied()
126
127       Description
128              Increment (by one) the number of tokens in the specified bucket.
129              is_denied() decrements the bucket by one  token  and  return_to‐
130              ken() adds it back.  Using these two, you can effectively make a
131              token bucket act like a limit on concurrent requests instead  of
132              requests / time.
133
134              Note:  This function doesn't enforce anything, it merely credits
135              a token to appropriate bucket.
136
137              Warning: If streaming is enabled (beresp.do_stream = true) as it
138              is  by  default now, vcl_deliver() is called before the response
139              is sent to the client (who may download it slowly). Thus you may
140              credit  the  token  back  too early if you use return_token() in
141              vcl_backend_response().
142
143       Example
144
145                 sub vcl_recv {
146                         if (vsthrottle.is_denied(client.identity, 20, 20s)) {
147                                 # Client has more than 20 concurrent requests
148                                 return (synth(429, "Too Many Requests In Flight"));
149                         }
150
151                         # ...
152                 }
153
154                 sub vcl_deliver {
155                         vsthrottle.return_token(client.identity, 10, 10s);
156                 }
157
158   INT remaining(STRING key, INT limit, DURATION period, DURATION block)
159          INT remaining(
160             STRING key,
161             INT limit,
162             DURATION period,
163             DURATION block=0
164          )
165
166       Arguments:
167
168              • Same arguments as is_denied()
169
170       Description
171          Get the current number of tokens for a given token bucket. This  can
172          be  used to create a response header to inform clients of their cur‐
173          rent quota.
174
175       Example
176
177                 sub vcl_deliver {
178                    set resp.http.X-RateLimit-Remaining = vsthrottle.remaining(client.identity, 15, 10s);
179                 }
180
181   DURATION blocked(STRING key, INT limit, DURATION period, DURATION block)
182          DURATION blocked(
183             STRING key,
184             INT limit,
185             DURATION period,
186             DURATION block
187          )
188
189       Arguments:
190
191              • Same arguments as is_denied()
192
193       Description
194          If the token bucket identified  by  the  four  parameters  has  been
195          blocked  by  use of the 'block' parameter in 'is_denied()', then re‐
196          turn the time remaining in the block. If it is not  blocked,  return
197          0s.  This can be used to inform clients how long they will be locked
198          out.
199
200       Example
201
202                 sub vcl_deliver {
203                    set resp.http.Retry-After
204                            = vsthrottle.blocked(client.identity, 15, 10s, 30s);
205                 }
206
207   VOID remove_bucket(STRING key, INT limit, DURATION period, DURATION block)
208          VOID remove_bucket(
209             STRING key,
210             INT limit,
211             DURATION period,
212             DURATION block=0
213          )
214
215       Arguments:
216
217              • Same arguments as is_denied()
218
219       Description
220          Remove the token bucket identified by the four parameters, if it ex‐
221          ists.
222
223       Example
224
225                 sub vcl_deliver {
226                        vsthrottle.remove_bucket(client.identity, 15, 10s, 30s);
227                 }
228
229
230
231
232                                                            VMOD_VSTHROTTLE(3)
Impressum