$npx -y skills add Lonsdale201/wp-agent-skills --skill br-network-securityConfigure Better Route 1.1 trusted-proxy client IP resolution and CIDR allowlists. Use behind Cloudflare, nginx, load balancers, or reverse proxies when authorization, rate limiting, or audit data depends on the real client IP.
| 1 | # Better Route network security |
| 2 | |
| 3 | Never trust a forwarded-IP header merely because it exists. Configure every proxy hop that your infrastructure controls. |
| 4 | |
| 5 | ```php |
| 6 | use BetterRoute\Middleware\Network\IpAllowlistMiddleware; |
| 7 | use BetterRoute\Middleware\Network\TrustedProxyClientIpResolver; |
| 8 | |
| 9 | $resolver = new TrustedProxyClientIpResolver( |
| 10 | trustedProxyCidrs: ['10.0.0.0/24', '2001:db8:1234::/48'], |
| 11 | forwardedHeaders: ['CF-Connecting-IP', 'X-Forwarded-For'] |
| 12 | ); |
| 13 | |
| 14 | $allowlist = new IpAllowlistMiddleware( |
| 15 | allowedCidrs: ['203.0.113.0/24'], |
| 16 | ipResolver: $resolver, |
| 17 | failClosed: true |
| 18 | ); |
| 19 | |
| 20 | $router->post('/back-channel/event', $handler) |
| 21 | ->middleware([$allowlist]) |
| 22 | ->protectedByMiddleware('ipAllowlist'); |
| 23 | ``` |
| 24 | |
| 25 | ## Resolution contract |
| 26 | |
| 27 | - If `REMOTE_ADDR` is invalid or absent, resolution returns `null`. |
| 28 | - If `REMOTE_ADDR` is not a trusted proxy, it is the client address and all forwarded headers are ignored. |
| 29 | - If the immediate peer is trusted, the resolver checks configured headers in order. |
| 30 | - For a comma-separated forwarding chain it walks right-to-left and returns the closest address that is not one of the configured trusted proxies. This avoids trusting a client-injected leftmost value behind an appending proxy. |
| 31 | - When no usable untrusted forwarded address exists, it falls back to `REMOTE_ADDR`. |
| 32 | |
| 33 | The header order is a trust decision. Prefer a provider-specific, overwriting header only when the immediate trusted proxy is guaranteed to set and scrub it. Otherwise use the forwarding-chain semantics and document the proxy topology. |
| 34 | |
| 35 | ## Rules |
| 36 | |
| 37 | - Keep `failClosed: true` for access control. |
| 38 | - Treat an IP allowlist as defense in depth, not the only proof for a sensitive webhook. Combine it with HMAC or another authentication method. |
| 39 | - Use the same resolver for allowlisting, rate-limit identity, and audit enrichment to avoid contradictory client identities. |
| 40 | - Update trusted proxy ranges through a controlled deployment process; never accept them from request input. |
| 41 | - Test direct requests with spoofed headers, trusted and untrusted immediate peers, IPv4/IPv6 CIDRs, malformed chains, multiple trusted hops, and all-hops-trusted fallback. |
| 42 | |
| 43 | Source references: `src/Middleware/Network/TrustedProxyClientIpResolver.php`, `src/Middleware/Network/CidrMatcher.php`, `src/Middleware/Network/IpAllowlistMiddleware.php`. |
| 44 | |
| 45 | ## References |
| 46 | |
| 47 | - Official documentation: <https://lonsdale201.github.io/better-docs/docs/better-route/agents> |