mirror of
https://github.com/ossrs/srs.git
synced 2025-03-09 15:49:59 +00:00
Security: Support IP whitelist for HTTP-FLV, HLS, WebRTC, and SRT. v5.0.202 (#3902)
Security is the built-in IP whitelist feature of SRS, which allows and denies certain IP and IP range users. Previously, it only supported RTMP, but this PR now supports HTTP-FLV, HLS, WebRTC, SRT, and other protocols. See https://ossrs.io/lts/en-us/docs/v6/doc/security as example. --------- Co-authored-by: john <hondaxiao@tencent.com>
This commit is contained in:
parent
0808be18ad
commit
52b01b14e9
11 changed files with 60 additions and 9 deletions
|
@ -7,6 +7,7 @@ The changelog for SRS.
|
||||||
<a name="v5-changes"></a>
|
<a name="v5-changes"></a>
|
||||||
|
|
||||||
## SRS 5.0 Changelog
|
## SRS 5.0 Changelog
|
||||||
|
* v5.0, 2023-12-14, Merge [#3902](https://github.com/ossrs/srs/pull/3902): Security: Support IP whitelist for HTTP-FLV, HLS, WebRTC, and SRT. v5.0.202 (#3902)
|
||||||
* v5.0, 2023-11-22, Merge [#3891](https://github.com/ossrs/srs/pull/3891): fix 'sed' error in options.sh. v5.0.201 (#3891)
|
* v5.0, 2023-11-22, Merge [#3891](https://github.com/ossrs/srs/pull/3891): fix 'sed' error in options.sh. v5.0.201 (#3891)
|
||||||
* v5.0, 2023-11-19, Merge [#3886](https://github.com/ossrs/srs/pull/3886): Change the hls_aof_ratio to 2.1. v5.0.200 (#3886)
|
* v5.0, 2023-11-19, Merge [#3886](https://github.com/ossrs/srs/pull/3886): Change the hls_aof_ratio to 2.1. v5.0.200 (#3886)
|
||||||
* v5.0, 2023-11-15, Merge [#3879](https://github.com/ossrs/srs/pull/3879): Add --extra-ldflags. v5.0.199 (#3879)
|
* v5.0, 2023-11-15, Merge [#3879](https://github.com/ossrs/srs/pull/3879): Add --extra-ldflags. v5.0.199 (#3879)
|
||||||
|
|
|
@ -64,6 +64,7 @@ void SrsHlsVirtualConn::expire()
|
||||||
SrsHlsStream::SrsHlsStream()
|
SrsHlsStream::SrsHlsStream()
|
||||||
{
|
{
|
||||||
_srs_hybrid->timer5s()->subscribe(this);
|
_srs_hybrid->timer5s()->subscribe(this);
|
||||||
|
security_ = new SrsSecurity();
|
||||||
}
|
}
|
||||||
|
|
||||||
SrsHlsStream::~SrsHlsStream()
|
SrsHlsStream::~SrsHlsStream()
|
||||||
|
@ -76,6 +77,7 @@ SrsHlsStream::~SrsHlsStream()
|
||||||
srs_freep(info);
|
srs_freep(info);
|
||||||
}
|
}
|
||||||
map_ctx_info_.clear();
|
map_ctx_info_.clear();
|
||||||
|
srs_freep(security_);
|
||||||
}
|
}
|
||||||
|
|
||||||
srs_error_t SrsHlsStream::serve_m3u8_ctx(ISrsHttpResponseWriter* w, ISrsHttpMessage* r, ISrsFileReaderFactory* factory, string fullpath, SrsRequest* req, bool* served)
|
srs_error_t SrsHlsStream::serve_m3u8_ctx(ISrsHttpResponseWriter* w, ISrsHttpMessage* r, ISrsFileReaderFactory* factory, string fullpath, SrsRequest* req, bool* served)
|
||||||
|
@ -167,6 +169,10 @@ srs_error_t SrsHlsStream::serve_new_session(ISrsHttpResponseWriter* w, ISrsHttpM
|
||||||
return srs_error_wrap(err, "stat on client");
|
return srs_error_wrap(err, "stat on client");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((err = security_->check(SrsHlsPlay, req->ip, req)) != srs_success) {
|
||||||
|
return srs_error_wrap(err, "HLS: security check");
|
||||||
|
}
|
||||||
|
|
||||||
// We must do hook after stat, because depends on it.
|
// We must do hook after stat, because depends on it.
|
||||||
if ((err = http_hooks_on_play(req)) != srs_success) {
|
if ((err = http_hooks_on_play(req)) != srs_success) {
|
||||||
return srs_error_wrap(err, "HLS: http_hooks_on_play");
|
return srs_error_wrap(err, "HLS: http_hooks_on_play");
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
#define SRS_APP_HTTP_STATIC_HPP
|
#define SRS_APP_HTTP_STATIC_HPP
|
||||||
|
|
||||||
#include <srs_core.hpp>
|
#include <srs_core.hpp>
|
||||||
|
#include <srs_app_security.hpp>
|
||||||
#include <srs_app_http_conn.hpp>
|
#include <srs_app_http_conn.hpp>
|
||||||
|
|
||||||
class ISrsFileReaderFactory;
|
class ISrsFileReaderFactory;
|
||||||
|
@ -52,6 +52,8 @@ private:
|
||||||
// interface ISrsFastTimer
|
// interface ISrsFastTimer
|
||||||
private:
|
private:
|
||||||
srs_error_t on_timer(srs_utime_t interval);
|
srs_error_t on_timer(srs_utime_t interval);
|
||||||
|
private:
|
||||||
|
SrsSecurity* security_;
|
||||||
};
|
};
|
||||||
|
|
||||||
// The Vod streaming, like FLV, MP4 or HLS streaming.
|
// The Vod streaming, like FLV, MP4 or HLS streaming.
|
||||||
|
|
|
@ -549,11 +549,13 @@ SrsLiveStream::SrsLiveStream(SrsLiveSource* s, SrsRequest* r, SrsBufferCache* c)
|
||||||
source = s;
|
source = s;
|
||||||
cache = c;
|
cache = c;
|
||||||
req = r->copy()->as_http();
|
req = r->copy()->as_http();
|
||||||
|
security_ = new SrsSecurity();
|
||||||
}
|
}
|
||||||
|
|
||||||
SrsLiveStream::~SrsLiveStream()
|
SrsLiveStream::~SrsLiveStream()
|
||||||
{
|
{
|
||||||
srs_freep(req);
|
srs_freep(req);
|
||||||
|
srs_freep(security_);
|
||||||
}
|
}
|
||||||
|
|
||||||
srs_error_t SrsLiveStream::update_auth(SrsLiveSource* s, SrsRequest* r)
|
srs_error_t SrsLiveStream::update_auth(SrsLiveSource* s, SrsRequest* r)
|
||||||
|
@ -591,6 +593,10 @@ srs_error_t SrsLiveStream::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage
|
||||||
return srs_error_wrap(err, "stat on client");
|
return srs_error_wrap(err, "stat on client");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((err = security_->check(SrsFlvPlay, req->ip, req)) != srs_success) {
|
||||||
|
return srs_error_wrap(err, "flv: security check");
|
||||||
|
}
|
||||||
|
|
||||||
// We must do hook after stat, because depends on it.
|
// We must do hook after stat, because depends on it.
|
||||||
if ((err = http_hooks_on_play(r)) != srs_success) {
|
if ((err = http_hooks_on_play(r)) != srs_success) {
|
||||||
return srs_error_wrap(err, "http hook");
|
return srs_error_wrap(err, "http hook");
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
#define SRS_APP_HTTP_STREAM_HPP
|
#define SRS_APP_HTTP_STREAM_HPP
|
||||||
|
|
||||||
#include <srs_core.hpp>
|
#include <srs_core.hpp>
|
||||||
|
#include <srs_app_security.hpp>
|
||||||
#include <srs_app_http_conn.hpp>
|
#include <srs_app_http_conn.hpp>
|
||||||
|
|
||||||
class SrsAacTransmuxer;
|
class SrsAacTransmuxer;
|
||||||
|
@ -177,6 +177,7 @@ private:
|
||||||
SrsRequest* req;
|
SrsRequest* req;
|
||||||
SrsLiveSource* source;
|
SrsLiveSource* source;
|
||||||
SrsBufferCache* cache;
|
SrsBufferCache* cache;
|
||||||
|
SrsSecurity* security_;
|
||||||
public:
|
public:
|
||||||
SrsLiveStream(SrsLiveSource* s, SrsRequest* r, SrsBufferCache* c);
|
SrsLiveStream(SrsLiveSource* s, SrsRequest* r, SrsBufferCache* c);
|
||||||
virtual ~SrsLiveStream();
|
virtual ~SrsLiveStream();
|
||||||
|
|
|
@ -31,10 +31,12 @@ using namespace std;
|
||||||
SrsGoApiRtcPlay::SrsGoApiRtcPlay(SrsRtcServer* server)
|
SrsGoApiRtcPlay::SrsGoApiRtcPlay(SrsRtcServer* server)
|
||||||
{
|
{
|
||||||
server_ = server;
|
server_ = server;
|
||||||
|
security_ = new SrsSecurity();
|
||||||
}
|
}
|
||||||
|
|
||||||
SrsGoApiRtcPlay::~SrsGoApiRtcPlay()
|
SrsGoApiRtcPlay::~SrsGoApiRtcPlay()
|
||||||
{
|
{
|
||||||
|
srs_freep(security_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -228,6 +230,10 @@ srs_error_t SrsGoApiRtcPlay::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessa
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((err = security_->check(SrsRtcConnPlay, ruc->req_->ip, ruc->req_)) != srs_success) {
|
||||||
|
return srs_error_wrap(err, "RTC: security check");
|
||||||
|
}
|
||||||
|
|
||||||
if ((err = http_hooks_on_play(ruc->req_)) != srs_success) {
|
if ((err = http_hooks_on_play(ruc->req_)) != srs_success) {
|
||||||
return srs_error_wrap(err, "RTC: http_hooks_on_play");
|
return srs_error_wrap(err, "RTC: http_hooks_on_play");
|
||||||
}
|
}
|
||||||
|
@ -324,10 +330,12 @@ srs_error_t SrsGoApiRtcPlay::http_hooks_on_play(SrsRequest* req)
|
||||||
SrsGoApiRtcPublish::SrsGoApiRtcPublish(SrsRtcServer* server)
|
SrsGoApiRtcPublish::SrsGoApiRtcPublish(SrsRtcServer* server)
|
||||||
{
|
{
|
||||||
server_ = server;
|
server_ = server;
|
||||||
|
security_ = new SrsSecurity();
|
||||||
}
|
}
|
||||||
|
|
||||||
SrsGoApiRtcPublish::~SrsGoApiRtcPublish()
|
SrsGoApiRtcPublish::~SrsGoApiRtcPublish()
|
||||||
{
|
{
|
||||||
|
srs_freep(security_);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Request:
|
// Request:
|
||||||
|
@ -503,6 +511,10 @@ srs_error_t SrsGoApiRtcPublish::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMe
|
||||||
return srs_error_wrap(err, "create session");
|
return srs_error_wrap(err, "create session");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((err = security_->check(SrsRtcConnPublish, ruc->req_->ip, ruc->req_)) != srs_success) {
|
||||||
|
return srs_error_wrap(err, "RTC: security check");
|
||||||
|
}
|
||||||
|
|
||||||
// We must do hook after stat, because depends on it.
|
// We must do hook after stat, because depends on it.
|
||||||
if ((err = http_hooks_on_publish(ruc->req_)) != srs_success) {
|
if ((err = http_hooks_on_publish(ruc->req_)) != srs_success) {
|
||||||
return srs_error_wrap(err, "RTC: http_hooks_on_publish");
|
return srs_error_wrap(err, "RTC: http_hooks_on_publish");
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
#define SRS_APP_RTC_API_HPP
|
#define SRS_APP_RTC_API_HPP
|
||||||
|
|
||||||
#include <srs_core.hpp>
|
#include <srs_core.hpp>
|
||||||
|
#include <srs_app_security.hpp>
|
||||||
#include <srs_protocol_http_stack.hpp>
|
#include <srs_protocol_http_stack.hpp>
|
||||||
|
|
||||||
class SrsRtcServer;
|
class SrsRtcServer;
|
||||||
|
@ -20,6 +20,7 @@ class SrsGoApiRtcPlay : public ISrsHttpHandler
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
SrsRtcServer* server_;
|
SrsRtcServer* server_;
|
||||||
|
SrsSecurity* security_;
|
||||||
public:
|
public:
|
||||||
SrsGoApiRtcPlay(SrsRtcServer* server);
|
SrsGoApiRtcPlay(SrsRtcServer* server);
|
||||||
virtual ~SrsGoApiRtcPlay();
|
virtual ~SrsGoApiRtcPlay();
|
||||||
|
@ -39,6 +40,7 @@ class SrsGoApiRtcPublish : public ISrsHttpHandler
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
SrsRtcServer* server_;
|
SrsRtcServer* server_;
|
||||||
|
SrsSecurity* security_;
|
||||||
public:
|
public:
|
||||||
SrsGoApiRtcPublish(SrsRtcServer* server);
|
SrsGoApiRtcPublish(SrsRtcServer* server);
|
||||||
virtual ~SrsGoApiRtcPublish();
|
virtual ~SrsGoApiRtcPublish();
|
||||||
|
|
|
@ -75,7 +75,10 @@ srs_error_t SrsSecurity::allow_check(SrsConfDirective* rules, SrsRtmpConnType ty
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case SrsRtmpConnPlay:
|
case SrsRtmpConnPlay:
|
||||||
case SrsRtcConnPlay:
|
case SrsHlsPlay:
|
||||||
|
case SrsFlvPlay:
|
||||||
|
case SrsRtcConnPlay:
|
||||||
|
case SrsSrtConnPlay:
|
||||||
if (rule->arg0() != "play") {
|
if (rule->arg0() != "play") {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -90,6 +93,7 @@ srs_error_t SrsSecurity::allow_check(SrsConfDirective* rules, SrsRtmpConnType ty
|
||||||
case SrsRtmpConnFlashPublish:
|
case SrsRtmpConnFlashPublish:
|
||||||
case SrsRtmpConnHaivisionPublish:
|
case SrsRtmpConnHaivisionPublish:
|
||||||
case SrsRtcConnPublish:
|
case SrsRtcConnPublish:
|
||||||
|
case SrsSrtConnPublish:
|
||||||
if (rule->arg0() != "publish") {
|
if (rule->arg0() != "publish") {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -126,7 +130,10 @@ srs_error_t SrsSecurity::deny_check(SrsConfDirective* rules, SrsRtmpConnType typ
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case SrsRtmpConnPlay:
|
case SrsRtmpConnPlay:
|
||||||
case SrsRtcConnPlay:
|
case SrsHlsPlay:
|
||||||
|
case SrsFlvPlay:
|
||||||
|
case SrsRtcConnPlay:
|
||||||
|
case SrsSrtConnPlay:
|
||||||
if (rule->arg0() != "play") {
|
if (rule->arg0() != "play") {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -141,6 +148,7 @@ srs_error_t SrsSecurity::deny_check(SrsConfDirective* rules, SrsRtmpConnType typ
|
||||||
case SrsRtmpConnFlashPublish:
|
case SrsRtmpConnFlashPublish:
|
||||||
case SrsRtmpConnHaivisionPublish:
|
case SrsRtmpConnHaivisionPublish:
|
||||||
case SrsRtcConnPublish:
|
case SrsRtcConnPublish:
|
||||||
|
case SrsSrtConnPublish:
|
||||||
if (rule->arg0() != "publish") {
|
if (rule->arg0() != "publish") {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -174,6 +174,8 @@ SrsMpegtsSrtConn::SrsMpegtsSrtConn(SrsSrtServer* srt_server, srs_srt_t srt_fd, s
|
||||||
srt_source_ = NULL;
|
srt_source_ = NULL;
|
||||||
req_ = new SrsRequest();
|
req_ = new SrsRequest();
|
||||||
req_->ip = ip;
|
req_->ip = ip;
|
||||||
|
|
||||||
|
security_ = new SrsSecurity();
|
||||||
}
|
}
|
||||||
|
|
||||||
SrsMpegtsSrtConn::~SrsMpegtsSrtConn()
|
SrsMpegtsSrtConn::~SrsMpegtsSrtConn()
|
||||||
|
@ -184,6 +186,7 @@ SrsMpegtsSrtConn::~SrsMpegtsSrtConn()
|
||||||
srs_freep(delta_);
|
srs_freep(delta_);
|
||||||
srs_freep(srt_conn_);
|
srs_freep(srt_conn_);
|
||||||
srs_freep(req_);
|
srs_freep(req_);
|
||||||
|
srs_freep(security_);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string SrsMpegtsSrtConn::desc()
|
std::string SrsMpegtsSrtConn::desc()
|
||||||
|
@ -311,6 +314,10 @@ srs_error_t SrsMpegtsSrtConn::publishing()
|
||||||
return srs_error_wrap(err, "srt: stat client");
|
return srs_error_wrap(err, "srt: stat client");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((err = security_->check(SrsSrtConnPublish, ip_, req_)) != srs_success) {
|
||||||
|
return srs_error_wrap(err, "srt: security check");
|
||||||
|
}
|
||||||
|
|
||||||
// We must do hook after stat, because depends on it.
|
// We must do hook after stat, because depends on it.
|
||||||
if ((err = http_hooks_on_publish()) != srs_success) {
|
if ((err = http_hooks_on_publish()) != srs_success) {
|
||||||
return srs_error_wrap(err, "srt: callback on publish");
|
return srs_error_wrap(err, "srt: callback on publish");
|
||||||
|
@ -333,12 +340,16 @@ srs_error_t SrsMpegtsSrtConn::playing()
|
||||||
// We must do stat the client before hooks, because hooks depends on it.
|
// We must do stat the client before hooks, because hooks depends on it.
|
||||||
SrsStatistic* stat = SrsStatistic::instance();
|
SrsStatistic* stat = SrsStatistic::instance();
|
||||||
if ((err = stat->on_client(_srs_context->get_id().c_str(), req_, this, SrsSrtConnPlay)) != srs_success) {
|
if ((err = stat->on_client(_srs_context->get_id().c_str(), req_, this, SrsSrtConnPlay)) != srs_success) {
|
||||||
return srs_error_wrap(err, "rtmp: stat client");
|
return srs_error_wrap(err, "srt: stat client");
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((err = security_->check(SrsSrtConnPlay, ip_, req_)) != srs_success) {
|
||||||
|
return srs_error_wrap(err, "srt: security check");
|
||||||
}
|
}
|
||||||
|
|
||||||
// We must do hook after stat, because depends on it.
|
// We must do hook after stat, because depends on it.
|
||||||
if ((err = http_hooks_on_play()) != srs_success) {
|
if ((err = http_hooks_on_play()) != srs_success) {
|
||||||
return srs_error_wrap(err, "rtmp: callback on play");
|
return srs_error_wrap(err, "srt: callback on play");
|
||||||
}
|
}
|
||||||
|
|
||||||
err = do_playing();
|
err = do_playing();
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
#include <srs_app_st.hpp>
|
#include <srs_app_st.hpp>
|
||||||
#include <srs_app_conn.hpp>
|
#include <srs_app_conn.hpp>
|
||||||
#include <srs_app_srt_utility.hpp>
|
#include <srs_app_srt_utility.hpp>
|
||||||
|
#include <srs_app_security.hpp>
|
||||||
|
|
||||||
class SrsBuffer;
|
class SrsBuffer;
|
||||||
class SrsLiveSource;
|
class SrsLiveSource;
|
||||||
|
@ -123,6 +124,7 @@ private:
|
||||||
|
|
||||||
SrsRequest* req_;
|
SrsRequest* req_;
|
||||||
SrsSrtSource* srt_source_;
|
SrsSrtSource* srt_source_;
|
||||||
|
SrsSecurity* security_;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
//
|
//
|
||||||
// Copyright (c) 2013-2023 The SRS Authors
|
// Copyright (c) 2023-2023 The SRS Authors
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: MIT or MulanPSL-2.0
|
// SPDX-License-Identifier: MIT or MulanPSL-2.0
|
||||||
//
|
//
|
||||||
|
@ -9,6 +9,6 @@
|
||||||
|
|
||||||
#define VERSION_MAJOR 5
|
#define VERSION_MAJOR 5
|
||||||
#define VERSION_MINOR 0
|
#define VERSION_MINOR 0
|
||||||
#define VERSION_REVISION 201
|
#define VERSION_REVISION 202
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue