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.