diff --git a/src/core/Handler.cpp b/src/core/Handler.cpp index cc2dc57..ec908cc 100644 --- a/src/core/Handler.cpp +++ b/src/core/Handler.cpp @@ -8,6 +8,7 @@ #include "../headers/gitProtocolHeader.hpp" #include "../headers/acceptLanguageHeader.hpp" #include "../headers/setCookieHeader.hpp" +#include "../headers/xrealip.hpp" #include "../debug/log.hpp" #include "../GlobalState.hpp" #include "../config/Config.hpp" @@ -57,17 +58,10 @@ std::string CServerHandler::fingerprintForRequest(const Pistache::Http::Request& const auto HEADERS = req.headers(); std::shared_ptr acceptEncodingHeader; std::shared_ptr userAgentHeader; - std::shared_ptr cfHeader; std::shared_ptr languageHeader; std::string input = "checkpoint-"; - try { - cfHeader = Pistache::Http::Header::header_cast(HEADERS.get("cf-connecting-ip")); - } catch (std::exception& e) { - ; // silent ignore - } - try { acceptEncodingHeader = Pistache::Http::Header::header_cast(HEADERS.get("Accept-Encoding")); } catch (std::exception& e) { @@ -86,8 +80,7 @@ std::string CServerHandler::fingerprintForRequest(const Pistache::Http::Request& ; // silent ignore } - if (cfHeader) - input += cfHeader->ip(); + input += ipForRequest(req); // TODO: those seem to change. Find better things to hash. // if (acceptEncodingHeader) // input += HEADERS.getRaw("Accept-Encoding").value(); @@ -96,8 +89,6 @@ std::string CServerHandler::fingerprintForRequest(const Pistache::Http::Request& if (userAgentHeader) input += userAgentHeader->agent(); - input += req.address().host(); - return g_pCrypto->sha256(input); } @@ -105,6 +96,31 @@ bool CServerHandler::isResourceCheckpoint(const std::string_view& res) { return res == "/checkpoint/NotoSans.woff"; } +std::string CServerHandler::ipForRequest(const Pistache::Http::Request& req) { + std::shared_ptr cfHeader; + std::shared_ptr xRealIPHeader; + + try { + cfHeader = Pistache::Http::Header::header_cast(req.headers().get("cf-connecting-ip")); + } catch (std::exception& e) { + ; // silent ignore + } + + try { + xRealIPHeader = Pistache::Http::Header::header_cast(req.headers().get("X-Real-IP")); + } catch (std::exception& e) { + ; // silent ignore + } + + if (cfHeader) + return cfHeader->ip(); + + if (xRealIPHeader) + return xRealIPHeader->ip(); + + return req.address().host(); +} + void CServerHandler::onRequest(const Pistache::Http::Request& req, Pistache::Http::ResponseWriter response) { const auto HEADERS = req.headers(); std::shared_ptr hostHeader; @@ -161,11 +177,9 @@ void CServerHandler::onRequest(const Pistache::Http::Request& req, Pistache::Htt Debug::log(LOG, "New request: {}:{}{}", hostHeader->host(), hostHeader->port().toString(), req.resource()); - Debug::log(LOG, " | Request author: IP {}", req.address().host()); - if (cfHeader) - Debug::log(LOG, " | CloudFlare reports IP: {}", cfHeader->ip()); - else - Debug::log(TRACE, "Connection does not come through CloudFlare"); + const auto REQUEST_IP = ipForRequest(req); + + Debug::log(LOG, " | Request author: IP {}, direct: {}", REQUEST_IP, req.address().host()); if (userAgentHeader) Debug::log(LOG, " | UA: {}", userAgentHeader->agent()); @@ -216,7 +230,7 @@ void CServerHandler::onRequest(const Pistache::Http::Request& req, Pistache::Htt int challengeDifficulty = g_pConfig->m_config.default_challenge_difficulty; if (!g_pConfig->m_parsedConfigDatas.ip_configs.empty()) { - const auto IP = CIP(req.address().host()); + const auto IP = CIP(REQUEST_IP); for (const auto& ic : g_pConfig->m_parsedConfigDatas.ip_configs) { bool matched = false; @@ -230,11 +244,11 @@ void CServerHandler::onRequest(const Pistache::Http::Request& req, Pistache::Htt if (matched) { if (ic.action == CConfig::IP_ACTION_ALLOW) { - Debug::log(LOG, " | Action: PASS (ip rule matched for {})", req.address().host()); + Debug::log(LOG, " | Action: PASS (ip rule matched for {})", REQUEST_IP); proxyPass(req, response); return; } else if (ic.action == CConfig::IP_ACTION_DENY) { - Debug::log(LOG, " | Action: DENY (ip rule matched for {})", req.address().host()); + Debug::log(LOG, " | Action: DENY (ip rule matched for {})", REQUEST_IP); response.send(Pistache::Http::Code::Forbidden, "Forbidden"); return; } diff --git a/src/core/Handler.hpp b/src/core/Handler.hpp index 87f1752..1bd7d56 100644 --- a/src/core/Handler.hpp +++ b/src/core/Handler.hpp @@ -20,6 +20,7 @@ class CServerHandler : public Pistache::Http::Handler { void proxyPass(const Pistache::Http::Request& req, Pistache::Http::ResponseWriter& response); void challengeSubmitted(const Pistache::Http::Request& req, Pistache::Http::ResponseWriter& response); std::string fingerprintForRequest(const Pistache::Http::Request& req); + std::string ipForRequest(const Pistache::Http::Request& req); bool isResourceCheckpoint(const std::string_view& res); diff --git a/src/headers/xrealip.hpp b/src/headers/xrealip.hpp new file mode 100644 index 0000000..6c36925 --- /dev/null +++ b/src/headers/xrealip.hpp @@ -0,0 +1,24 @@ +#include +#include + +class XRealIPHeader : public Pistache::Http::Header::Header { + public: + NAME("X-Real-IP"); + + XRealIPHeader() = default; + + void parse(const std::string& str) override { + m_ip = str; + } + + void write(std::ostream& os) const override { + os << m_ip; + } + + std::string ip() const { + return m_ip; + } + + private: + std::string m_ip = ""; +}; \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index 74e1fa0..1270f18 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -14,6 +14,7 @@ #include "headers/gitProtocolHeader.hpp" #include "headers/acceptLanguageHeader.hpp" #include "headers/setCookieHeader.hpp" +#include "headers/xrealip.hpp" #include "debug/log.hpp" @@ -78,6 +79,7 @@ int main(int argc, char** argv, char** envp) { Pistache::Http::Header::Registry::instance().registerHeader(); Pistache::Http::Header::Registry::instance().registerHeader(); Pistache::Http::Header::Registry::instance().registerHeader(); + Pistache::Http::Header::Registry::instance().registerHeader(); g_pCrypto = std::make_unique();