AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / server / 问题 / 1019317
Accepted
johnsonjp34
johnsonjp34
Asked: 2020-05-31 03:47:25 +0800 CST2020-05-31 03:47:25 +0800 CST 2020-05-31 03:47:25 +0800 CST

在 NGINX-RTMP 上接收 RTMPS 流

  • 772

RTMP 的标准做法仍然是在线路上输出纯文本流密钥。

我想接受从编码器到 NGINX 的 RTMPS 流,但是 RTMP 模块还没有 RTMPS。

我对所有允许通过 RTMPS 获取 RTMP 流并发送到 facebook 之类的地方的中继解决方案不感兴趣,因为相同的安全漏洞仍然存在,因为在某些时候您正在通过纯文本传递密钥。

我的问题是在哪里可以找到 RTMPS 的参考规范?我想知道在 OBS 和 NGINX 等 RTMPS 源之间进行正确握手需要哪些密钥,然后我将使用与 RTMP 模块的连接。可以在服务器上使用普通密钥和 Let's Encrypt 之类的授权,以便它可以与 RTMPS 编码器进行握手吗?

我见过用于在 TLS 中包装 RTMP 的 stunnel。是否可以反过来 - 使用 stunnel 接收 RTMPS 并将 RTMP 模块转换回 RTMP?

ssl nginx rtmp
  • 4 4 个回答
  • 11288 Views

4 个回答

  • Voted
  1. Danila Vershinin
    2020-05-31T07:54:59+08:002020-05-31T07:54:59+08:00

    由于 NGINX 能够为上游 TCP 服务器终止 TLS,因此应该只使用 NGINX 来处理它(只需stream从@Esa Jokinen 将部分添加到配置中):

    stream {
        upstream backend {
            server 127.0.0.1:1936;
        }
        server {
            listen 1935 ssl;
            proxy_pass backend;
            ssl_certificate /etc/letsencrypt/live/rtmp.example.com/fullchain.pem;
            ssl_certificate_key /etc/letsencrypt/live/rtmp.example.com/privkey.pem;
        }
    }
    
    rtmp {
        server {
            listen 127.0.0.1:1936;
            chunk_size 4096;
    
            application app-secret-stream-key {
                live on;
                record off;
                allow publish 127.0.0.1;  # for streaming through stunnel
                allow play 127.0.0.1;     # for the pull from /live
            }
    
            application live {
                live on;
                record off;
                deny publish all;         # no need to publish on /live
                allow play all;           # playing allowed
    
                pull rtmp://127.0.0.1:1936/app-secret-stream-key;
            }
        }
    }
    
    http {
        server {
            listen 80;
            server_name rtmp.example.com;
    
            location ^~ /.well-known/acme-challenge/ {
                root /var/www/letsencrypt;
            }
            location / {
                return 404;
            }
        }
    }
    
    • 7
  2. Esa Jokinen
    2020-06-07T04:42:55+08:002020-06-07T04:42:55+08:00

    Nginx RTMPS + 秘密发布密钥 + 基于 IP 地址的访问控制

    我决定将此作为另一个答案发布,因为我的第一个答案仍然是一个很好的解释性答案,我还想感谢Danila Vershinin指出使用 Nginx 的stream{}. 然而,虽然这两个答案都通过加密包括密钥在内的内容来提高安全性,但它们也消除了使用模块的/进行访问控制的能力。allowdeny [play|publish] address|subnet|allrtmp{}

    stream{}ie代理的TCP有自己的访问控制,但(不像rtmp{})它不能区分发布和播放:使用单个stream{}代理,每个人都可以发布和播放 - 或者被拒绝做任何一个。因此,同时使用密钥和 IP 限制的访问控制需要一个结构,该结构具有用于发布和流式传输的单独代理:一个单独的 TCP 端口,用于使用密钥代理发布。下图演示了这种设计:

    在此处输入图像描述

    在这里,我为 RTMPS-play 使用标准端口,为 RTMPS-publish1935/tcp使用附加端口。1936/tcp对于内部未加密的 RTMP 连接,我使用类似的端口19351和19361. 红色代表未加密的连接和不受信任的网络,而绿色代表加密的连接和受信任的网络。

    代理的 TCP 现在有两个 ( RTMPS ) 配置,但两者仍然可以使用相同的证书:

    stream {
        upstream publish {
            server 127.0.0.1:19361;
        }
        server {
            listen 1936 ssl;        # additional port for publishing
            proxy_pass publish;
            ssl_certificate /etc/letsencrypt/live/rtmp.example.com/fullchain.pem;
            ssl_certificate_key /etc/letsencrypt/live/rtmp.example.com/privkey.pem;
    
            allow 192.0.2.1;        # allow publish from this IP
            allow 192.0.2.0/24;     # -- also supports CIDR notation!
            deny all;               # deny publish from the rest
        }
    
        upstream live {
            server 127.0.0.1:19351;
        }
        server {
            listen 1935 ssl;        # standard RTMP(S) port
            proxy_pass live;
            ssl_certificate /etc/letsencrypt/live/rtmp.example.com/fullchain.pem;
            ssl_certificate_key /etc/letsencrypt/live/rtmp.example.com/privkey.pem;
    
            allow all;              # this is public (this is also the default)
        }
    }
    

    同样,我们现在需要为每个应用程序提供两个单独的(本地环回)RTMP服务器:

    rtmp {
        server {
            listen 127.0.0.1:19361;
            chunk_size 4096;
    
            application secret-key {
                live on;
                record off;
                allow publish 127.0.0.1;  # publishing through rtmps://rtmp.example.com:1936
                allow play 127.0.0.1;     # for the pull from rtmp://localhost:19351/live
            }
        }
    
        server {
            listen 127.0.0.1:19351;
            chunk_size 4096;
    
            application live {
                live on;
                record off;
                deny publish all;         # no need to publish on /live -- IMPORTANT!!!
                allow play 127.0.0.1;     # playing through rtmps://rtmp.example.com:1935/live
    
                pull rtmp://127.0.0.1:19361/secret-key;
            }
        }
    }
    

    实际基于 IP 的访问控制是在该stream{}部分完成的,因此只有deny publish all;防止使用应用程序直接发布是强制性的/live。我将allow指令添加到该rtmp{}部分只是为了阐明(和评论)RTMP 访问控制的默认行为。

    • 6
  3. Best Answer
    Esa Jokinen
    2020-05-31T06:23:32+08:002020-05-31T06:23:32+08:00

    更新:这是我的原始答案,很好地描述了使用 Nginx 实现 RTMPS 时可能面临的问题。但是,我添加了一个改进版本,以实现更精细的访问控制,我建议使用其中的配置。


    是的,这可以通过 stunnel 实现,因为 RTMPS 只是包装在标准 TLS 会话中的 RTMP 会话。网上的例子大多是RTMP→RTMPS,即stunnel作为纯文本服务器和TLS客户端工作,配置client = yes. 没有它,client默认为no,即服务器模式。

    stunnel配置可能如下所示:

    [rtmps]
    accept = 1935
    connect = 127.0.0.1:1936
    cert=/etc/letsencrypt/live/rtmp.example.com/fullchain.pem
    key=/etc/letsencrypt/live/rtmp.example.com/privkey.pem
    

    有了这个:

    • Nginx 应该在本地环回端口上侦听 RTMP 1936/tcp。
    • 由于您无法使用 RTMP 更新 Let's Encrypt 证书,因此您可能还需要一个 HTTP 服务器块来处理 HTTP-01 质询。
    • 由于与 Nginx 的连接始终来自 stunnel,即来自127.0.0.1,因此您不能再使用allow/deny指令来限制基于 IP 地址的连接。这意味着您的访问控制将仅限于密钥,但同时它不是问题,因为它是加密传输的。

      但是,这仍然会导致问题,因为您将从与使用它的客户端相同的 IP 推送流,但您不能允许它们发布到您的流。幸运的是,您不必push使用密钥从应用程序中获取流,但您也pull可以从公共应用程序 ( /live) 中获取。

    以下Nginx示例配置考虑了这些注意事项:

    rtmp {
        server {
            listen 127.0.0.1:1936;
            chunk_size 4096;
    
            application app-secret-stream-key {
                live on;
                record off;
                allow publish 127.0.0.1;  # for streaming through stunnel
                allow play 127.0.0.1;     # for the pull from /live
            }
    
            application live {
                live on;
                record off;
                deny publish all;         # no need to publish on /live
                allow play all;           # playing allowed
    
                pull rtmp://127.0.0.1:1936/app-secret-stream-key;
            }
        }
    }
    
    http {
        server {
            listen 80;
            server_name rtmp.example.com;
    
            location ^~ /.well-known/acme-challenge/ {
                root /var/www/letsencrypt;
            }
            location / {
                return 404;
            }
        }
    }
    

    但是,这只是一个示例,因此您可以并且应该对其进行修改以满足您的确切需求。(另外,我没有测试过这个配置,只是根据文档编写的,所以如果我有错误,请随时纠正。)

    • 4
  4. Code Rider
    2020-11-21T15:23:15+08:002020-11-21T15:23:15+08:00

    不确定这在这里是否有效,但我使用与代理协议相同的简单 SSL 终止来保留客户端 IP 地址。RTMP 模块支持代理协议,因此您仍然可以允许通过 IP 地址拒绝。做了一些基本的测试,它似乎工作得很好,日志中的正确消息和通过 IP 地址拒绝工作。

    也许我错过了理解,但它似乎正在做我认为应该做的事情,即允许通过 RTMPS 进行 SSL 连接,并在 RTMP 模块中保留客户端 IP 地址以进行访问控制。

    我的流块如下所示:

    stream {
    
        upstream backend {
            server 127.0.0.1:1935;
        }
    
        server {
            listen 1936 ssl;
            proxy_pass backend;
            proxy_protocol on;
            ssl_certificate /etc/..../fullchain.pem;
            ssl_certificate_key /etc/.../privkey.pem;
        }
    }
    

    以及我的 RTMP 部分的相关位:(注意:直接连接可能无法正常工作,但没有尝试过......在博客中建议了这一点(见下文),但我不需要直接连接)。

    rtmp {
        server {
    
            listen 1935 proxy_protocol;
            chunk_size 4000;
    
         
            application stream_app{
                live on;
                .....
                .....
                .....
                }
            }
        }
    }
    

    您可以在 RTMP 博客http://nginx-rtmp.blogspot.com中了解它。

    希望它对某人有所帮助,并感谢上面的答案,因为他们为我指明了正确的方向。

    仅供参考,我在推出 HLS 时拒绝所有游戏,目前不需要游戏或其他任何东西。

    • 2

相关问题

  • 如何使用 Tomcat 5.5 更新 SSL 证书

  • 为 IIS6 自行生成 SSL 证书?

  • plesk 上的域和子域 ssl 访问

  • 如何设置 SSL 邮件服务器?

  • 如何通过 SVN 命令行接受 SSL 证书?

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    新安装后 postgres 的默认超级用户用户名/密码是什么?

    • 5 个回答
  • Marko Smith

    SFTP 使用什么端口?

    • 6 个回答
  • Marko Smith

    命令行列出 Windows Active Directory 组中的用户?

    • 9 个回答
  • Marko Smith

    什么是 Pem 文件,它与其他 OpenSSL 生成的密钥文件格式有何不同?

    • 3 个回答
  • Marko Smith

    如何确定bash变量是否为空?

    • 15 个回答
  • Martin Hope
    Tom Feiner 如何按大小对 du -h 输出进行排序 2009-02-26 05:42:42 +0800 CST
  • Martin Hope
    Noah Goodrich 什么是 Pem 文件,它与其他 OpenSSL 生成的密钥文件格式有何不同? 2009-05-19 18:24:42 +0800 CST
  • Martin Hope
    Brent 如何确定bash变量是否为空? 2009-05-13 09:54:48 +0800 CST
  • Martin Hope
    cletus 您如何找到在 Windows 中打开文件的进程? 2009-05-01 16:47:16 +0800 CST

热门标签

linux nginx windows networking ubuntu domain-name-system amazon-web-services active-directory apache-2.4 ssh

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve