Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
Dawid Ciepiela 5770571c15
Some checks failed
test_and_report / Test and report maintainability of ldap-cli (push) Failing after 1m1s
Adapt to Forgejo: Renovate preset, Forgejo CI
By scripts/github_to_forgejo.py in HomeLab.
2026-10-07 12:36:29 +00:00
.forgejo/workflows Adapt to Forgejo: Renovate preset, Forgejo CI 2026-10-07 12:36:29 +00:00
.github chore(deps): update actions/setup-go action to v7 2026-07-16 06:10:28 +00:00
v2 fix(deps): update module golang.org/x/sync to v0.23.0 2026-09-08 19:38:42 +00:00
.gitignore Initial commit 2026-02-16 12:59:24 +01:00
go.mod fix(deps): update module golang.org/x/sync to v0.23.0 2026-09-08 19:38:42 +00:00
go.sum fix(deps): update module golang.org/x/sync to v0.23.0 2026-09-08 19:38:42 +00:00
LICENSE Initial commit 2026-02-16 12:59:24 +01:00
provider.go fix: use fmt for generous parsing 2026-02-16 17:40:20 +01:00
provider_test.go fix: use fmt for generous parsing 2026-02-16 17:40:20 +01:00
README.md fix json marshalling for v2 2026-05-21 22:10:37 +02:00
renovate.json Adapt to Forgejo: Renovate preset, Forgejo CI 2026-10-07 12:36:29 +00:00
trustedproxies.go fix: support custom JSON providers in native JSON config 2026-05-20 17:41:34 +03:00
trustedproxies_test.go fix json marshalling for v2 2026-05-21 22:10:37 +02:00

caddy-cdn-ranges

Use CDN provider IP ranges as a trusted proxies source for Caddy.

This module periodically fetches IP ranges from the cdn-ranges providers list and exposes them to Caddy's trusted_proxies IP source.

Why use this module?

Trusted proxies are critical for applications behind reverse proxies or load balancers. This module automatically:

  • Fetches the latest IP ranges from major CDN and cloud providers
  • Updates them periodically to stay in sync with provider changes
  • Supports custom providers for specialized use cases
  • Filters by IPv4/IPv6 as needed
  • Handles concurrent fetches for performance

Features

  • Periodic refresh of CDN IP ranges (default: 24h).
  • Filter by provider name(s).
  • Custom provider support with JMESPath filtering and plain text handling.
  • IPv4 and/or IPv6 selection.
  • Concurrent fetching for faster updates.

Caddyfile usage

{
  servers {
    trusted_proxies {
      source cdn_ranges {
        interval 24h
        provider cloudflare cloudfront
        concurrency 5
        ipv4 true
        ipv6 true
      }
    }
  }
}

Custom provider block form:

{
  servers {
    trusted_proxies {
      source cdn_ranges {
        provider {
          cloudflare
          custom_cdn {
            ipv4_url https://example.com/ipv4
            ipv6_url https://example.com/ipv6 items
            asn_list [13335, 20940]
          }
        }
      }
    }
  }
}

JSON configuration example:

{
  "interval": "24h",
  "provider": [
    "cloudflare",
    {
      "custom_cdn": {
        "ipv4_url": ["https://example.com/ipv4.json", "prefixes[].cidr"],
        "ipv6_url": {
          "url": "https://example.com/ipv6.json",
          "jmespath": "prefixes[].cidr"
        },
        "asn_list": [13335, 20940]
      }
    }
  ],
  "concurrency": 5,
  "ipv4": true,
  "ipv6": true
}

The JSON shape mirrors the Caddyfile options:

  • provider can contain built-in provider names or custom provider objects.
  • Custom provider values support ipv4_url, ipv6_url, and asn_list.
  • ipv4_url and ipv6_url accept either [url, jmespath] arrays or { "url": ..., "jmespath": ... } objects.
  • asn_list accepts a JSON array of ASN numbers.

Custom Provider Configuration

Define custom providers inline in your Caddyfile to fetch from arbitrary sources:

JSON Response with JMESPath

If your provider returns JSON, use JMESPath to extract the IP list:

provider {
  my_custom_cdn {
    ipv4_url https://api.example.com/ipv4.json "prefixes[].cidr"
    ipv6_url https://api.example.com/ipv6.json "prefixes[].cidr"
  }
}

JMESPath examples:

  • @ (default): Return the entire response as-is (must be an array or string)
  • items: Extract the items array from the response
  • prefixes[].cidr: Extract the cidr field from each item in the prefixes array
  • data.networks: Navigate nested objects

See JMESPath Specification for more complex queries.

Plain Text Response

If your provider returns plain text (one IP per line), simply omit the JMESPath argument:

provider {
  my_static_list {
    ipv4_url https://example.com/ipv4.txt
    ipv6_url https://example.com/ipv6.txt
  }
}

Plain text responses automatically skip empty lines and lines starting with # or //.

Using ASN Lookups

Fetch prefixes for Autonomous System Numbers (ASNs):

provider {
  my_asn_provider {
    asn_list 13335 15169 8452
  }
}

Combining Multiple Sources

A single custom provider can combine ASNs, IPv4 URLs, and IPv6 URLs:

provider {
  all_sources {
    asn_list [13335, 20940]
    ipv4_url https://api.example.com/v4 "items[].network"
    ipv6_url https://api.example.com/v6 "items[].network"
  }
}

Directive options

  • provider <name...>: One or more provider names (space-separated). If omitted, all providers are used.

    • Short form: provider cloudflare cloudfront
    • Block form: provider { cloudflare custom { ... } }
  • provider { <name> { ... } }: Define custom providers inline. Each custom provider block can set:

    • ipv4_url <url> [jmespath]: Fetch IPv4 ranges from a URL. Uses JMESPath to extract CIDR blocks from JSON. For plain text, omit JMESPath. Default JMESPath is @ (return entire response).
    • ipv6_url <url> [jmespath]: Fetch IPv6 ranges from a URL. Uses JMESPath to extract CIDR blocks from JSON. For plain text, omit JMESPath. Default JMESPath is @ (return entire response).
    • asn_list <asn...>: Fetch ranges for one or more Autonomous System Numbers. Can be space-separated or comma-separated with brackets: asn_list 13335 20940 or asn_list [13335, 20940].
  • concurrency <number>: Number of concurrent provider fetches. Default: 5.

  • ipv4 <true|false>: Enable IPv4 ranges. Default: true.

  • ipv6 <true|false>: Enable IPv6 ranges. Default: true.

  • interval <duration>: Refresh interval. Default: 24h.

Provider names

Provider names come from the cdn-ranges library. Use the provider names listed in that project (see CDN Providers).

Built-in providers include:

  • cloudflare
  • cloudfront (AWS CloudFront)
  • And more — check the cdn-ranges repository for a complete list.

Troubleshooting

Module fails to fetch ranges

Check the logs for provider errors. Common causes:

  • Network timeouts or DNS failures
  • Invalid JMESPath in custom provider configuration
  • Provider returning an unexpected content type

Incorrect IP ranges returned

Verify your custom provider configuration:

  • Test the URL in your browser to see the response format
  • Verify the JMESPath extraction by testing it at jmespath.org
  • Ensure the response contains valid CIDR blocks (e.g., 192.0.2.0/24)

Performance concerns

If fetching takes too long:

  • Increase concurrency (default: 5)
  • Increase interval to fetch less frequently
  • Reduce the number of providers being fetched

Build with xcaddy or custom image

Use xcaddy to build a Caddy binary that includes this module:

xcaddy build \
  --with github.com/sarumaj/caddy-cdn-ranges/v2

Example Dockerfile that builds a custom Caddy image with this module:

FROM caddy:2.11-builder-alpine AS builder

WORKDIR /build

ENV GOTOOLCHAIN=go1.26.0

RUN xcaddy build \
  --with github.com/sarumaj/caddy-cdn-ranges/v2

FROM caddy:2.11-alpine
COPY --from=builder /build/caddy /usr/bin/caddy

Notes

  • The module reuses its fetched ranges for all requests until the next refresh.
  • If provider names are specified and none match, the module fails during provisioning.
  • Custom providers must return one of:
    • JSON (for JMESPath extraction)
    • Plain text with one CIDR block per line
  • Invalid CIDR blocks are rejected and will cause fetch failures. Ensure your data is well-formed.

License

See LICENSE.