Repository navigation
security(srt-listen): enforce SRT passphrase on the public guest listener - #40
Draft
guycochran wants to merge 1 commit into
Draft
guycochran wants to merge 1 commit into
guycochran wants to merge 1 commit into
Conversation
…guest listener In srt-listen mode (the quickstart default) mediamtx's SRT server is off, so the existing MXL_GUEST*_SRT_PASSPHRASE settings were ignored and the public guest ports accepted any caller. - tools/guest_av_listen.sh: the A/V fan-out (owns the public port) passes passphrase= to its srtsrc listener when MXL_GUEST_SRT_PASSPHRASE is set; validates first and exits 2 on a bad value; loud warning when unset. Loopback legs stay unencrypted. - tools/adapters.py / guest_ingest.py: SrtListenerGuestAdapter takes an optional passphrase (launch string byte-identical when unset); guest_ingest reads MXL_GUEST_SRT_PASSPHRASE in srt-listen mode and fails closed on invalid values. - scripts/quickstart.sh: validates per-slot/shared passphrases in listen mode, hands them to each fan-out via env inheritance (not docker argv), reports which slots require one and warns loudly about open slots. - Passphrase charset limited to URL-unreserved A-Za-z0-9._~- (10-79 chars) so it survives both gst-launch argv and a caller's srt:// URL unescaped. - docs/TESTERS.md: how to lock guest slots. tests/test_srt_listen_passphrase.py. No behaviour change unless a passphrase variable is set. Signed-off-by: Guy Cochran <guycochran@gmail.com>
Owner
Author
|
Decision (Guy): /join contributor policy = passphrase (this PR). Public contributors must present the SRT passphrase; the /join QR embeds it so legit scanners stay one-tap. Approval-first lobby is a possible later addition, not now. This PR is #2 in the merge order (#38→**#40**→#37→#39→#41). Open sub-question in docs/REVIEW-RESPONSE.md: should the passphrase also gate multiview visibility, or is passphrase-to-publish enough? |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
In
srt-listenmode (the quickstart default), mediamtx's SRT server is disabled, soMXL_GUEST_SRT_PASSPHRASE/MXL_GUEST1_SRT_PASSPHRASE/MXL_GUEST2_SRT_PASSPHRASEonly applied tosrt-direct. The public guest ports (8890/8891) accepted any caller, so anyone who could reach the port could publish into program. This was the top item in the recent security review.What changes
tools/guest_av_listen.sh(A/V fan-out, owns the public port): whenMXL_GUEST_SRT_PASSPHRASEis set, it addspassphrase=to the publicsrtsrclistener as its own argv word, never spliced into the URI. The value is checked before anything binds, and a bad value exits 2, so the listener never falls back to open. When the variable is unset, the script prints a loud OPEN warning. The two127.0.0.1legs stay unencrypted (loopback only).tools/adapters.py+tools/guest_ingest.py:SrtListenerGuestAdaptertakes an optionalpassphrase. Without one, the launch string is byte-identical, so the golden parity tests are unchanged.guest_ingest.pyreadsMXL_GUEST_SRT_PASSPHRASEinsrt-listenmode. It exits on an invalid value and warns when a non-loopback listener is open. The secret never goes into flow metadata or logs.scripts/quickstart.sh: in listen mode, each slot's passphrase is checked (per-slot value wins over the shared one). Each slot's passphrase reaches its fan-out container through env inheritance (-e NAMEwith no value), so it stays out of the docker command line. Startup and the final banner list which slots require a passphrase and warn loudly about any open ones, including a partly open setup. The old "passphrase is ignored in srt-listen mode" message is gone.A-Z a-z 0-9 . _ ~ -(URL-unreserved). Wider sets broke in practice: ffmpeg URL-decodes%,+and others insrt://…&passphrase=, so the caller ends up with a different key than the one configured.openssl rand -hex 16is the suggested generator.docs/TESTERS.md: new "Lock the guest slots" section.Tests
tests/test_srt_listen_passphrase.py(41 cases): adapter fragment with and without a passphrase, back half unchanged, invalid values rejected.guest_ingest.pyapplies the passphrase, warns when unset, and fails closed. The fan-out runs against a stubgst-launch-1.0: argv placement is checked, the loopback legs stay plain, invalid values exit before anything listens, and output with no passphrase is unchanged. Quickstart listen-mode validation and reporting are covered, plus static checks that the fan-out gets the secret only through env and the legs never get it.guest_av_listen.sh:UNSECURE).BADSECRET).Deploy / compatibility
+,%…) now stops the quickstart instead of being silently ignored.quickstart.shis re-run (the guest image tag is content-hashed, so it rebuilds).Known limits / follow-ups
&passphrase=in OBS/ffmpeg).ps) and indocker inspectenv on the host. That is fine for the single-tenant VM model; worth noting in SECURITY.md.guest_audio.pyin listen mode only ever binds loopback behind the fan-out, so it was left alone.SECURITY.md,docs/QUICKSTART.mdanddocs/CONFIG.mdneeds a small update. Those files were left out of this PR to avoid conflicts with the open PRs that touch them.Conflict risk
The
tools/adapters.pychange is small and additive (SrtListenerGuestAdapter+ one helper near the top).git merge-treeagainst the open NMOS/timing PR, the adopter quick-fix PR and the Apache-2.0 PR is clean for all three.contribution_core.pyis not touched.Draft: needs a maintainer decision on merge order. Not tested on the live deployment.