Apache HTTPD / Trust, correctness, and reviewed change / Lesson 13
Forwarded client addresses and proxy trust
Distinguish the connection peer from a claimed original client before using addresses in logs or authorization.
On this page
Lesson goals
- Explain mod_remoteip’s identity effect and trusted-proxy boundary.
- Review forwarding chains without accepting arbitrary client claims.
The socket peer and original client can differ
Behind a reverse proxy, Apache’s network peer may be the proxy rather than the user agent. A forwarded address header can carry another identity claim, but a client can also send such text directly. Parcel’s logs and address-based access checks need an explicit rule for which intermediary is authorized to supply it. Never treat a familiar header name as authentication. Preserve the direct connection identity as well as the interpreted client identity when the investigation requires both, with appropriate privacy and access controls.
Remote address interpretation can affect authorization
mod_remoteip can replace the request client address used for logging and authorization according to configured header and trusted proxy rules. This is more than cosmetic log cleanup. Review RemoteIPTrustedProxy, RemoteIPInternalProxy, chain processing, and any PROXY-protocol integration under the actual module and network design. Their semantics differ, including handling of internal addresses. Trusting all incoming intermediaries can let an untrusted requester influence an address-based decision. Restrict direct reachability and header sanitization according to the owner’s architecture rather than assuming configuration alone establishes the network boundary.
Read a declared trusted-intermediary illustration
The fragment below selects X-Forwarded-For and one documentation-only proxy subnet. It is not loaded and does not create or trust a real network. A real configuration must identify actual authorized intermediaries and the chain’s exact contract. The example is not a complete multi-proxy policy and must not be copied as an operational allowlist. Address ranges, module support, inherited configuration, and which listener receives direct clients all matter. No header, packet, request, or access rule is tested by this course.
RemoteIPHeader X-Forwarded-For
RemoteIPTrustedProxy 192.0.2.0/24
The subnet is reserved teaching data and identifies no operational proxy. No client address is rewritten, network configured, authorization changed, or log inspected.
Accept a claim only from a declared trusted peer
The complete local model below uses exact synthetic peer names to decide whether one claimed address is considered. It does not parse X-Forwarded-For, evaluate CIDR ranges, walk a right-to-left chain, or implement mod_remoteip. It demonstrates one essential predicate: an untrusted peer’s claim should not replace the observed peer identity under this declared rule. Real parsing needs the supported module behavior and full topology. A log-format change alone cannot establish that the trusted-peer premise is true.
trusted_peers = {"192.0.2.10"}
def interpreted(peer, claimed):
return claimed if peer in trusted_peers else peer
print(interpreted("192.0.2.10", "198.51.100.23"))
print(interpreted("203.0.113.5", "198.51.100.23"))
198.51.100.23
203.0.113.5
The addresses are documentation examples. No network, header parser, Apache module, CIDR evaluator, or authorization provider is used.
Review all consumers of the interpreted address
Rate controls, Require ip, application logs, audit trails, and upstream forwarding may consume different address forms. Ensure the intended identity reaches each consumer and remains distinguishable from a direct connection peer where needed. Use the actual supported logging fields, such as request and connection-address forms, with their version requirements. Include direct-client, trusted-proxy, unexpected-peer, and multi-hop cases in an authorized validation plan. Do not widen proxy trust merely to make an access rule pass; first identify which actor should have supplied the claim and whether that path was actually enforced.
Common errors and fixes
Any X-Forwarded-For value is accepted as the real client.
- Why it happens
- A client-controlled claim is confused with trusted transport evidence.
- How to fix it
- Constrain authorized intermediaries and review direct access paths.
- Prevent it next time
- Trace claim origin and sanitization through every hop.
Remote address rewriting is treated as a log-only change.
- Why it happens
- Authorization and other consumers of the interpreted identity were overlooked.
- How to fix it
- Review affected access, application, and audit behavior before change.
- Prevent it next time
- Keep connection and interpreted identities explicit.
A one-peer teaching model is used as a full proxy-chain parser.
- Why it happens
- A narrow predicate is stretched into unsupported protocol handling.
- How to fix it
- Use the module’s documented chain and address semantics for actual policy.
- Prevent it next time
- State model limits and validate representative topology cases.
Check your understanding
1. An untrusted direct peer supplies the same claimed address as a trusted proxy. What does the local model do?
Show worked solution
It keeps the direct peer’s observed identity for the untrusted case and accepts the claim only for the declared trusted peer. This establishes the model’s predicate, not actual header or chain security. Real topology and module behavior need independent evidence.
2. Why can changing the interpreted client address alter Require ip results?
Show worked solution
Address-based authorization can consume that interpreted request identity. A trust mistake can therefore affect access, not only display. Review authorized proxy sources, effective policy, and direct reachability before treating the change as harmless logging cleanup.
Key takeaways
- A forwarded identity is trustworthy only under an enforced intermediary contract.
- Review every consumer of connection and interpreted client identity.