Haivision / srt

Secure, Reliable, Transport
https://www.srtalliance.org
Mozilla Public License 2.0
3.06k stars 840 forks source link

[FR] DTLS support for SRT #1297

Open alexpokotilo opened 4 years ago

alexpokotilo commented 4 years ago

SRT with streamid may be great replacement for rtmps but:

If we add DTLS support into SRT(with or without server certificate validation) many users can use SRT in the same set of use-cases:

Now SRT cannot replace RTMPS for cases when many not predefined publishers(like rtmps youtube publishers) publish SRT into single ip:port. Maybe I missed something in SRT features but I think I don't

jeandube commented 4 years ago

@alexpokotilo with streamID and listen_callback features, the publisher model can be implemented with each publisher having its own passphrase. See the AccessControl.md document in the doc directory.

ethouris commented 4 years ago

The srt-test-live application contains an example listener callback called "user-password". This simply reads the username from StreamID, both as raw and through the syntax of #!::u=USERNAME, then depending on the user, it sets the passphrase through the option on the freshly created accepted socket. When the callback handler exits with success, the handshake processing continues and the password check is already against the password that the listener callback has set.

A more advanced authentication can be done by making a generated passphrase and session ID and passed over a separate connection before the real stream connection. For this purpose there's intended the s key for a one-shot session ID and the t key to specify the purpose of the connection, auth value in this case.

alexpokotilo commented 4 years ago

@jeandube, @ethouris, thanks a lot for replies guys! The main problem with approach you proposed is interoperability between implementations. This is a killer for this approach. Just imagine what we have in SRT ecosystem if each vendor implement it's own listen_callback-based approach. E.g our company support several SRT based products and we can implement "listen_callback" method in all of them but this method will not work with other vendors as there is no any standard "listen_callback"-based method everybody agreed. And this method shouldn't be implemented if we don't want to have the same "signaling" interoperability problems as webRTC has. So DTLS is a standard traffic encryption ptotocol implemented in openSSL and RFC driven. I understand and agree that simple passphrase approach initially implemented in SRT is sufficient for simple cases when we have predefined set of senders and receivers. But if we want to replace RTMP we cannot do that with custom approach like "listen_callback" because we drop interoperability between vendors. From my point of view the main SRT feature is interoperability between vendors and we should go this way further. And this means that proposed "listen_callback" method is not a solution but DTLS is.

DTLS/HTTPS/RTMPS is more convenient from another hand. When you open https://github.com all your traffic is encrypted and you don't have to specify session key to access https site. I think passphrase now used for both publish authorization and traffic encryption but if we implement DTLS we get traffic encryption out of the box and each vendor can implement authorization based on streamid. This is more secure too as passphrase is used multiple times while DTLS session key is changed on each session and probably during long sessions as well.

ethouris commented 4 years ago

When you open Github all your traffic is encrypted because you use it by the web browser, which has builtin mechanism to operate with CA certificates, and the session keys required for this connection are generated by the browser and interchanged with the server.

That's simply the matter which things can be implemented by the library, and which only by the application. I'm not sure how WebKit library solves this problem.

My idea was to make one connection with key interchange (maybe an overlay library that will enclose this process in a black box?), and after the application gets the session ID and per-session generated PSK, it uses them for configuring the passphrase and Session ID in StreamID option. Whether the auth part involves authorization or authentication check, is another matter.

I'd have to educate myself a little bit better, but after first partial taking a look it seems like DTLS is enhanced towards TLS with things that SRT already implements (a file-type SRT connection is just as reliable as TCP). I think then, possibly implementing something like what TLS is for TCP would be more feasible...

alexpokotilo commented 4 years ago

When you open Github all your traffic is encrypted because you use it by the web browser, which has builtin mechanism to operate with CA certificates, and the session keys required for this connection are generated by the browser and interchanged with the server.

That's simply the matter which things can be implemented by the library, and which only by the application. I'm not sure how WebKit library solves this problem.

it doesn't matter what browser components implement https parts from my POV. Finally I don't have to specify session key for github repo but with SRT I have to do that now. I can also connect to github via curl and will get the same result - encrypted traffic without session key specification. curl doesn't have WebKit for sure but it works the same way as browser. Why? Because both browser, curl, web server etc works according to https standard. https = http over tls. tls is envelop for every http delivery. You are right that library cannot response for everything and it's good to see it's responsibility boundaries in advance. If we include key exchange processing in the library this will simplify application development and hence: ffmpeg, vlc, etc and all commercial software vendors will not have to implement they wheel and will be compatible with each other. DTLS implementations ignores CA checks by the way. At least webRTC completely ignores root CA checks and allow to use self-signer certificates. SRT with it's passphrase is more secure as this prevents us from man-in-the-middle attacks.

My idea was to make one connection with key interchange (maybe an overlay library that will enclose this process in a black box?), and after the application gets the session ID and per-session generated PSK, it uses them for configuring the passphrase and Session ID in StreamID option. Whether the auth part involves authorization or authentication check, is another matter.

To exchange PSK in separate session you need to protect this separate session with something secret or your PSK may be discovered and used to decrypt later "main" session. And this means you need to have passphrase in anyway and this will make you proposal useless. If I'm wrong - please explain your approach step-by-step. Even if I'm wrong I don't see why we cannot exchange key in the single session. Just create new version of handshake and if user set "session_key_exchange" property before 'connect'/'listen' SRT will exchange session key during handshake. When handshake is done user can use session_id for authorization purposes. But I vote for "dtls_handshake" property below. I proposed "session_key_exchange" just to show my view about separate session for key exchange. I'm against this approach.

I'd have to educate myself a little bit better, but after first partial taking a look it seems like DTLS is enhanced towards TLS with things that SRT already implements (a file-type SRT connection is just as reliable as TCP). I think then, possibly implementing something like what TLS is for TCP would be more feasible...

DTLS doesn't reorder/recover UDP datagrams. it just encrypts datagrams and allows to decrypt it. It probably works like TCP at the beginning of the session during dtls handshake as every packet matters but once negotiated it just encrypts datagrams without any further processing. you still have to reorder/recover them as SRT already did. This is what I learned when looked at webRTC servers where DTLS is used as a transport for all UDP-based protocols.

DTLS may wrap SRT packets after initial "dtls_enabled" handshake. e.g