Expand description
Trusted reverse proxies and the real client address
Behind a load balancer every connection comes from the proxy, and the client’s
address travels in X-Forwarded-For / Forwarded. Those headers are written
by clients too: a naive “take the first entry” lets anyone choose their own
address, which defeats rate limits, allow-lists and audit logs. The rule that
works: only believe the header when the connection comes from a proxy you
run, and read it from the right, skipping hops that are your own proxies.
use ullun::prelude::*;
use ullun::proxy::TrustedProxies;
App::new()
// the load balancers in front of this service
.trusted_proxies(TrustedProxies::new().trust("10.0.0.0/8").unwrap())
.get("/ip", |req: Request| async move {
Ok(Response::text(req.client_ip().map(|ip| ip.to_string()).unwrap_or_default()))
})
.run("0.0.0.0:3000")
.await
.unwrap();With trusted proxies configured:
Request::client_ipis the first address from the right that is not one of your proxies (Forwardedwins overX-Forwarded-For); from any other peer it is the peer address itself, whatever the headers sayRequest::is_securealso acceptsX-Forwarded-Proto: https/Forwarded: proto=httpsfrom a trusted peer- the default
RateLimiterkey and theAccessLoguse the client address
Without them nothing changes: client_ip() is the peer address.
Structs§
- Cidr
- A network such as
10.0.0.0/8orfd00::/8(a bare address is a single host) - Trusted
Proxies - The proxies whose forwarding headers are believed