github.com/letsencrypt/boulder@v0.20251208.0/ratelimits/README.md (about) 1 # Configuring and Storing Key-Value Rate Limits 2 3 ## Rate Limit Structure 4 5 All rate limits use a token-bucket model. The metaphor is that each limit is 6 represented by a bucket which holds tokens. Each request removes some number of 7 tokens from the bucket, or is denied if there aren't enough tokens to remove. 8 Over time, new tokens are added to the bucket at a steady rate, until the bucket 9 is full. The _burst_ parameter of a rate limit indicates the maximum capacity of 10 a bucket: how many tokens can it hold before new ones stop being added. 11 Therefore, this also indicates how many requests can be made in a single burst 12 before a full bucket is completely emptied. The _count_ and _period_ parameters 13 indicate the rate at which new tokens are added to a bucket: every period, count 14 tokens will be added. Therefore, these also indicate the steady-state rate at 15 which a client which has exhausted its quota can make requests: one token every 16 (period / count) duration. 17 18 ## Default Limit Settings 19 20 Each key directly corresponds to a `Name` enumeration as detailed in `//ratelimits/names.go`. 21 The `Name` enum is used to identify the particular limit. The parameters of a 22 default limit are the values that will be used for all buckets that do not have 23 an explicit override (see below). 24 25 ```yaml 26 NewRegistrationsPerIPAddress: 27 burst: 20 28 count: 20 29 period: 1s 30 NewOrdersPerAccount: 31 burst: 300 32 count: 300 33 period: 180m 34 ``` 35 36 ## Override Limit Settings 37 38 Each entry in the override list is a map, where the key is a limit name, 39 corresponding to the `Name` enum of the limit, and the value is a set of 40 overridden parameters. These parameters are applicable to a specific list of IDs 41 included in each entry. It's important that the formatting of these IDs matches 42 the ID format associated with their respective limit's `Name`. For more details on 43 the relationship of ID format to limit `Name`s, please refer to the documentation 44 of each `Name` in the `//ratelimits/names.go` file or the [ratelimits package 45 documentation](https://pkg.go.dev/github.com/letsencrypt/boulder/ratelimits#Name). 46 47 ```yaml 48 - NewRegistrationsPerIPAddress: 49 burst: 20 50 count: 40 51 period: 1s 52 ids: 53 - 10.0.0.2 54 - 10.0.0.5 55 - NewOrdersPerAccount: 56 burst: 300 57 count: 600 58 period: 180m 59 ids: 60 - 12345678 61 - 87654321 62 ``` 63 64 The above example overrides the default limits for specific subscribers. In both 65 cases the count of requests per period are doubled, but the burst capacity is 66 explicitly configured to match the default rate limit. 67 68 ### Id Formats in Limit Override Settings 69 70 Id formats vary based on the `Name` enumeration. Below are examples for each 71 format: 72 73 #### ipAddress 74 75 A valid IPv4 or IPv6 address. 76 77 Examples: 78 - `10.0.0.1` 79 - `2001:0db8:0000:0000:0000:ff00:0042:8329` 80 81 #### ipv6RangeCIDR 82 83 A valid IPv6 range in CIDR notation with a /48 mask. A /48 range is typically 84 assigned to a single subscriber. 85 86 Example: `2001:0db8:0000::/48` 87 88 #### regId 89 90 An ACME account registration ID. 91 92 Example: `12345678` 93 94 #### identValue 95 96 A valid ACME identifier value, i.e. an FQDN or IP address. 97 98 Examples: 99 - `www.example.com` 100 - `192.168.1.1` 101 - `2001:db8:eeee::1` 102 103 #### domainOrCIDR 104 105 A valid eTLD+1 domain name, or an IP address. IPv6 addresses must be the lowest 106 address in their /64, i.e. their last 64 bits must be zero; the override will 107 apply to the entire /64. Do not include the CIDR mask. 108 109 Examples: 110 - `example.com` 111 - `192.168.1.0` 112 - `2001:db8:eeee:eeee::` 113 114 #### fqdnSet 115 116 A comma-separated list of identifier values. 117 118 Example: `192.168.1.1,example.com,example.org` 119 120 ## Bucket Key Definitions 121 122 A bucket key is used to lookup the bucket for a given limit and 123 subscriber. Bucket keys are formatted similarly to the overrides but with a 124 slight difference: the limit Names do not carry the string form of each limit. 125 Instead, they apply the `Name` enum equivalent for every limit. 126 127 So, instead of: 128 129 ``` 130 NewOrdersPerAccount:12345678 131 ``` 132 133 The corresponding bucket key for regId 12345678 would look like this: 134 135 ``` 136 6:12345678 137 ``` 138 139 When loaded from a file, the keys for the default/override limits undergo the 140 same interning process as the aforementioned subscriber bucket keys. This 141 eliminates the need for redundant conversions when fetching each 142 default/override limit. 143 144 ## How Limits are Applied 145 146 Although rate limit buckets are configured in terms of tokens, we do not 147 actually keep track of the number of tokens in each bucket. Instead, we track 148 the Theoretical Arrival Time (TAT) at which the bucket will be full again. If 149 the TAT is in the past, the bucket is full. If the TAT is in the future, some 150 number of tokens have been spent and the bucket is slowly refilling. If the TAT 151 is far enough in the future (specifically, more than `burst * (period / count)`) 152 in the future), then the bucket is completely empty and requests will be denied. 153 154 Additional terminology: 155 156 - **burst offset** is the duration of time it takes for a bucket to go from 157 empty to full (`burst * (period / count)`). 158 - **emission interval** is the interval at which tokens are added to a bucket 159 (`period / count`). This is also the steady-state rate at which requests can 160 be made without being denied even once the burst has been exhausted. 161 - **cost** is the number of tokens removed from a bucket for a single request. 162 - **cost increment** is the duration of time the TAT is advanced to account 163 for the cost of the request (`cost * emission interval`). 164 165 For the purposes of this example, subscribers originating from a specific IPv4 166 address are allowed 20 requests to the newFoo endpoint per second, with a 167 maximum burst of 20 requests at any point-in-time, or: 168 169 ```yaml 170 - NewFoosPerIPAddress: 171 burst: 20 172 count: 20 173 period: 1s 174 ids: 175 - 172.23.45.22 176 ``` 177 178 A subscriber calls the newFoo endpoint for the first time with an IP address of 179 172.23.45.22. Here's what happens: 180 181 1. The subscriber's IP address is used to generate a bucket key in the form of 182 'NewFoosPerIPAddress:172.23.45.22'. 183 184 2. The request is approved and the 'NewFoosPerIPAddress:172.23.45.22' bucket is 185 initialized with 19 tokens, as 1 token has been removed to account for the 186 cost of the current request. To accomplish this, the initial TAT is set to 187 the current time plus the _cost increment_ (which is 1/20th of a second if we 188 are limiting to 20 requests per second). 189 190 3. Bucket 'NewFoosPerIPAddress:172.23.45.22': 191 - will reset to full in 50ms (1/20th of a second), 192 - will allow another newFoo request immediately, 193 - will allow between 1 and 19 more requests in the next 50ms, 194 - will reject the 20th request made in the next 50ms, 195 - and will allow 1 request every 50ms, indefinitely. 196 197 The subscriber makes another request 5ms later: 198 199 4. The TAT at bucket key 'NewFoosPerIPAddress:172.23.45.22' is compared against 200 the current time and the _burst offset_. The current time is greater than the 201 TAT minus the cost increment. Therefore, the request is approved. 202 203 5. The TAT at bucket key 'NewFoosPerIPAddress:172.23.45.22' is advanced by the 204 cost increment to account for the cost of the request. 205 206 The subscriber makes a total of 18 requests over the next 44ms: 207 208 6. The current time is less than the TAT at bucket key 209 'NewFoosPerIPAddress:172.23.45.22' minus the burst offset, thus the request 210 is rejected. 211 212 This mechanism allows for bursts of traffic but also ensures that the average 213 rate of requests stays within the prescribed limits over time.