NODED.CLOUD/Blog/SRT and RTMP Ingest DDoS Protection for a Self-Hosted Server

SRT and RTMP Ingest DDoS Protection for a Self-Hosted Server

24 Oct 2026 · Mario Marin

Why self-hosted SRT and RTMP ingests get attacked, what 100 Gbps of included Layer 3/4 filtering removes, and the ingest-side work: SRT passphrases and stream IDs, MediaMTX and nginx-rtmp auth, RTMPS, and a backup ingest in a second city.

You run your own ingest, MediaMTX or nginx-rtmp on a VPS, so OBS, an IRL backpack or a co-streamer's encoder sends to you rather than straight to a platform. Then the feed freezes mid-show and the server's network graph goes vertical. Good SRT and RTMP ingest DDoS protection has to cover two things: floods aimed at the port, and connections that should never have been accepted.

This post covers why self-hosted ingests become targets, what Noded's included filtering removes, SRT passphrases and stream IDs, RTMP key security in MediaMTX and nginx-rtmp, keeping viewers off the ingest IP, and a backup ingest in a second city. Installing the server is in our MediaMTX setup guide; config keys here match MediaMTX v1.21.2.

Why a self-hosted ingest becomes a target

An ingest address is meant to be private, but it travels further than you think:

  • OBS profiles passed between editors and moderators, with the server URL and key inside.
  • IRL rigs. Phone apps and bonding encoders store the relay address, and the phone gets lent out, screenshotted for a tutorial or shown on stream while you fix a setting.
  • Co-streamers and guests who got the URL in a Discord DM and still have it months later.
  • Stats pages that bitrate switchers and overlays poll. If the page answers anyone, its URL gives away the IP.
  • DNS and certificates. A hostname resolves for anyone, and publicly trusted TLS certificates are logged in public Certificate Transparency logs, hostname included.

Anyone who wants your stream down needs only one of those leaks. So "hiding" the IP means limiting who gets it, keeping it off everything public and being able to replace it quickly.

SRT and RTMP ingest DDoS protection: what is filtered before your port

Every Noded KVM VPS, media server VPS and dedicated server sits behind 100 Gbps of always-on DDoS protection at Layers 3 and 4, included at no extra cost. Attack traffic is dropped upstream, before it reaches the server's port, and clean traffic keeps flowing. For an ingest, that covers the two classic attacks:

  • UDP floods on the SRT port, including DNS and NTP amplification. Unfiltered, a flood on 8890/udp fills the link your contribution packets share, and SRT can only re-send so much inside its latency window.
  • SYN floods on 1935/tcp, or 443 if you run RTMPS there, which would otherwise use up connection slots before OBS completes a handshake.

Above 100 Gbps, the first five such attacks in a month are still mitigated; from the sixth, the attacked IP is null-routed until the attack stops or the server moves to a higher tier.

What upstream filtering cannot judge is whether a well-formed connection is welcome. Someone holding your stream key, a script guessing keys or an HTTP flood against HLS on the same box all look like ordinary traffic at Layers 3 and 4, and Layer 7 filtering exists only on the 10 Tbps tier. The rest is ingest-side work.

SRT: passphrase encryption and stream ID access control

SRT gives you two separate controls; use both.

The passphrase switches on AES encryption. In FFmpeg's SRT implementation, which OBS uses, it must be 10 to 79 characters, and pbkeylen sets the key length: 16, 24 or 32 bytes for AES-128, -192 or -256. Set pbkeylen on the sender only; the receiver takes it from the handshake. The passphrase is never sent, as both ends derive keys from it, and by default a caller with a different passphrase, or none, is rejected.

The stream ID says who the caller is and what it wants. Haivision's access-control guidelines define a #!:: syntax with keys such as u (user), r (resource) and m (publish or request), up to 512 characters. MediaMTX accepts that form (reading s as the password) as well as its own publish:path:user:pass. The catch: SRT encrypts only data-packet payloads, so the stream ID crosses the network in the clear during the handshake. Treat it as a login someone on the path could read, and rely on the passphrase for privacy.

authInternalUsers:
  - user: obs
    pass: long-random-publish-secret
    permissions:
      - action: publish
        path: live
paths:
  live:
    srtPublishPassphrase: encoder-passphrase-min-10

Replacing authInternalUsers removes the default entry, which lets anyone publish and read any path. Nobody gets read permission at all; the ingest pushes the stream onwards itself, as the backup section shows. In OBS, pick a Custom service, leave the key empty and use a server like:

srt://203.0.113.10:8890?streamid=publish:live:obs:long-random-publish-secret&passphrase=encoder-passphrase-min-10&pbkeylen=32&pkt_size=1316&latency=500000

OBS's SRT guide notes that latency is in microseconds, so this is half a second; choosing it is covered in our SRT ingest post.

RTMP stream key security, publish rules and RTMPS

Plain RTMP sends the stream key in clear text. Treat it as a password: never on screen, one per person, rotated after every leak.

MediaMTX

The same users cover RTMP, with credentials in the query string: in OBS, server rtmp://203.0.113.10, stream key live?user=obs&pass=long-random-publish-secret. The authentication docs cover hashed passwords, an external HTTP check (authMethod: http, any 2xx allows) and a fail2ban filter for repeated failed logins. Two more settings matter:

  • RTMPS. rtmpEncryption: "strict" with rtmpServerKey and rtmpServerCert serves TLS on rtmpsAddress (1936 by default) and closes plain 1935. MediaMTX's OBS page warns that OBS silently rejects self-signed certificates, so use a publicly trusted one on a hostname that does not say what it is.
  • overridePublisher defaults to true: anyone with publish rights can disconnect your encoder and take the path. After a leak that is a hijack, so rotate the secret first.

nginx-rtmp

The nginx-rtmp-module directives offer allow publish/deny publish by address, which suits a studio on a fixed IP but not a phone on mobile data, and on_publish, which asks an HTTP endpoint you write: 2xx continues, 3xx renames the stream to the Location header, anything else disconnects. Use the rename. OBS sends the key as the stream name, and with hls on the playlist is named after it, putting your key in every viewer's URL.

stream {
    server {
        listen 443 ssl;
        ssl_certificate     /etc/letsencrypt/live/in1.example.net/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/in1.example.net/privkey.pem;
        proxy_pass 127.0.0.1:1935;
    }
}
rtmp {
    server {
        listen 127.0.0.1:1935;
        application live {
            live on;
            on_publish http://127.0.0.1:8080/rtmp-auth;
            drop_idle_publisher 10s;
            deny play all;
            push rtmp://203.0.113.20/live;
        }
    }
}

nginx-rtmp has no TLS listener, so the stream module (libnginx-mod-stream on Debian) terminates RTMPS on 443 and OBS uses rtmps://in1.example.net:443/live. Every publisher then appears as 127.0.0.1, so IP rules stop working and the key check does the job. drop_idle_publisher clears a dead session that would otherwise hold the stream name when your encoder reconnects. Setup basics are in our RTMP server post.

Keep viewers, stats and APIs off the ingest IP

The ingest has one job: receive from encoders you trust and push the stream to one place. Viewers should never connect to it. Serve HLS from a separate playback box, or a CDN in front of one, so the ingest address stays out of page source and playlists and HTTP floods hit something your show does not depend on. Our self-hosted apps post covers what a CDN can and cannot do; on a MediaMTX playback box, hlsCDNSecret identifies the CDN's requests.

PortPurposeOpen to
8890/udpSRTAnywhere; the passphrase decides
1936/tcp or 443/tcpRTMPSAnywhere; the key decides
1935/tcpPlain RTMPClosed, unless an encoder cannot do RTMPS
8554, 8888, 8889, 8189, 8892–8893RTSP, HLS, WebRTC, Media-over-QUICClosed; set rtsp, hls, webrtc, moq to no
9997, 9998, nginx statsAPI, metrics, rtmp_statLocalhost or the one machine that polls them

With unused protocols off in the config, a firewall mistake exposes nothing. Give each guest their own credentials, or their own small ingest, so one leaked config costs one secret or one €4 box rather than the main show. If a public hostname ever pointed at the ingest, assume the address is known.

A backup ingest in a second city

Filtering absorbs most floods, but two things still take an ingest off air: a host failure and the null-route. If the address takes a sixth attack above 100 Gbps in a month, it stays null-routed until the attack stops or the server moves to a higher tier, which can mean the rest of your broadcast. The null-route applies to the attacked address, so a second ingest on its own IP in another city gives you somewhere to go.

Build the backup as a copy with its own credentials, pushing to the same playback box:

paths:
  live:
    srtPublishPassphrase: encoder-passphrase-min-10
    forward:
      - dest: srt://203.0.113.20:8890?streamid=publish:live:ingest-b:SECRET&passphrase=playback-passphrase-min-10

On the playback box, give each ingest a publish user pinned with ips to its address. With overridePublisher on there, whichever ingest publishes last takes the path, so viewers keep the same URL. Keep the backup's address out of shared profiles until you need it.

The weak point is the encoder. OBS streams to one server per output, and its automatic reconnect (on by default, 2-second delay, 25 attempts) retries the same address. It has no backup URL for custom servers; the "Backup YouTube ingest server" in its list is just another server you select. Realistic options:

  • A second OBS profile pointing at the backup: stop, switch profile, start. Rehearse it.
  • Both at once with a multi-output plugin such as obs-multi-rtmp. That doubles your upload, and each ingest must forward to a different path with the switch made downstream, or the feeds keep displacing each other.
  • IRL rigs usually send to one relay per profile, so save the backup as a second profile and check your app's documentation before assuming it fails over by itself. If a studio OBS pulls the feed in, NOALBS can watch several ingest servers by priority and switch scenes when one goes offline.

Neither ingest needs much: one 8 Mbps feed forwarded to a playback box and two platforms is 24 Mbps out, a quarter of the smallest standard VPS's 100 Mbps ceiling.

What this is not

Not a way to make an ingest unattackable. The included tier filters Layers 3 and 4 up to 100 Gbps and null-routes the attacked IP from the sixth attack above 100 Gbps in a month; below 10 Tbps there is no Layer 7 filtering, so HLS needs a CDN or reverse proxy for HTTP floods. Both cities sit on the same network, AS60982, with transit from one upstream carrier, so a second city covers a null-routed address or a failed host, not every network problem. You install, patch and rotate secrets yourself. Standard VPS shapes are capped at 100 to 300 Mbps, fine for an ingest but not for serving viewers, and no VPS has a GPU, so encode renditions on the sender.

How Noded Can Help

For most creators, two standard VPS I ingests are enough: €4 a month in Bucharest and €5 in Warsaw or Amsterdam (€5.50 in Ashburn for US East), each with 1 vCPU, 2 GB of RAM, a 100 Mbps ceiling and 100 Gbps of protection included, from the VPS page. Put viewers on a media server VPS, unshaped with no per-VM ceiling, from €9.99 a month in Bucharest, with a CDN in front for large audiences. If an ingest is a known target, pick a higher DDoS protection tier when you configure it: 500 Gbps is €156.45 a month per server. To move an existing server to a higher tier or choose which two cities to pair, open a ticket.

FAQ

Does DDoS protection cover an SRT ingest on UDP?

Yes, at Layers 3 and 4. On Noded, 100 Gbps of always-on filtering is included with every VPS and drops UDP floods, including DNS and NTP amplification, upstream of the server's port. It cannot tell a welcome SRT caller from an unwelcome one that sends valid packets, so you still need a passphrase and per-user stream IDs.

How do I hide my RTMP server IP?

You cannot keep it secret from anyone holding an encoder config, so limit who has it and keep it off everything public. Serve viewers from a separate box or CDN, keep stats pages and APIs private, give guests their own credentials, and keep a second ingest on another IP ready to switch to.

How do I encrypt an SRT stream with a passphrase?

Add passphrase=your-secret&pbkeylen=32 to the encoder's SRT URL for AES-256, and set the same passphrase on the server; in MediaMTX that is srtPublishPassphrase on the path. FFmpeg, which OBS uses, needs 10 to 79 characters. Callers with a missing or wrong passphrase are refused.

Can OBS switch to a backup ingest server automatically?

Not on its own. OBS reconnects automatically, by default every 2 seconds for up to 25 attempts, but always to the same server. For a backup, keep a second profile pointing at the other ingest and switch by hand, or send to both with a multi-output plugin and switch downstream.

What happens if my ingest IP is null-routed?

On Noded's included tier, the first five attacks above 100 Gbps in a month are mitigated. From the sixth, the attacked address is null-routed until the attack stops or the server moves to a higher tier. Traffic to it is dropped, so the stream stops until your encoder switches to a backup ingest on a different IP.

← All posts

Related services

Run this on NODED.CLOUD.

Keep reading

More from the NOC.

22 Oct 2026·Mario Marin

DDoS Protection for Self-Hosted Apps: A Hands-On Guide

What the included 100 Gbps of Layer 3/4 filtering does for a self-hosted VPS, and what stays your job: nginx rate limits with a strict login zone, Nextcloud, Vaultwarden and Synapse limits, CrowdSec or fail2ban, and where a CDN stops.

Read post
04 Aug 2026·Mario Marin

SRT Ingest Server Hosting

RTMP falls apart on unstable contribution feeds. Here's when SRT ingest wins, the latency numbers that matter, and how to stand up an SRT gateway with MediaMTX or MistServer on a full-root streaming VPS.

Read post

Like the way we run things? Spin up a server in 60 seconds.