feat(stream): authenticate /stream and /hls with signed tokens
/stream and /hls were served with no auth (only CORS + rate limit), so a funnel- or UPnP-exposed daemon leaked active downloads to anyone with the URL. Bind a short-lived HMAC token (scope + 6h expiry) to every stream URL the daemon hands out and verify it on each request: - /stream + VLC playlist: ?t= query, agent-minted, scope "stream" - /hls: path segment /hls/<session>/<token>/<resource>, web-minted with the agent's reported secret, scope "hls:<session>" — relative playlist URIs inherit it with no rewriting - NO loopback exemption: cloudflared relays public funnel traffic over localhost, so a loopback source address is not a trust signal - the agent reports its per-run signing key on register only when enforcing - require_stream_token config (default true); secret fails hard if rand fails - /playlist.m3u no longer self-mints a token (was an open token oracle) Roadmap: Docs/plans/unarr-agent-roadmap.md (hueco #1). Deploy the web HLS-minting change BEFORE shipping this agent release.
This commit is contained in:
parent
ea00130d08
commit
444d7e63fd
8 changed files with 622 additions and 36 deletions
|
|
@ -310,6 +310,14 @@ func runDaemonStart() error {
|
|||
// Create persistent stream server
|
||||
streamSrv := engine.NewStreamServer(cfg.Download.StreamPort)
|
||||
streamSrv.SetUPnPEnabled(cfg.Download.EnableUPnP)
|
||||
streamSrv.SetRequireStreamToken(cfg.Download.RequireStreamToken)
|
||||
// Report the stream-token signing key ONLY when enforcing, so the web's
|
||||
// "secret present → mint HLS token" signal accurately means "this agent
|
||||
// verifies tokens". Reporting it with enforcement off would make the web
|
||||
// mint HLS path tokens the agent never peels → 404. Set before Register().
|
||||
if cfg.Download.RequireStreamToken {
|
||||
d.UpdateStreamSecret(streamSrv.StreamSecretHex())
|
||||
}
|
||||
// CORS extras = operator config + dynamic mirror list from /api/mirrors.
|
||||
// Without the mirror merge, a user playing from `torrentclaw.to` (or any
|
||||
// future mirror) hits the daemon, gets 200 + body, but no
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue