Encrypting RTMP video streams using NGINX and Stunnel
Encrypting RTMP video streams using NGINX and Stunnel

Encrypting RTMP video streams using NGINX and Stunnel

Tags
SRTDockerRTMP

I was on a work site where they were transitioning from using Open Broadcast Studio1^1 to Haivision Makito X hardware encoders in order to stream an SDI video feed to social media sites (Youtube, Facebook, Twitch). The client also wanted to send a single stream out to all the platforms to conserve bandwidth, so there would be a in-cloud replication effort to re-stream the video out to each platform. I suggested the client should use Cloudflare Stream to receive the feed and then re-stream it to the social media endpoints.

Note: This setup could work with services like Restream.io, Castr.io or Wowza. The advantage to using Cloudflare (besides it being very cost-effective!) is their ability to embed HLS in a web player and to record the stream. We were also able to conserve bandwidth by sending one stream to Cloudflare and having them re-distribute it from their data center.

As of 2019, Facebook only accepts RTMPS protocol (RTMP over TLS/SSL)… and unfortunately the Haivision Makito X only outputs to RTMP:// endpoints (no support for encryption).

Like Facebook, Cloudflare requires that you use RTMPS when sending a stream to their ingest endpoints. This meant we still needed to convert the stream output to add the SSL/TLS layer. Haivision has stated they don’t plan on bringing RTMPS support to the Makito X encoder.

The three versions of the Haivision Makito X Encoder
The three versions of the Haivision Makito X Encoder

The Makito X Encoder doesn’t support RTMPs. Currently there is no plan to add RTMPS support on the Makito X Encoder. – Haivision Support

NGINX-RTMP has the ability to mirror a single RTMP feed to different endpoints, so I wondered if it could be a solution to re-wrap the stream feed with SSL/TLS to turn a RTMP feed into RTMPS. The nginx-rtmp-module doesn’t yet support RTMPS… (there is an un-merged branch with support) so I took the route most people did and used Stunnel to encrypt the RTMP stream.

Stunnel is an open-source proxy designed to add TLS encryption functionality to existing services. Using both NGINX and Stunnel you can proxy your RTMP feed to endpoints through a universal TLS/SSL tunnel. I found a Docker image that has both packages pre-configured for the exact use case I was looking for. All I needed to do was fork the repo and add Cloudflare as an endpoint / destination for your RTMP feed. (I’ve created a pull request that has now been merged with the changes).

You can download the Docker package from Github:

Using NGINX-RTMPS with Cloudflare

Deploy using Docker

docker run -it -p 1935:1935 -e CLOUDFLARE_KEY="<key>" thiagoeolima/nginx-rtmps

Build From Source

Download the repository from GitHub and unzip the folder

Navigate to the directory via the terminal:

cd nginx-rtmps-master

Build a Docker image from the folder

docker build . -t rtmps-proxy

Run the Docker image with your platform Stream Key

docker run -it -p 1935:1935 -e CLOUDFLARE_KEY=<key> rtmps-proxy

Connect your encoder and start streaming to the machine’s RTMP endpoint (in this case, something like rtmp://192.168.1.2:1935/live)

Your stream will now be mirrored to the RTMPS endpoint (in our case, Cloudflare)

Stream Flow

Haivision Makito (RTMP) → NGINX-RTMPS → Cloudflare → Social Media Destinations (Youtube, Facebook, Twitch) → Embedded Players (HLS, MPEG-DASH)

1^1OBS is a fantastic encoder (I actually think the feed looks better when encoded through OBS when compared side-by-side to the Haivision Makito X). The reason the client was transitioning to Haivision is because the Makitos operate better in a more-traditional broadcast workflow and they are known for having rock-solid hardware.