Skip to content
Development
Skill

/proxy-client-address

Forward the real client address from a server-side proxy to a backend without trusting forgeable headers. Use when an API behind a BFF or reverse proxy rate-limits or audits every user as one address.

From plugin
dotclaude
586 skills1 agent1 command

Claude Code

$ npx -y skills add KhaledSaeed18/dotclaude --skill proxy-client-address --agent claude-code

SKILL.md

proxy-client-address.SKILL.md
name: proxy-client-address
description: Forward the real client address from a server-side proxy to a backend without trusting forgeable headers. Use when an API behind a BFF or reverse proxy rate-limits or audits every user as one address.
argument-hint: "(optional) the front-end proxy file and the backend's middleware"

When a browser calls a front-end server that forwards to an API, the API's peer is the front-end for every user: one rate-limit bucket and one audit address for everyone. Fix it with a named address the API believes only next to a shared secret, derived from the one forwarded header the edge proxy wrote itself.

Hard rules: never break these

  • **Never trust `X-Forwarded-For` from the client side.** Only the entry the edge proxy appended is real; confirm which entry that is for the proxy in front of you before relying on it.
  • **The secret is runtime, server-only, identical on both sides,** generated by the owner (`openssl rand -base64 32`), pasted into both deployments, never in a repository or a client bundle.
  • **Strip the headers on the way in.** The front-end deletes any `x-<app>-proxy-secret` or `x-<app>-client-ip` a browser sent before setting its own; the API deletes both after reading them.
  • **Compare the secret in constant time** on digests, so length and content leak nothing.
  • **Without the secret, behave as before.** The front-end falls back to the plain rewrite; the API falls back to `req.ip`. Rollout is safe in any order.

Step 1: Establish the proxy's behaviour

Read the edge proxy's configuration (Traefik: `docker inspect coolify-proxy --format '{{json .Args}}' | grep -i forwarded`). With no trusted IPs configured, Traefik discards client-sent `X-Forwarded-*` and writes the peer address itself, so the **last** entry is the client; a platform edge behaves the same. If trusted IPs or `insecure` are set, the client's forged entries survive in front of the real one and the last entry is still the real one. A Node server does not append. Document the finding.

Step 2: Front-end side (the BFF)

In the Next.js proxy (or middleware), for `/api/*` requests: when the secret is configured, rewrite to the API origin with two added request headers, else return nothing and let `next.config` rewrites handle it. Server-side fetches (Server Components) add the same headers from `next/headers`. Snippets in [reference/snippets.md](./reference/snippets.md).

Step 3: API side

A middleware early in the chain: read both headers, delete them, verify the presented secret against the configured one on SHA-256 digests with `timingSafeEqual`, accept the named address only if it is a valid IP, else use `req.ip`. Store the result on the request (`req.clientIp`) and make the rate limiter's key generator and the audit writer read it. `trust proxy` stays set for `req.ip` to be meaningful behind the edge.

Step 4: Roll out and prove it

1. Ship both code sides (they are inert without the secret). 2. Owner sets `API_PROXY_SECRET` on the front-end app and `DASHBOARD_PROXY_SECRET` (or the chosen name) on the API, same value, then redeploys both. 3. Prove it: a request through the front-end to a non-existent API route with a forged `X-Forwarded-For: 203.0.113.9`, from two different networks, must be logged by the API with each real address; the same forged header plus a wrong secret sent straight to the API must be logged with the sender's address. The `deploy-verification` skill has the commands.

Report the proxy finding, the header names chosen, the variable names on each side, and the proof lines from the API log.

Read more
@khaledsaeed18
Ships withdotclaude

Reusable Claude Code extension registry. skills, subagents, slash commands, and hooks for engineering, git, testing, and security workflows. Distributed as a shadcn GitHub registry and as installable plugins.

586 skills1 agent
Get the whole plugin

Stars on GitHub

Momentum

stars in total
5
Star history of KhaledSaeed18/dotclaude on GitHub, a chart by star-history.com

Other skills on dotclaude.

academic-writing

academic-writing

Write or revise thesis and paper prose section by section (abstract, introduction, related work, method, results, discussion,…

bibtex-manager

bibtex-manager

Maintain the thesis .bib file as a single source of truth: fetch verified BibTeX from a DOI, arXiv id, or title via CrossRef and…

citation-graph

citation-graph

Expand a set of key papers into the literature around them by walking the citation graph with the Semantic Scholar and OpenAlex…

citation-verifier

citation-verifier

Audit every citation in a chapter, paper, or proposal against the .bib file and the real world: each cite key must exist, each…

More skills from other plugins.

brainstorming
Auto-invoked

brainstorming

You MUST use this before any creative work - creating features, building components, adding functionality, modifying behavior, or…

@obra@obraInstall Skill
ask-matt

ask-matt

Ask which skill or flow fits your situation. A router over the skills in this repo.

skills10d309k
@mattpocock@mattpocockInstall Skill
accessibility
Auto-invoked

accessibility

Design, implement, and audit accessible UI to WCAG 2.2 Level AA across Web, iOS, and Android — semantic ARIA roles and labels,…

ecc12d293k
@affaan-m@affaan-mInstall Skill
compiler-commit

compiler-commit

Use when you want to verify compiler changes and commit with the correct convention. Runs tests, lint, and format, then commits…

react1d252k
@facebook@facebookInstall Skill

Questions about proxy-client-address.

Which coding agents can use proxy-client-address?
proxy-client-address installs in Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot, OpenCode and Windsurf with the skills CLI, using each agent's flag shown on this page. Flowy's auto-invocation, which fires a skill when your prompt matches, runs in Claude Code only.