ossrs / srs

SRS is a simple, high-efficiency, real-time media server supporting RTMP, WebRTC, HLS, HTTP-FLV, HTTP-TS, SRT, MPEG-DASH, and GB28181.
https://ossrs.io
MIT License
25.28k stars 5.33k forks source link

SRT: Support multiple querystring for authentication. #2893

Closed winlinvip closed 2 years ago

winlinvip commented 2 years ago

Because SRT does not defines the querystring, or because streamid IS actually a querystring, so it's hard to use authentication in SRT URL. For example, a general SRT url defines as bellow:

srt://127.0.0.1:10080?streamid=#!::r=live/livestream,m=publish

How to pass something like secret=xxx in the URL? It's undefined, so we defined as:

srt://127.0.0.1:10080?streamid=#!::r=live/livestream,secret=xxx,m=publish

It also allows us to pass more than one querystring, for example:

srt://127.0.0.1:10080?streamid=#!::r=live/livestream,secret=xxx,token=yyy,other=zzz,m=publish

SRT does not define QueryString, so there will be problems when switching to RTMP, and authentication cannot be done.

Usage

OBS streaming address:

With VHOST parameter:

FFPLAY playback address:

With authentication information:

Publish by FFmpeg:

ffmpeg -re -i doc/source.flv -c copy -f mpegts \
    'srt://127.0.0.1:10080?streamid=#!::r=live/livestream,secret=xxx,m=publish'

Play by ffplay:

ffplay -fflags nobuffer -flags low_delay \
  -i 'srt://127.0.0.1:10080?streamid=#!::r=live/livestream,latency=20,m=request'

Solution

If using domain (vhost) for push-pull streaming, the general correspondence between RTMP and SRT is:

It is also possible to directly use the IP to specify the domain for push-pull streaming.

Sometimes (often), SRS does not have a domain name (domain/vhost) and directly uses IP for push-pull streaming. In such cases:

Key points:

  1. In the SRT URL, the & symbol should not be used, as it will be treated as a parameter separator by ffmpeg and OBS, resulting in the loss of input parameters.
  2. For SRT, the h=hostname parameter needs to be included again in the streamid, whereas for RTMP, it is not required. This is because RTMP automatically includes the hostname in the tcUrl, while in SRT, it needs to be manually specified to differentiate the business domain.
  3. m=request|publish represents whether it is a pull or push stream. The default is a pull stream.

Note: SRS also supports multiple ports, and different ports have different default values for m. This allows for scenarios where m does not need to be specified, which is effective when there is port redundancy on the broadcasting system but the URL needs to be kept simple. However, in the internet environment, ports are usually restricted by firewalls or security groups, so it is preferable to open fewer ports and specify more information in the URL.

Regarding the definitions of h and r, please refer to SRT: Standard Keys.

Reference document:

PS: The URL of Bilibili is not informative, as the stream itself is empty, ?streamname=live_430256302_28738971, which corresponds to the RTMP stream.

Compatible

The previously defined old URL format mainly included the stream information in the h parameter. It is currently still compatible, but it will be removed in the future. Please refrain from using it.

Based on the article from the official SRT website: AccessControl

The latest modification to the SRT streaming address specification is:

URL for defaultVhost

# https://github.com/Haivision/srt/blob/master/docs/AccessControl.md
# Publish stream by SRT:
#               srt://127.0.0.1:10080?streamid=#!::h=live/livestream,m=publish
# Play stream by SRT
#               srt://127.0.0.1:10080?streamid=#!::h=live/livestream,m=request
# Play stream by RTMP:
#               rtmp://127.0.0.1/live/livestream

URL for vhost

# To use vhost in SRS.
# Publish stream by SRT:
#               srt://127.0.0.1:10080?streamid=#!::h=srs.srt.com.cn/live/livestream,m=publish
# Play stream by SRT:
#               srt://127.0.0.1:10080?streamid=#!::h=srs.srt.com.cn/live/livestream,m=request
# Play stream by RTMP:
#               rtmp://127.0.0.1/live/livestream?vhost=srs.srt.com.cn

Based on the SRT official website, the format of the stream ID has Standard Keys. The SRT service in SRS should strive to comply with the official website standards.

The Stream ID value can be used as free-form, but there is a recommended convention so that all SRT users speak the same language. The intent of the convention is to:
1. promote readability and consistency among free-form names
2. interpret some typical data in the key-value style

Comply with the YAML format, starting with #!::. The key "h" represents the vhost and appname/stream. The key "m" represents publishing (publish) or requesting (request) a stream.

TRANS_BY_GPT3

zhouxiaojun2008 commented 2 years ago

srt://127.0.0.1:10080?streamid=#!::h=live/livestream?secret=xxx&token=yyy,m=publish',In software based on libavformat implementation, the parameters after '&' will be ignored by ffmpeg. The streamid passed out will be truncated to '#!::h=live/livestream?secret=xxx'.

参考如下设计是否可行'

Please let me know the specific design you are referring to so that I can provide an accurate translation.

  1. With one parameter: SRT: 'srt://127.0.0.1:10080?streamid=#!::h=live/livestream,secret=xxx,m=publish' RTMP: rtmp://127.0.0.1/live/livestream?secret=xxx

  2. With multiple parameters SRT: 'srt://127.0.0.1:10080?streamid=#!::h=live/livestream,secret=xxx,token=yyy,m=publish' RTMP: rtmp://127.0.0.1/live/livestream?secret=xxx&token=yyy This type of single-letter format like 'h' and 'm' belongs to Standard Keys according to the official srt documentation. They cannot be customized for use. On the other hand, 'secret' and 'token' are custom keys. The value after 'streamid' will be passed to the other end during the srt handshake. Additionally, tools like ffmpeg support other parameters that can be connected using '&', but they can only be used locally in ffmpeg. For reference on the ffmpeg srt URL format, you can visit ffmpeg srt URL format. Using the mentioned format will not conflict with the av_find_info_tag parsing function in ffmpeg and is fully compliant with the official srt definition.

  3. Tencent srt URL definition

  4. "In addition, since the secret is within the stream and livestream is a string, it requires the playback to also include the secret. This makes it impossible to authenticate only the push stream without authenticating the pull stream, and it also makes it impossible to use different secrets (or tokens) for push and playback." This means that all parameters are placed within the stream.

TRANS_BY_GPT3

winlinvip commented 2 years ago

The parameters of RTMP must all be placed in the stream, not in the app.

Originally, Adobe placed them in the app, but this looks messy.

rtmp://127.0.0.1/live?secret=xxx&token=yyy?vhost=live.test.com/livestream

It's better to place them naturally in the stream.

rtmp://127.0.0.1/live/livestream?secret=xxx&token=yyy?vhost=live.test.com

Therefore, the parameters of RTMP must not be placed in the app anymore. SRS supports placing them in the app for compatibility purposes, but the new ones cannot be placed here anymore.

TRANS_BY_GPT3

winlinvip commented 2 years ago

After checking the current URL formats of Tencent and Bilibili, it seems that they are different from what we have defined.

Tencent:

srt://${rtmp-push-domain}:9000?streamid=#!::h=${rtmp-push-domain},r=${app}/${stream},txSecret=${txSecret},txTime=${txTime}

Bilibili:

Server address:
srt://live-push.bilivideo.com:1937?streamid=#!::h=live-push.bilivideo.com,r=live-bvc/?streamname=live_430256302_28738971,key=ad890c602709895446f8fb994a01393b,schedule=srtts,pflag=1

Stream key:
?streamname=live_430256302_28738971&key=ad890c602709895446f8fb994a01393b

Please make sure to determine which URL format to use and finalize the conclusion in the document. Otherwise, readers will be confused, users won't know how to use it, and the code will need to be constantly modified.

We should prioritize the documentation. The document should be finalized before working on the code. The code is ultimately meant for the users, and if we ourselves don't understand it, how can we expect the users to know how to use it?

In addition, the previous relevant documents need to be updated. Documentation is more important than code. If the documentation is not updated, even if the code is updated, it will be useless. No one will go through the code in detail just to understand how to use it.

Please everyone, first put your thoughts into a document and write them in the comments of this PR. Then I will schedule a Tencent meeting to finalize a time. Once we have confirmed, I will share it in the SRT group for others to review and see if there are any additions.

I would like to propose a few objectives:

  1. Both streaming and playback require support for multiple parameters. There is no need to specifically consider the case of a single parameter, as the URL format for both single and multiple parameters remains the same.
  2. Streaming and playback should not use the same secret. In other words, the authentication for playback must be different from that of streaming. Otherwise, if someone knows how to play the stream, they will also have streaming permissions, which is completely unacceptable.
  3. Adapt to open-source industry standards as much as possible, and prioritize compatibility with established commercial standards. Our previous definitions should only be considered if they are appropriate. Otherwise, they should be modified accordingly.

Please everyone, first share your thoughts so that we can reach a consensus on this.

TRANS_BY_GPT3

xiaozhihong commented 2 years ago

Moved to https://github.com/ossrs/srs/issues/2893#solution

winlinvip commented 2 years ago

Thanks @xiaozhihong @zhouxiaojun2008