From 51243ce62f8981a2d733c207bf73f050682dfecf Mon Sep 17 00:00:00 2001 From: Doug Hoyte Date: Wed, 8 Feb 2023 16:08:03 -0500 Subject: [PATCH] option to extract client's IP from HTTP header (ie X-Real-IP) --- TODO | 1 - golpe.yaml | 3 +++ src/RelayWebsocket.cpp | 10 +++++++++- src/global.h | 1 + src/misc.cpp | 10 ++++++++++ strfry.conf | 3 +++ 6 files changed, 26 insertions(+), 2 deletions(-) diff --git a/TODO b/TODO index cdd0745..96d623c 100644 --- a/TODO +++ b/TODO @@ -3,7 +3,6 @@ when disk is full it should log warning but not crash ensure DB upgrade flow works disable sync - get IP from HTTP header ? why isn't the LMDB mapping CLOEXEC 0.2 release diff --git a/golpe.yaml b/golpe.yaml index 97f5c08..f959654 100644 --- a/golpe.yaml +++ b/golpe.yaml @@ -125,6 +125,9 @@ config: desc: "Set OS-limit on maximum number of open files/sockets (if 0, don't attempt to set)" default: 1000000 noReload: true + - name: relay__realIpHeader + desc: "HTTP header that contains the client's real IP, before reverse proxying (ie x-real-ip) (MUST be all lower-case)" + default: "" - name: relay__info__name desc: "NIP-11: Name of this server. Short/descriptive (< 30 characters)" diff --git a/src/RelayWebsocket.cpp b/src/RelayWebsocket.cpp index c0912b4..6643695 100644 --- a/src/RelayWebsocket.cpp +++ b/src/RelayWebsocket.cpp @@ -94,7 +94,15 @@ void RelayServer::runWebsocket(ThreadPool::Thread &thr) { uint64_t connId = nextConnectionId++; Connection *c = new Connection(ws, connId); - c->ipAddr = ws->getAddressBytes(); + + if (cfg().relay__realIpHeader.size()) { + auto header = req.getHeader(cfg().relay__realIpHeader.c_str()).toString(); + c->ipAddr = parseIP(header); + if (c->ipAddr.size() == 0) LW << "Couldn't parse IP from header " << cfg().relay__realIpHeader << ": " << header; + } + + if (c->ipAddr.size() == 0) c->ipAddr = ws->getAddressBytes(); + ws->setUserData((void*)c); connIdToConnection.emplace(connId, c); diff --git a/src/global.h b/src/global.h index aeb23e9..c6b478f 100644 --- a/src/global.h +++ b/src/global.h @@ -19,3 +19,4 @@ std::string renderIP(std::string_view ipBytes); std::string renderSize(uint64_t si); std::string renderPercent(double p); uint64_t parseUint64(const std::string &s); +std::string parseIP(const std::string &ip); diff --git a/src/misc.cpp b/src/misc.cpp index 4cfbfeb..0f23f20 100644 --- a/src/misc.cpp +++ b/src/misc.cpp @@ -21,6 +21,16 @@ std::string renderIP(std::string_view ipBytes) { return std::string(buf); } +std::string parseIP(const std::string &ip) { + int af = ip.find(':') != std::string::npos ? AF_INET6 : AF_INET; + unsigned char buf[16]; + + int ret = inet_pton(af, ip.c_str(), &buf[0]); + if (ret == 0) return ""; + + return std::string((const char*)&buf[0], af == AF_INET6 ? 16 : 4); +} + std::string renderSize(uint64_t si) { if (si < 1024) return std::to_string(si) + "b"; diff --git a/strfry.conf b/strfry.conf index 8c06e02..d6d440e 100644 --- a/strfry.conf +++ b/strfry.conf @@ -23,6 +23,9 @@ relay { # Set OS-limit on maximum number of open files/sockets (if 0, don't attempt to set) (restart required) nofiles = 1000000 + # HTTP header that contains the client's real IP, before reverse proxying (ie x-real-ip) (case-insensitive) + realIpHeader = "" + info { # NIP-11: Name of this server. Short/descriptive (< 30 characters) name = "strfry default"