fix: Proxy support (#3103)

Port of two changes onto release/2.7.1:
- #3006 (d3381a1d): resolve proxy ip before processing any request
- #3043 (d7bcf6e7): re-resolve client ip when a proxy reuses a TCP
connection for different clients (resolveClientIp now returns
std::optional; extractClientIp made public; isProxyConnection_ tracked)
This commit is contained in:
Sergey Kuznetsov
2026-06-09 16:25:02 +01:00
committed by GitHub
parent ce44aec245
commit 14645e1494
7 changed files with 252 additions and 36 deletions

View File

@@ -26,6 +26,7 @@
#include <boost/beast/http/field.hpp>
#include <algorithm>
#include <optional>
#include <string>
#include <string_view>
@@ -63,20 +64,20 @@ ProxyIpResolver::fromConfig(util::config::ClioConfigDefinition const& config)
return ProxyIpResolver{std::move(ips), std::move(tokens)};
}
std::string
std::optional<std::string>
ProxyIpResolver::resolveClientIp(std::string const& connectionIp, HttpHeaders const& headers) const
{
if (proxyIps_.contains(connectionIp)) {
return extractClientIp(headers).value_or(connectionIp);
return extractClientIp(headers);
}
if (auto it = headers.find(kPROXY_TOKEN_HEADER); it != headers.end()) {
auto const tokenHash = util::sha256sum(it->value());
if (proxyTokens_.contains(tokenHash)) {
return extractClientIp(headers).value_or(connectionIp);
return extractClientIp(headers);
}
}
return connectionIp;
return std::nullopt;
}
std::optional<std::string>
@@ -92,14 +93,17 @@ ProxyIpResolver::extractClientIp(HttpHeaders const& headers)
auto const headerValue = util::toLower(it->value());
static constexpr std::string_view kFOR_PREFIX = "for=";
auto const startPos = headerValue.find(kFOR_PREFIX);
auto const startPos = headerValue.rfind(kFOR_PREFIX);
if (startPos == std::string::npos) {
return std::nullopt;
}
auto value = it->value().substr(startPos + kFOR_PREFIX.size());
static constexpr char kDELIMITER = ';';
auto const endPos = value.find(kDELIMITER);
static constexpr char kSECTION_DELIMITER = ';';
static constexpr char kCHAIN_DELIMITER = ',';
auto const sectionEnd = value.find(kSECTION_DELIMITER);
auto const chainEnd = value.find(kCHAIN_DELIMITER);
auto const endPos = std::min(sectionEnd, chainEnd);
auto const ip = value.substr(0, endPos);
static constexpr auto kMIN_IP_LENGTH = 7; // minimum 3 dots + 4 digits