新增http api与http文件访问ip白名单限制机制,默认禁止公网访问

This commit is contained in:
xia-chu 2023-07-26 16:33:21 +08:00
parent e8f8b48d38
commit 098046cb1d
6 changed files with 77 additions and 2 deletions

View File

@ -241,6 +241,8 @@ forbidCacheSuffix=
forwarded_ip_header= forwarded_ip_header=
#默认允许所有跨域请求 #默认允许所有跨域请求
allow_cross_domains=1 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
[multicast] [multicast]
#rtp组播截止组播ip地址 #rtp组播截止组播ip地址

View File

@ -238,6 +238,11 @@ static inline void addHttpListener(){
//该api已被消费 //该api已被消费
consumed = true; consumed = true;
if (!HttpFileManager::isIPAllowed(sender.get_peer_ip())) {
invoker(403, HttpSession::KeyValue(), "Your ip is not allowed to access the service.");
return;
}
if(api_debug){ if(api_debug){
auto newInvoker = [invoker, parser](int code, const HttpSession::KeyValue &headerOut, const HttpBody::Ptr &body) { auto newInvoker = [invoker, parser](int code, const HttpSession::KeyValue &headerOut, const HttpBody::Ptr &body) {
//body默认为空 //body默认为空

View File

@ -165,6 +165,7 @@ const string kDirMenu = HTTP_FIELD "dirMenu";
const string kForbidCacheSuffix = HTTP_FIELD "forbidCacheSuffix"; const string kForbidCacheSuffix = HTTP_FIELD "forbidCacheSuffix";
const string kForwardedIpHeader = HTTP_FIELD "forwarded_ip_header"; const string kForwardedIpHeader = HTTP_FIELD "forwarded_ip_header";
const string kAllowCrossDomains = HTTP_FIELD "allow_cross_domains"; const string kAllowCrossDomains = HTTP_FIELD "allow_cross_domains";
const string kAllowIPRange = HTTP_FIELD "allow_ip_range";
static onceToken token([]() { static onceToken token([]() {
mINI::Instance()[kSendBufSize] = 64 * 1024; mINI::Instance()[kSendBufSize] = 64 * 1024;
@ -193,6 +194,7 @@ static onceToken token([]() {
mINI::Instance()[kForbidCacheSuffix] = ""; mINI::Instance()[kForbidCacheSuffix] = "";
mINI::Instance()[kForwardedIpHeader] = ""; mINI::Instance()[kForwardedIpHeader] = "";
mINI::Instance()[kAllowCrossDomains] = 1; 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";
}); });
} // namespace Http } // namespace Http

View File

@ -254,6 +254,8 @@ extern const std::string kForbidCacheSuffix;
extern const std::string kForwardedIpHeader; extern const std::string kForwardedIpHeader;
// 是否允许所有跨域请求 // 是否允许所有跨域请求
extern const std::string kAllowCrossDomains; extern const std::string kAllowCrossDomains;
// 允许访问http api和http文件索引的ip地址范围白名单置空情况下不做限制
extern const std::string kAllowIPRange;
} // namespace Http } // namespace Http
////////////SHELL配置/////////// ////////////SHELL配置///////////

View File

@ -50,6 +50,58 @@ const string &HttpFileManager::getContentType(const char *name) {
return HttpConst::getHttpContentType(name); return HttpConst::getHttpContentType(name);
} }
#ifndef ntohll
static uint64_t ntohll(uint64_t val) {
return (((uint64_t)ntohl(val)) << 32) + ntohl(val >> 32);
}
#endif
static uint64_t 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<uint32_t &>(reinterpret_cast<struct sockaddr_in &>(storage).sin_addr));
}
if (storage.ss_family == AF_INET6) {
return ntohll(reinterpret_cast<uint64_t &>(reinterpret_cast<struct sockaddr_in6 &>(storage).sin6_addr));
}
} catch (std::exception &ex) {
WarnL << ex.what();
}
return 0;
}
bool HttpFileManager::isIPAllowed(const std::string &ip) {
using IPRangs = std::vector<std::pair<uint64_t /*min_ip*/, uint64_t /*max_ip*/>>;
GET_CONFIG_FUNC(IPRangs, allow_ip_range, Http::kAllowIPRange, [](const string &str) -> IPRangs {
IPRangs ret;
auto vec = split(str, ",");
for (auto &item : vec) {
auto range = split(item, "-");
if (range.size() == 2) {
ret.emplace_back(get_ip_uint64(trim(range[0])), get_ip_uint64(trim(range[1])));
} else if (range.size() == 1) {
auto ip = get_ip_uint64(trim(range[0]));
ret.emplace_back(ip, ip);
} else {
WarnL << "Invalid ip range: " << item;
}
}
return ret;
});
if (allow_ip_range.empty()) {
return true;
}
for (auto &range : allow_ip_range) {
auto ip_int = get_ip_uint64(ip);
if (ip_int >= range.first && ip_int <= range.second) {
return true;
}
}
return false;
}
static string searchIndexFile(const string &dir){ static string searchIndexFile(const string &dir){
DIR *pDir; DIR *pDir;
dirent *pDirent; dirent *pDirent;
@ -321,10 +373,15 @@ static void canAccessPath(Session &sender, const Parser &parser, const MediaInfo
return; return;
} }
//事件未被拦截则认为是http下载请求 if (!HttpFileManager::isIPAllowed(sender.get_peer_ip())) {
callback("Your ip is not allowed to access the service.", nullptr);
return;
}
// 事件未被拦截则认为是http下载请求
bool flag = NoticeCenter::Instance().emitEvent(Broadcast::kBroadcastHttpAccess, parser, path, is_dir, accessPathInvoker, static_cast<SockInfo &>(sender)); bool flag = NoticeCenter::Instance().emitEvent(Broadcast::kBroadcastHttpAccess, parser, path, is_dir, accessPathInvoker, static_cast<SockInfo &>(sender));
if (!flag) { if (!flag) {
//此事件无人监听,我们默认都有权限访问 // 此事件无人监听,我们默认都有权限访问
callback("", nullptr); callback("", nullptr);
} }
} }

View File

@ -62,6 +62,13 @@ public:
* @return mime值 * @return mime值
*/ */
static const std::string &getContentType(const char *name); static const std::string &getContentType(const char *name);
/**
* ip是否再白名单中
* @param ip ipv4和ipv6
*/
static bool isIPAllowed(const std::string &ip);
private: private:
HttpFileManager() = delete; HttpFileManager() = delete;
~HttpFileManager() = delete; ~HttpFileManager() = delete;