Skip to content

feat(dns): per-identity rate limiting on DoH endpoints - #65

Merged
PenguinzTech merged 1 commit into
v2.1.xfrom
feature/doh-rate-limiting
Jul 27, 2026
Merged

feat(dns): per-identity rate limiting on DoH endpoints#65
PenguinzTech merged 1 commit into
v2.1.xfrom
feature/doh-rate-limiting

Conversation

@PenguinzTech

@PenguinzTech PenguinzTech commented Jul 25, 2026

Copy link
Copy Markdown
Contributor

Per-identity rate limiting on the DoH data plane (dns-server/app). Async token-bucket keyed by verified JWT sub → SPIFFE ID → client IP; in-memory backend with 10k-key LRU cap (IP churn can't exhaust memory) + optional Valkey fixed-window backend (SQUAWK_RATE_LIMIT_BACKEND=valkey). Off by default (SQUAWK_RATE_LIMIT_ENABLED, default RPS 50 / burst 100); over-limit → 429 + Retry-After. Prometheus counters labeled by key type only — no identity values in labels.

Tests: 48 green (27 unit + 11 integration; injected clock, no sleeps).

Stack note: bases on chore/dedup-reusable-code (top of the #53#59 chain); auto-retargets toward v2.1.x as the stack merges bottom-up.

🤖 Generated with Claude Code

Summary by Sourcery

Add configurable per-identity rate limiting to the DNS DoH server with metrics and status reporting.

New Features:

  • Introduce a rate limiter service with in-memory token-bucket and optional Valkey backend for per-identity request control.
  • Integrate rate limiting into the /dns/query endpoint using JWT subject or client IP as the identity key, returning 429 with Retry-After when over limit.
  • Expose rate limiting configuration via environment variables and surface current limiter stats on the /status endpoint.

Enhancements:

  • Extend Prometheus metrics to track rate-limit checks and exceeded events by identity type without exposing specific identities.

Tests:

  • Add comprehensive unit tests for the rate limiter, backends, and token bucket plus integration tests for DoH endpoint behavior under rate limiting.

Adds token-bucket rate limiting for DoH /dns/query endpoint with:
- Per-identity tracking (JWT subject → SPIFFE ID → client IP)
- In-memory backend with LRU eviction (10k keys default)
- Optional Valkey backend via SQUAWK_RATE_LIMIT_BACKEND=valkey
- Configurable RPS and burst via env vars (default 50 RPS, 100 burst)
- 429 responses with Retry-After header when limited
- Disabled by default (SQUAWK_RATE_LIMIT_ENABLED=false)
- Prometheus metrics for allowed/limited requests by identity type
- Comprehensive async test coverage (27 tests, 100% pass)

No overhead when disabled (single boolean check).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@PenguinzTech PenguinzTech self-assigned this Jul 25, 2026
@sourcery-ai

sourcery-ai Bot commented Jul 25, 2026

Copy link
Copy Markdown

🧙 Sourcery is reviewing your pull request!


Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry @PenguinzTech, you have reached your weekly rate limit of 500000 diff characters.

Please try again later or upgrade to continue using Sourcery

@PenguinzTech
PenguinzTech changed the base branch from chore/dedup-reusable-code to v2.1.x July 27, 2026 00:55
@PenguinzTech
PenguinzTech merged commit fea04d4 into v2.1.x Jul 27, 2026
3 of 4 checks passed
PenguinzTech added a commit that referenced this pull request Jul 27, 2026
- dns-server/app/main.py: combined imports -- this branch's
  domain_policy/jwt_verify additions plus already-merged #65's
  rate-limit config vars and RateLimiter import. Also removed a
  redundant local re-import of verify_squawk_jwt/JWT_PUBLIC_KEY
  (leftover from #65's original code) that was shadowing the combined
  module-level import and tripping flake8's F401 check.
- dns-server/app/services/prometheus_metrics.py: combined two
  independent new methods (record_policy_denial from this branch,
  record_rate_limited_query from #65) on the same metrics class --
  their backing Counter definitions survived the auto-merge intact.
- manager/backend/app/services/auth_service.py: auto-merged cleanly
  but silently dropped the `List` import from typing while THIS
  branch's new allowed_domains: Optional[List[str]] parameter still
  uses it -- classic silent-auto-merge risk. Restored.

Full manager suite: 264/264 passing. dns-server: 112/112 real tests
passing (8 rate-limiter test errors are a pre-existing bug already
fixed in #77, not yet in this branch's v2.1.x snapshot -- will
re-verify after pulling latest v2.1.x).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant