1

Long time listener, first time caller.

I want to know if there is a way to keep someone from hijacking our rtmp stream without restricting the incoming source to a particular IP address (which is what we are currently doing). The reason for this is that our isp may change our source IP on us at any time unless we pay more for a static IP (and we will if there are no other workarounds to this issue). We are using:

nginx server with the rtmp streaming module

Here is the setup:

rtmp {
        server {
                listen 1935;
                chunk_size 4096;

                application live {
                        live on;
                        meta copy;
                        hls on;
                        hls_path /mnt/hls/live;
                        hls_fragment 5s;
                        hls_playlist_length 10s;

                allow publish IP_ADDRESS_GOES_HERE;
                deny publish all;
        }
}

We are using a key with the player so that the source streamer needs to provide the key that the player will check. But this is easily viewable from the player page's source code along with the domain of the stream server which can be used to get an ip. So, if we turned off the "deny publish all" setting above anyone with the ip and the key can send a stream of their own to our website.

Again, the goal here is to be able to restrict the rtmp from receiving stream sources that aren't from our organization. I am not a security expert, IT professional, or nginx expert. I am guessing the answer(s) is going to be obvious to many of you, but if you could boil it down for an entry level person I'd much appreciate it. Thanks!

UPDATE:

I've attempted to use the on_publish directive and added the following changes:

rtmp {
        server {
                listen 1935;
                chunk_size 4096;

                application live {
                        live on;
                        on_publish http://localhost:8000/auth;
                        meta copy;
                        hls on;
                        hls_path /mnt/hls/live;
                        hls_fragment 5s;
                        hls_playlist_length 10s;

#                allow publish IP_ADDRESS_GOES_HERE;
#                deny publish all;
        }
}

and

http {

...

    server {
    
    ...

        listen 8000;
        location /auth{
            if ($arg_user != 'usernamegoeshere') {
                return 404;
            }
            if ($arg_psk = 'passwordgoeshere') {
                return 201;
            }
            return 404;
        }
    
    ...
    
    }

...

}

Using authentication with OBS does not connect. However, if I change all of the 404s to 201s the stream passes. Any thoughts? What am I missing?

Jesse York
  • 21
  • 3
  • "But this is easily viewable from the player page's source code" Why? The player doesn't need to know the RTMP ingest endpoint. I'm confused on this point. – Brad Dec 30 '21 at 23:52
  • 1
    The player opens the file from the streaming server and has to provide the streaming key. Thus I am giving away the streaming server's domain and key when I call the player from the page. I don't need to lock down people accessing the stream for viewing, but want to make sure I don't give enough info out that someone could stream to it. – Jesse York Dec 31 '21 at 00:01
  • on_* commands use POST with encoded request body, $arg_*'s are from the URL, not the request body. – Daniel Hill Apr 23 '23 at 07:24

1 Answers1

-1

NginxRTMP supports CIDR for IP_ADDRESS_GOES_HERE, like:

allow play 192.168.0.0/24;

However, it works only when your IP changes in a specified CIDR. If your IP is random, you need to write code to verify the IP or something to identify the client, like:

                                    --on-publish->--- 
Client(OBS) ---RTMP--> Nginx/Other                      Your Backend Server
                                    --<--allow/deny---

Note: For NginxRTMP, note that it use HTTP GET to access the callback, so please config the notify_method get; see #1442 or here.

If need authentication for multiple protocols, like to verify the SRT/RTMP publisher, or HLS/HTTP-FLV/WebRTC player, it's simple to use SRS with HTTP callback, please read usage from here. If it's not possible to replace your NginxRTMP server, there is a workaround solution, to use SRS as a proxy to verify the client, then forward to your NginxRTMP, like this:

                              --on-publish(play)->--- 
Client(OBS) --SRT/RTMP-> SRS  --<---allow/deny-------  Your Backend Server
                          +
                          |
                          +-->--Forward-if-Verify-ok----> NginxRTMP
                          |
                          +-->--Stream-if-Verify-ok----> Player(FLV/HLS/WebRTC)

Note: For SRS to callback your backend server to verify client, please read HTTP Callback. For SRS to forward to NginxRTMP, please read Edge or Forward.

Fair enough.

Winlin
  • 1,136
  • 6
  • 25
  • Thanks Winlin. This is the sort of thing I am attempting to accomplish with the on_publish directive shown in the markup after the UPDATE heading above. But my authentication isn't working for some reason. – Jesse York Dec 31 '21 at 02:20
  • It does an interrupt and waits for a 201 just as the on_play directive listed just before it in the docs: HTTP 2xx code continues RTMP session HTTP 3xx redirects RTMP to another stream whose name is taken from Location HTTP response header. If new stream name is started with rtmp:// then remote relay is created instead. Relays require that IP address is specified instead of domain name and only work with nginx versions greater than 1.3.10. See also notify_relay_redirect. Otherwise RTMP connection is dropped – Jesse York Dec 31 '21 at 02:29
  • Sorry, it does check the on_publish resonse code. You should specifies the `notify_method get` for NginxRTMP, please read [#442](https://github.com/arut/nginx-rtmp-module/issues/1442) or [this post](https://smartshitter.com/musings/2017/12/nginx-rtmp-streaming-with-simple-authentication/) – Winlin Dec 31 '21 at 02:32
  • Will do. Thank you! – Jesse York Dec 31 '21 at 02:48