ratelimit

package module
v0.0.0-...-0f18ffa Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 17, 2026 License: MIT Imports: 17 Imported by: 0

README

ratelimit

A Caddy v2 extension to apply IP-based rate-limiting for HTTP requests. Optionally, block offending IPs via a Cloudflare Custom List when the rate limit is exceeded.

Features

  • Powerful and configurable rate limiting by IP or request property (see placeholders).
  • Cloudflare Integration: Automatically add violating client IPs to a specified Cloudflare IP Custom List via the Cloudflare API (optional). The module will also remove IPs from the list automatically 20 seconds after being added for fast, self-healing blocks.

Installation

$ xcaddy build --with github.com/HellDarkK/caddy-cfrl/ratelimit

Caddyfile Syntax

rate_limit [<matcher>] <key> <rate> [<zone_size> [<reject_status>]] {
    cloudflare {
        api_token <api_token>
        account_id <account_id>
        list_id   <list_id>
    }
}

Parameters:

  • <key>: The variable to uniquely identify a client. Supported variables (Caddy shorthand placeholders):
    • {path.<var>}
    • {query.<var>}
    • {header.<VAR>}
    • {cookie.<var>}
    • {body.<var>} (requires the requestbodyvar extension)
    • {remote.host} (ignores the X-Forwarded-For header)
    • {remote.port}
    • {remote.ip} (prefers the first IP in the X-Forwarded-For header)
    • {remote.host_prefix.<bits>} (CIDR block version)
    • {remote.ip_prefix.<bits>} (CIDR block version)
  • <rate>: The request rate limit (per client key) as Nr/s or Nr/m (requests per second/minute).
  • <zone_size>: Max number of key values (LRU zone).
  • <reject_status>: HTTP status code to return when limited (default: 429).

Example: Basic Rate Limiting

localhost:8080 {
    route /foo {
        rate_limit {remote.ip} 2r/m
        respond 200
    }
}

Limits /foo route to 2 requests/minute per IP. Exceeding the limit gets a 429 response.


Example: With Cloudflare Integration

localhost:8080 {
    route /api {
        rate_limit {remote.ip} 5r/m {
            cloudflare {
                api_token <YOUR_API_TOKEN>
                account_id <YOUR_ACCOUNT_ID>
                list_id   <YOUR_LIST_ID>
            }
        }
        respond 200
    }
}
  • When a client exceeds the specified rate, their IP will be added to the specified Cloudflare List.
  • Their IP will be automatically removed from the list 20 seconds later (removal is also handled by the module; errors are logged).
  • The Cloudflare API call is asynchronous and errors are logged to the Caddy log.

Cloudflare Setup Guide

  1. Create an IP Custom List:
    • Go to Cloudflare Dashboard.
    • Choose your account, go to Lists > IP Lists > Create List.
    • Give the list a name and note the List ID after creation.
  2. Generate an API Token:
    • Go to My Profile > API Tokens > Create Token.
    • Required permissions:
      • Zone > Lists: Edit
      • Account > Lists: Edit
    • Scope the token as narrowly as possible.
    • Keep your API token secret.
  3. Find Your Account ID:
    • Account ID is in the dashboard URL or account settings.

Security & Operational Notes

  • Cloudflare integration is optional; omit the cloudflare block if you don't want to block list IPs.
  • If Cloudflare API calls fail, requests are still rate-limited; blocking is best effort and errors are logged.
  • Rate limiting can be evaded by IP rotation if {remote.ip} is used. Use other keys as needed.
  • Ensure you comply with Cloudflare List API rate limits see docs.

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type CloudflareConfig

type CloudflareConfig struct {
	APIToken  string `json:"api_token,omitempty"`
	AccountID string `json:"account_id,omitempty"`
	ListID    string `json:"list_id,omitempty"`
}

CloudflareConfig holds the configuration for Cloudflare integration.

type RateLimit

type RateLimit struct {
	// The variable used to differentiate one client from another.
	//
	// Currently supported variables:
	//
	// - `{path.<var>}`
	// - `{query.<var>}`
	// - `{header.<VAR>}`
	// - `{cookie.<var>}`
	// - `{body.<var>}` (requires the [requestbodyvar](https://github.com/HellDarkK/caddy-cfrl/tree/master/requestbodyvar) extension)
	// - `{remote.host}` (ignores the `X-Forwarded-For` header)
	// - `{remote.port}`
	// - `{remote.ip}` (prefers the first IP in the `X-Forwarded-For` header)
	// - `{remote.host_prefix.<bits>}` (CIDR block version of `{remote.host}`)
	// - `{remote.ip_prefix.<bits>}` (CIDR block version of `{remote.ip}`)
	Key string `json:"key,omitempty"`

	// The request rate limit (per key value) specified in requests
	// per second (r/s) or requests per minute (r/m).
	Rate string `json:"rate,omitempty"`

	// The size (i.e. the number of key values) of the LRU zone that
	// keeps states of these key values. Defaults to 10,000.
	ZoneSize int `json:"zone_size,omitempty"`

	// The HTTP status code of the response when a client exceeds the rate.
	// Defaults to 429 (Too Many Requests).
	RejectStatusCode int `json:"reject_status,omitempty"`

	// Cloudflare configuration for adding blocked IPs to a list.
	Cloudflare *CloudflareConfig `json:"cloudflare,omitempty"`
	// contains filtered or unexported fields
}

RateLimit implements a handler for rate-limiting.

If a client exceeds the rate limit, an HTTP error with status `<reject_status>` will be returned. This error can be handled using the conventional error handlers. See [handle_errors](https://caddyserver.com/docs/caddyfile/directives/handle_errors) for how to set up error handlers.

func (RateLimit) CaddyModule

func (RateLimit) CaddyModule() caddy.ModuleInfo

CaddyModule returns the Caddy module information.

func (*RateLimit) Cleanup

func (rl *RateLimit) Cleanup() error

Cleanup cleans up the resources made by rl during provisioning.

func (*RateLimit) Provision

func (rl *RateLimit) Provision(ctx caddy.Context) (err error)

Provision implements caddy.Provisioner.

func (*RateLimit) ServeHTTP

func (rl *RateLimit) ServeHTTP(w http.ResponseWriter, r *http.Request, next caddyhttp.Handler) error

ServeHTTP implements caddyhttp.MiddlewareHandler.

func (*RateLimit) UnmarshalCaddyfile

func (rl *RateLimit) UnmarshalCaddyfile(d *caddyfile.Dispenser) (err error)

func (*RateLimit) Validate

func (rl *RateLimit) Validate() error

Validate implements caddy.Validator.

type Var

type Var struct {
	Raw  string
	Name string
	Bits int
}

func ParseVar

func ParseVar(s string) (*Var, error)

ParseVar transforms shorthand variables into Caddy-style placeholders.

Examples for shorthand variables:

- `{path.<var>}` - `{query.<var>}` - `{header.<VAR>}` - `{cookie.<var>}` - `{body.<var>}` - `{remote.host}` - `{remote.port}` - `{remote.ip}` - `{remote.host_prefix.<bits>}` - `{remote.ip_prefix.<bits>}`

func (*Var) Evaluate

func (v *Var) Evaluate(r *http.Request) (value string, err error)

type Zone

type Zone struct {
	// contains filtered or unexported fields
}

func NewZone

func NewZone(size int, rateSize time.Duration, rateLimit int64) (*Zone, error)

func (*Zone) Allow

func (z *Zone) Allow(key string) bool

func (*Zone) Purge

func (z *Zone) Purge()

Purge is used to completely clear the zone.

func (*Zone) RateLimitPolicyHeader

func (z *Zone) RateLimitPolicyHeader() string

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL