Summary
An unauthenticated RTMP peer can hold server connection slots indefinitely by cycling pause/unpause commands, even when it never receives any outbound relay media.
Attacker
Any network client that can complete the RTMP handshake and AMF connect exchange against a librtmp2 server.
Controlled input
Repeated pause(true) / pause(false) NetStream commands on a playing session that has never received relayed media (media_bytes_sent == 0).
Attack path
- Connect, send
connect, createStream, and play for any stream name (no publisher required).
- Before the 10-second setup-timeout reaper closes the idle viewer, send
pause(true).
- The pause handler resets
session_setup_started, granting another full grace window.
- Briefly send
pause(false) so the next pause(true) is accepted (timer reset only fires on transitions into paused state).
- Repeat steps 2-4 every few seconds.
Because the player never receives relay data, the post-2f40c6d idle-viewer reaper never applies the slow-reader exemption, yet each pause transition keeps refreshing the timeout anchor.
Impact
Medium — denial of service. With max_connections configured, the attacker can exhaust all available slots and deny legitimate publishers/players. With unlimited connections, each squatter retains per-connection buffers and poll-loop work.
Location
src/session/conn.rs
Remediation
Only refresh session_setup_started on pause when the viewer has actually received outbound relay (media_bytes_sent > 0), preserving the grace window for legitimate paused viewers while blocking timer reset for squatters.
Summary
An unauthenticated RTMP peer can hold server connection slots indefinitely by cycling
pause/unpausecommands, even when it never receives any outbound relay media.Attacker
Any network client that can complete the RTMP handshake and AMF
connectexchange against alibrtmp2server.Controlled input
Repeated
pause(true)/pause(false)NetStream commands on a playing session that has never received relayed media (media_bytes_sent == 0).Attack path
connect,createStream, andplayfor any stream name (no publisher required).pause(true).session_setup_started, granting another full grace window.pause(false)so the nextpause(true)is accepted (timer reset only fires on transitions into paused state).Because the player never receives relay data, the post-
2f40c6didle-viewer reaper never applies the slow-reader exemption, yet each pause transition keeps refreshing the timeout anchor.Impact
Medium — denial of service. With
max_connectionsconfigured, the attacker can exhaust all available slots and deny legitimate publishers/players. With unlimited connections, each squatter retains per-connection buffers and poll-loop work.Location
src/session/conn.rsRemediation
Only refresh
session_setup_startedon pause when the viewer has actually received outbound relay (media_bytes_sent > 0), preserving the grace window for legitimate paused viewers while blocking timer reset for squatters.