Solución:
Solución 1:
Dado que NGINX es capaz de terminar TLS para servidores TCP ascendentes, esto debería encargarse de ello, utilizando solo NGINX (simplemente agregado stream
sección a la configuración de @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;
}
}
}
Solucion 2:
ACTUALIZAR: Esta es mi respuesta original que describe bastante bien los problemas que uno puede enfrentar al implementar RTMPS con Nginx. Sin embargo, he agregado un versión mejorada para un control de acceso más afinado, y recomiendo usar la configuración de este, en su lugar.
Sí, esto es posible con stunnel, ya que RTMPS es solo una sesión RTMP envuelta dentro de una sesión TLS estándar. Los ejemplos en Internet son principalmente RTMP → RTMPS, es decir, el stunnel funciona como un servidor de texto sin formato y un cliente TLS, que está configurado con client = yes
. Sin eso, el client
predeterminado a no
, Cuál es el modo servidor.
los aturdir La configuración podría verse así:
[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
Con este:
- El Nginx debería estar escuchando RTMP en bucle de retorno local, Puerto
1936/tcp
. - Como no puede renovar el certificado Let’s Encrypt usando RTMP, es posible que también necesite un bloque de servidor HTTP para el desafío HTTP-01.
-
Como la conexión a Nginx siempre proviene del stunnel, es decir, del
127.0.0.1
, no puedes usar elallow
/deny
directivas para limitar la conexión basada en direcciones IP. Esto significa que su control de acceso se limitaría a la clave, solo, pero al mismo tiempo es un problema menor, ya que se transmite encriptada.Sin embargo, esto todavía causa problemas, ya que enviaría la transmisión desde la misma IP que los clientes que la están usando, pero no puede permitirles que publiquen en su transmisión. Afortunadamente, no tienes que hacerlo
push
el flujo de la aplicación con la clave, pero también puedepull
desde la aplicación pública (/live
).
El seguimiento Nginx La configuración de ejemplo tiene en cuenta estas consideraciones:
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;
}
}
}
Sin embargo, este es solo un ejemplo, por lo que puede y debe modificarlo para que se ajuste a sus necesidades exactas. (Además, no he probado esta configuración, pero la escribí únicamente en función de la documentación, así que no dude en corregirla si me sale algo mal).
Solución 3:
Nginx RTMPS + clave de publicación secreta + control de acceso basado en dirección IP
Decidí publicar esto como otra respuesta, ya que mi primera respuesta sigue siendo una buena respuesta explicativa para mantener, y también quería darle crédito a Danila Vershinin por señalar el uso de Nginx stream{}
. Sin embargo, si bien ambas respuestas aumentan la seguridad al cifrar el contenido, incluida la clave, también eliminan la capacidad de control de acceso mediante allow
/deny
[play|publish] address|subnet|all
de El rtmp{}
módulo.
los stream{}
es decir TCP proxy tiene control de acceso propio, pero (a diferencia de rtmp{}
) no puede distinguir la publicación de la reproducción: con un solo stream{}
proxy todos pueden publicar y reproducir, o se les niega no hacer nada. Por tanto, un control de acceso que utilice tanto claves y restricciones de IP requiere una estructura con proxies separados para publicación y transmisión: un puerto TCP separado para enviar la publicación con la clave. El siguiente diagrama demuestra este diseño:
Aquí, uso el puerto estándar 1935/tcp
para el RTMPS-play y un adicional 1936/tcp
para la publicación RTMPS. Para las conexiones RTMP internas no cifradas, utilizo puertos similares 19351
y 19361
. El color rojo representa conexiones no cifradas y redes no confiables, mientras que el color verde representa conexiones cifradas y redes confiables.
El TCP proxy ahora tiene dos (RTMPS) configuraciones, pero ambos aún pueden usar el mismo certificado:
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)
}
}
Del mismo modo, ahora necesitamos dos (loopback local) separados RTMP servidores para cada aplicación:
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;
}
}
}
El control de acceso basado en IP real se realiza en el stream{}
sección, por lo que solo el deny publish all;
es obligatorio para evitar la publicación directa utilizando el /live
solicitud. He agregado el allow
directivas al rtmp{}
sección solo para aclarar (y comentar) el comportamiento predeterminado del control de acceso RTMP.