From 9f6930390ab9d1adb38d7a301e5c4fa3ff980822 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=A4=8F=E6=A5=9A?= <771730766@qq.com> Date: Tue, 26 Sep 2023 14:48:19 +0800 Subject: [PATCH] =?UTF-8?q?IP=E7=99=BD=E5=90=8D=E5=8D=95=E6=94=AF=E6=8C=81?= =?UTF-8?q?ipv6=20(#2858)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix #2855 --- conf/config.ini | 2 +- src/Common/config.cpp | 2 +- src/Http/HttpFileManager.cpp | 78 ++++++++++++++++++++++++++++-------- 3 files changed, 63 insertions(+), 19 deletions(-) diff --git a/conf/config.ini b/conf/config.ini index 0bd86b0b..dc343b32 100644 --- a/conf/config.ini +++ b/conf/config.ini @@ -244,7 +244,7 @@ forwarded_ip_header= #默认允许所有跨域请求 allow_cross_domains=1 #允许访问http api和http文件索引的ip地址范围白名单,置空情况下不做限制 -allow_ip_range=127.0.0.1,172.16.0.0-172.31.255.255,192.168.0.0-192.168.255.255,10.0.0.0-10.255.255.255 +allow_ip_range=::1,127.0.0.1,172.16.0.0-172.31.255.255,192.168.0.0-192.168.255.255,10.0.0.0-10.255.255.255 [multicast] #rtp组播截止组播ip地址 diff --git a/src/Common/config.cpp b/src/Common/config.cpp index b113a968..6e75e27d 100644 --- a/src/Common/config.cpp +++ b/src/Common/config.cpp @@ -194,7 +194,7 @@ static onceToken token([]() { mINI::Instance()[kForbidCacheSuffix] = ""; mINI::Instance()[kForwardedIpHeader] = ""; mINI::Instance()[kAllowCrossDomains] = 1; - mINI::Instance()[kAllowIPRange] = "127.0.0.1,172.16.0.0-172.31.255.255,192.168.0.0-192.168.255.255,10.0.0.0-10.255.255.255"; + mINI::Instance()[kAllowIPRange] = "::1,127.0.0.1,172.16.0.0-172.31.255.255,192.168.0.0-192.168.255.255,10.0.0.0-10.255.255.255"; }); } // namespace Http diff --git a/src/Http/HttpFileManager.cpp b/src/Http/HttpFileManager.cpp index 5577ffbb..c8996d1c 100644 --- a/src/Http/HttpFileManager.cpp +++ b/src/Http/HttpFileManager.cpp @@ -50,29 +50,69 @@ const string &HttpFileManager::getContentType(const char *name) { return HttpConst::getHttpContentType(name); } -#ifndef ntohll -static uint64_t ntohll(uint64_t val) { - return (((uint64_t)ntohl(val)) << 32) + ntohl(val >> 32); -} -#endif +namespace { +class UInt128 { +public: + UInt128() = default; -static uint64_t get_ip_uint64(const std::string &ip) { + UInt128(const struct sockaddr_storage &storage) { + _family = storage.ss_family; + memset(_bytes, 0, 16); + switch (storage.ss_family) { + case AF_INET: { + memcpy(_bytes, &(reinterpret_cast(storage).sin_addr), 4); + break; + } + case AF_INET6: { + memcpy(_bytes, &(reinterpret_cast(storage).sin6_addr), 16); + break; + } + default: CHECK(false, "Invalid socket family"); break; + } + } + + bool operator==(const UInt128 &that) const { return _family == that._family && !memcmp(_bytes, that._bytes, 16); } + + bool operator<=(const UInt128 &that) const { return *this < that || *this == that; } + + bool operator>=(const UInt128 &that) const { return *this > that || *this == that; } + + bool operator>(const UInt128 &that) const { return that < *this; } + + bool operator<(const UInt128 &that) const { + auto sz = _family == AF_INET ? 4 : 16; + for (int i = 0; i < sz; ++i) { + if (_bytes[i] < that._bytes[i]) { + return true; + } else if (_bytes[i] > that._bytes[i]) { + return false; + } + } + return false; + } + + operator bool() const { return _family != -1; } + + bool same_type(const UInt128 &that) const { return _family == that._family; } + +private: + int _family = -1; + uint8_t _bytes[16]; +}; + +} + +static UInt128 get_ip_uint64(const std::string &ip) { try { - auto storage = SockUtil::make_sockaddr(ip.data(), 0); - if (storage.ss_family == AF_INET) { - return ntohl(reinterpret_cast(reinterpret_cast(storage).sin_addr)); - } - if (storage.ss_family == AF_INET6) { - return ntohll(reinterpret_cast(reinterpret_cast(storage).sin6_addr)); - } + return UInt128(SockUtil::make_sockaddr(ip.data(), 0)); } catch (std::exception &ex) { WarnL << ex.what(); } - return 0; + return UInt128(); } bool HttpFileManager::isIPAllowed(const std::string &ip) { - using IPRangs = std::vector>; + using IPRangs = std::vector>; GET_CONFIG_FUNC(IPRangs, allow_ip_range, Http::kAllowIPRange, [](const string &str) -> IPRangs { IPRangs ret; auto vec = split(str, ","); @@ -84,13 +124,17 @@ bool HttpFileManager::isIPAllowed(const std::string &ip) { if (range.size() == 2) { auto ip_min = get_ip_uint64(trim(range[0])); auto ip_max = get_ip_uint64(trim(range[1])); - if (ip_min && ip_max) { + if (ip_min && ip_max && ip_min.same_type(ip_max)) { ret.emplace_back(ip_min, ip_max); + } else { + WarnL << "Invalid ip range or family: " << item; } } else if (range.size() == 1) { auto ip = get_ip_uint64(trim(range[0])); if (ip) { ret.emplace_back(ip, ip); + } else { + WarnL << "Invalid ip: " << item; } } else { WarnL << "Invalid ip range: " << item; @@ -104,7 +148,7 @@ bool HttpFileManager::isIPAllowed(const std::string &ip) { } auto ip_int = get_ip_uint64(ip); for (auto &range : allow_ip_range) { - if (ip_int >= range.first && ip_int <= range.second) { + if (ip_int.same_type(range.first) && ip_int >= range.first && ip_int <= range.second) { return true; } }