scan X-Forwarded-For right-to-left in get_client_ip (#2503)

This commit is contained in:
metsw24-max authored and GitHub committed 2026-07-21 18:12:40 -04:00
1 parent ef2beaea34
commit 6c4cbd49a2
2 files changed
+50 -14

No files matched your search

+12 -12
View File
@@ -12420,25 +12420,25 @@ get_client_ip(const std::string &x_forwarded_for,
// caller can fall back to the connection-level remote address.
if (ip_list.empty()) { return std::string(); }
for (size_t i = 0; i < ip_list.size(); ++i) {
auto ip = ip_list[i];
// Each hop appends the address it received the request from, so the rightmost
// entries are the ones written by our own infrastructure while the leftmost
// are whatever the original client chose to send. Walk from the right and
// skip trusted proxies; the first address that is not a trusted proxy is the
// furthest point still attributable to a real hop, i.e. the client. Scanning
// from the left instead lets a client forge an arbitrary address by following
// it with a trusted proxy's address, which the left-to-right scan then
// returned as the client.
for (size_t i = ip_list.size(); i-- > 0;) {
const auto &ip = ip_list[i];
auto is_trusted_proxy =
std::any_of(trusted_proxies.begin(), trusted_proxies.end(),
[&](const std::string &proxy) { return ip == proxy; });
if (is_trusted_proxy) {
if (i == 0) {
// If the trusted proxy is the first IP, there's no preceding client IP
return ip;
} else {
// Return the IP immediately before the trusted proxy
return ip_list[i - 1];
}
}
if (!is_trusted_proxy) { return ip; }
}
// If no trusted proxy is found, return the first IP in the list
// Every hop was a trusted proxy; fall back to the first entry.
return ip_list.front();
}