option to extract client's IP from HTTP header (ie X-Real-IP)

This commit is contained in:
Doug Hoyte
2023-02-08 16:08:03 -05:00
parent 4eb7a4fe53
commit 51243ce62f
6 changed files with 26 additions and 2 deletions

1
TODO
View File

@ -3,7 +3,6 @@
when disk is full it should log warning but not crash when disk is full it should log warning but not crash
ensure DB upgrade flow works ensure DB upgrade flow works
disable sync disable sync
get IP from HTTP header
? why isn't the LMDB mapping CLOEXEC ? why isn't the LMDB mapping CLOEXEC
0.2 release 0.2 release

View File

@ -125,6 +125,9 @@ config:
desc: "Set OS-limit on maximum number of open files/sockets (if 0, don't attempt to set)" desc: "Set OS-limit on maximum number of open files/sockets (if 0, don't attempt to set)"
default: 1000000 default: 1000000
noReload: true 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 - name: relay__info__name
desc: "NIP-11: Name of this server. Short/descriptive (< 30 characters)" desc: "NIP-11: Name of this server. Short/descriptive (< 30 characters)"

View File

@ -94,7 +94,15 @@ void RelayServer::runWebsocket(ThreadPool<MsgWebsocket>::Thread &thr) {
uint64_t connId = nextConnectionId++; uint64_t connId = nextConnectionId++;
Connection *c = new Connection(ws, connId); 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); ws->setUserData((void*)c);
connIdToConnection.emplace(connId, c); connIdToConnection.emplace(connId, c);

View File

@ -19,3 +19,4 @@ std::string renderIP(std::string_view ipBytes);
std::string renderSize(uint64_t si); std::string renderSize(uint64_t si);
std::string renderPercent(double p); std::string renderPercent(double p);
uint64_t parseUint64(const std::string &s); uint64_t parseUint64(const std::string &s);
std::string parseIP(const std::string &ip);

View File

@ -21,6 +21,16 @@ std::string renderIP(std::string_view ipBytes) {
return std::string(buf); 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) { std::string renderSize(uint64_t si) {
if (si < 1024) return std::to_string(si) + "b"; if (si < 1024) return std::to_string(si) + "b";

View File

@ -23,6 +23,9 @@ relay {
# Set OS-limit on maximum number of open files/sockets (if 0, don't attempt to set) (restart required) # Set OS-limit on maximum number of open files/sockets (if 0, don't attempt to set) (restart required)
nofiles = 1000000 nofiles = 1000000
# HTTP header that contains the client's real IP, before reverse proxying (ie x-real-ip) (case-insensitive)
realIpHeader = ""
info { info {
# NIP-11: Name of this server. Short/descriptive (< 30 characters) # NIP-11: Name of this server. Short/descriptive (< 30 characters)
name = "strfry default" name = "strfry default"