The client's address behind trusted proxies.
When the connection's peer is a trusted proxy, the client is the right-most
X-Forwarded-For entry that is not itself a trusted proxy; entries to its
left could have been written by the client. Otherwise the client is the
peer, and the header is ignored. The plug sets conn.remote_ip to the
client, so logging, rate limits and everything downstream key on the right
address, and keeps the socket peer in conn.private.macaw_plug_peer.
plug Macaw.Plug.ClientIp, trusted_proxies: ["10.0.0.0/8", "fd00::/8"]Trusted proxies default to none. With none trusted, every client is its
peer: behind a reverse proxy that means every visitor looks like the
proxy, which is wrong but never spoofable. The :trusted_proxies option
takes CIDRs or single addresses, or {module, function, args} returning
them, called on every request, for a list that changes at runtime. A
malformed entry raises at init/1, naming it.
A forwarded request from an untrusted peer (it sent X-Forwarded-For,
but its address isn't trusted) is served as usual, with the header
ignored, and emits the telemetry event
[:macaw_plug, :client_ip, :untrusted_forward] with the peer in its
metadata. It usually means a proxy in front of the app is missing from
the trusted list. attach_default_logger/1 logs it at most once per
interval.
Summary
Functions
Logs an untrusted forward, and a bad entry in a dynamic trusted-proxy
list, each at most once per interval_ms (default one minute) on this
node. Returns the telemetry handler's attach result.
The X-Forwarded-For entries of a request, left to right.
The socket peer of a request this plug has run on, else its remote_ip.
The client address for a peer, its X-Forwarded-For entries (left to
right, as sent) and the trusted CIDRs.
Functions
@spec attach_default_logger(pos_integer()) :: :ok | {:error, :already_exists}
Logs an untrusted forward, and a bad entry in a dynamic trusted-proxy
list, each at most once per interval_ms (default one minute) on this
node. Returns the telemetry handler's attach result.
@spec forwarded_for(Plug.Conn.t()) :: [String.t()]
The X-Forwarded-For entries of a request, left to right.
@spec peer(Plug.Conn.t()) :: Macaw.Plug.Ip.ip()
The socket peer of a request this plug has run on, else its remote_ip.
@spec resolve(Macaw.Plug.Ip.ip(), [String.t()], [Macaw.Plug.Ip.cidr()]) :: Macaw.Plug.Ip.ip()
The client address for a peer, its X-Forwarded-For entries (left to
right, as sent) and the trusted CIDRs.