mirror of
https://github.com/ZLMediaKit/ZLMediaKit.git
synced 2024-11-22 19:00:01 +08:00
新增http api与http文件访问ip白名单限制机制,默认禁止公网访问
This commit is contained in:
parent
e8f8b48d38
commit
098046cb1d
@ -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地址
|
||||||
|
@ -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默认为空
|
||||||
|
@ -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
|
||||||
|
@ -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配置///////////
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
Loading…
Reference in New Issue
Block a user