Validate connecting peer before honoring X-Forwarded-For

Server::process_request only checked that trusted_proxies_ was
non-empty before deriving req.remote_addr from the X-Forwarded-For
header. It never verified that the actual TCP peer (remote_addr) was
itself one of the trusted proxies, so any client connecting directly
to the server could spoof remote_addr simply by sending an arbitrary
X-Forwarded-For header.

Now X-Forwarded-For is only honored when the connecting peer address
matches an entry in trusted_proxies_.
This commit is contained in:
yhirose committed 2026-07-21 19:44:39 -04:00
1 parent bbd56a7e2c
commit fd0c18b1b5
2 files changed
+55 -7

No files matched your search

+8 -1
View File
@@ -12558,7 +12558,14 @@ Server::process_request(Stream &strm, const std::string &remote_addr,
connection_closed = true;
}
if (!trusted_proxies_.empty() && req.has_header("X-Forwarded-For")) {
// Only honor X-Forwarded-For if the peer on the actual TCP connection is
// itself a trusted proxy. Otherwise any direct client could spoof
// remote_addr simply by sending an arbitrary X-Forwarded-For header.
auto is_trusted_peer = std::any_of(
trusted_proxies_.begin(), trusted_proxies_.end(),
[&](const std::string &proxy) { return proxy == remote_addr; });
if (is_trusted_peer && req.has_header("X-Forwarded-For")) {
auto x_forwarded_for = req.get_header_value("X-Forwarded-For");
auto derived = get_client_ip(x_forwarded_for, trusted_proxies_);
req.remote_addr = derived.empty() ? remote_addr : derived;