Nginx Dynamic Proxy to Docker Containers

Viewed 771

I am trying to figure out a solution for this problem, unfortunately I am not much of an Nginx expert.

I am trying to figure a way to dynamically proxy to Docker containers that are running Nginx RTMP.

I would have the main Nginx image that does the "routing" and each of the RTMP instances would simply have their own configuration, allowing for each to be restarted without disturbing the others.

My question is: how?

I assume that I can dynamically route the RTMP request based on a "secret key" and then have it proxy to the appropriate port.

Something like?

server {
    listen 1935;
    chunk_size 4096;
    notify_method get;

    application live {
        on_publish http://localhost/auth;
        live on;
        record all;
        record_path /var/www/html/recordings;
        record_unique on;
        push rtmp://localhost:$dynport;
    }
}

I am just unsure how to get the auth script to pass a port number to nginx.

2 Answers

I think this isn't possible with nginx and RTMP. With HTTP it could be hacked by setting desired destination into cookies (bad idea) but with RTMP... I didn't find in Google any sign that RTMP can do anything of the sort.

I'll leave you here an example how it can be done with HTTP, maybe you'll find a way how to trick it for RTMP since I'm not really familiar with the protocol. In the example below I used curl to set cookie port and made nginx to use it in proxy directive. Nginx can access cookies with $cookie_{name} variable.

version: "3.7"

x-generator-common:
  &common
  image: curlimages/curl:latest
  depends_on:
    - nginx
  entrypoint:
    - /bin/ash
    - -c
  command:
    - while sleep 3; do curl -s -b "port=$$PORT" nginx >/dev/null; done

services:
  generator9000:
    << : *common
    environment:
      PORT: 9000

  generator3000:
    << : *common
    environment:
      PORT: 3000

  nginx:
    image: nginx:alpine
    environment:
      CONFIG: |-
        log_format test "Got request on port $$cookie_port";
        server {
          listen 80;
          access_log /var/log/nginx/access.log test;
          location / { proxy_pass http://127.0.0.1:$$cookie_port; }
        }
        server {
          listen 3000;
          listen 9000;
          access_log off;
          location / { return 200; }
        }
    entrypoint:
      - /bin/ash
      - -c
    command:
      - echo "$$CONFIG" > /etc/nginx/conf.d/default.conf && /docker-entrypoint.sh nginx -g "daemon off;"

UPD: This is an example how you can extract something from URI:

map $uri $port {
    ~^/live/(?<port>.*) $port; 
}

You can use this project I created: https://github.com/spartanz51/rtmp-interceptor

And redirect user to different RTMP server based on their rtmp key

const RTMPInterceptor = require('rtmp-interceptor')

const params = {
  listenPort: '1936'
}

RTMPInterceptor.listen(params, (client, tcUrl, SKey) => {
  console.log('tcUrl: '+tcUrl)      /* Do something with the data ... */
  console.log('StreamKey: '+SKey)

  return {                          /* Return false to block client and close stream */
    host: 'localhost',
    port: '1935'
  }
})

This will redirect user to localhost:1935

Related