1
0
Fork 0
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 v6.0.104 (#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:
Haibo Chen 2023-12-14 21:36:06 +08:00 committed by GitHub
parent 1b34fc4d4e
commit 6d56c407c6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 62 additions and 10 deletions

View file

@ -7,6 +7,7 @@ The changelog for SRS.
<a name="v6-changes"></a> <a name="v6-changes"></a>
## SRS 6.0 Changelog ## SRS 6.0 Changelog
* v6.0, 2023-12-14, Merge [#3902](https://github.com/ossrs/srs/pull/3902): Security: Support IP whitelist for HTTP-FLV, HLS, WebRTC, and SRT. v6.0.104 (#3902)
* v6.0, 2023-11-22, Merge [#3891](https://github.com/ossrs/srs/pull/3891): fix 'sed' error in options.sh. v6.0.103 (#3891) * v6.0, 2023-11-22, Merge [#3891](https://github.com/ossrs/srs/pull/3891): fix 'sed' error in options.sh. v6.0.103 (#3891)
* v6.0, 2023-11-22, Merge [#3883](https://github.com/ossrs/srs/pull/3883): Fix opus delay options, use ffmpeg-opus in docker test. v6.0.102 (#3883) * v6.0, 2023-11-22, Merge [#3883](https://github.com/ossrs/srs/pull/3883): Fix opus delay options, use ffmpeg-opus in docker test. v6.0.102 (#3883)
* v6.0, 2023-11-19, Merge [#3886](https://github.com/ossrs/srs/pull/3886): Change the hls_aof_ratio to 2.1. v6.0.101 (#3886) * v6.0, 2023-11-19, Merge [#3886](https://github.com/ossrs/srs/pull/3886): Change the hls_aof_ratio to 2.1. v6.0.101 (#3886)
@ -115,6 +116,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)

View file

@ -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");

View file

@ -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.

View file

@ -558,11 +558,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)
@ -600,6 +602,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");

View file

@ -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;
@ -180,6 +180,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();

View file

@ -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");

View file

@ -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();

View file

@ -75,7 +75,10 @@ srs_error_t SrsSecurity::allow_check(SrsConfDirective* rules, SrsRtmpConnType ty
switch (type) { switch (type) {
case SrsRtmpConnPlay: case SrsRtmpConnPlay:
case SrsHlsPlay:
case SrsFlvPlay:
case SrsRtcConnPlay: 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 SrsHlsPlay:
case SrsFlvPlay:
case SrsRtcConnPlay: 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;
} }

View file

@ -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();

View file

@ -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

View file

@ -1,5 +1,5 @@
// //
// Copyright (c) 2013-2023 The SRS Authors // Copyright (c) 2023-2023 The SRS Authors
// //
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
// //
@ -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

View file

@ -9,6 +9,6 @@
#define VERSION_MAJOR 6 #define VERSION_MAJOR 6
#define VERSION_MINOR 0 #define VERSION_MINOR 0
#define VERSION_REVISION 103 #define VERSION_REVISION 104
#endif #endif