mirror of
https://github.com/ZLMediaKit/ZLMediaKit.git
synced 2024-11-25 20:27:34 +08:00
新增http api与http文件访问ip白名单限制机制,默认禁止公网访问
This commit is contained in:
parent
e8f8b48d38
commit
098046cb1d
@ -241,6 +241,8 @@ forbidCacheSuffix=
|
||||
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
|
||||
|
||||
[multicast]
|
||||
#rtp组播截止组播ip地址
|
||||
|
@ -238,6 +238,11 @@ static inline void addHttpListener(){
|
||||
//该api已被消费
|
||||
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){
|
||||
auto newInvoker = [invoker, parser](int code, const HttpSession::KeyValue &headerOut, const HttpBody::Ptr &body) {
|
||||
//body默认为空
|
||||
|
@ -165,6 +165,7 @@ const string kDirMenu = HTTP_FIELD "dirMenu";
|
||||
const string kForbidCacheSuffix = HTTP_FIELD "forbidCacheSuffix";
|
||||
const string kForwardedIpHeader = HTTP_FIELD "forwarded_ip_header";
|
||||
const string kAllowCrossDomains = HTTP_FIELD "allow_cross_domains";
|
||||
const string kAllowIPRange = HTTP_FIELD "allow_ip_range";
|
||||
|
||||
static onceToken token([]() {
|
||||
mINI::Instance()[kSendBufSize] = 64 * 1024;
|
||||
@ -193,6 +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";
|
||||
});
|
||||
|
||||
} // namespace Http
|
||||
|
@ -254,6 +254,8 @@ extern const std::string kForbidCacheSuffix;
|
||||
extern const std::string kForwardedIpHeader;
|
||||
// 是否允许所有跨域请求
|
||||
extern const std::string kAllowCrossDomains;
|
||||
// 允许访问http api和http文件索引的ip地址范围白名单,置空情况下不做限制
|
||||
extern const std::string kAllowIPRange;
|
||||
} // namespace Http
|
||||
|
||||
////////////SHELL配置///////////
|
||||
|
@ -50,6 +50,58 @@ 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
|
||||
|
||||
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){
|
||||
DIR *pDir;
|
||||
dirent *pDirent;
|
||||
@ -321,10 +373,15 @@ static void canAccessPath(Session &sender, const Parser &parser, const MediaInfo
|
||||
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));
|
||||
if (!flag) {
|
||||
//此事件无人监听,我们默认都有权限访问
|
||||
// 此事件无人监听,我们默认都有权限访问
|
||||
callback("", nullptr);
|
||||
}
|
||||
}
|
||||
|
@ -62,6 +62,13 @@ public:
|
||||
* @return mime值
|
||||
*/
|
||||
static const std::string &getContentType(const char *name);
|
||||
|
||||
/**
|
||||
* 该ip是否再白名单中
|
||||
* @param ip 支持ipv4和ipv6
|
||||
*/
|
||||
static bool isIPAllowed(const std::string &ip);
|
||||
|
||||
private:
|
||||
HttpFileManager() = delete;
|
||||
~HttpFileManager() = delete;
|
||||
|
Loading…
Reference in New Issue
Block a user