Diablo_Rain 0b761f684b harden: relay timeouts, DNS resolver reuse, cache hygiene + frontend polish
Server (relay/SSRF):
- Bound connect+TLS+request under CONNECT_TIMEOUT and body download under
  BODY_TIMEOUT so a stalling upstream can't pin a relay permit indefinitely
- Add inbound header_read_timeout to defeat slow-loris connections
- Allowlist relayed Content-Type (fall back to octet-stream) to block
  content-confusion from attacker-controlled stream origins
- Reuse one DNS resolver process-wide instead of rebuilding it per request
  (restores hickory's DNS cache; drops per-segment resolver setup)
- Probe cache: random per-process hash seed (DefaultHasher was deterministic)
  + bounded growth with expired-entry eviction
- Real Ctrl-C handler for a clean shutdown (honours the banner)
- Collapse the wrap_raw no-op alias into wrap

Frontend:
- Guide: visible focus ring tracking arrow-key navigation
- Player: buffering/tuning indicator while <video> is stalled
- prefers-contrast: more pass (lifts --ink-dim to meet WCAG AA)
- Service worker: date-stamped cache names so shell updates propagate

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 14:20:06 -04:00

🔮 The Pondering Orb

A retro CRT-themed web TV. Channel-surf live streams through a security-hardened, same-origin relay.

A reformed mad-wizard gazes into a scrying orb and flips channels like it's 1994 — but every upstream is treated as hostile.

Stack Relay Security License


What it is

The Pondering Orb turns any HLS source into a 1994 cable-TV experience in the browser: a red/black phosphor CRT frame, a scrolling TV guide, channel zapping with a 7-segment OSD, and YouTube-style theater / dim / ambient-glow modes.

It is built around one idea: a channel is "a named thing on a guide that resolves to an HLS stream at a point in time." Public live streams (via iptv-org) and — later — your own self-hosted media library are just different providers feeding the same UI. No rewrite required to add the second.

"Purple team" here is a security identity (red offense + blue defense), not a color. The palette stays red/black; the wizard theme is naming and lore on top of clear, accessible function.

It is developed as a parallel build to a peer project that takes the same premise — your media as 24/7 TV channels — through a different architecture (a NAS + ErsatzTV + Raspberry Pi feeding a physical CRT). This implementation is portable, browser-based, and security-first.

Features

  • Authentic CRT presentation — phosphor glow, scanlines, screen curvature, vignette breathing (all CSS, no WebGL).
  • Cable-box channel zapping — number entry with debounce + 7-segment OSD, channel up/down, last-channel toggle, auto-fading now-playing banner.
  • "Scrying Static" transitions — procedural channel-change noise that clears the moment the new stream buffers (reduced-motion aware).
  • The Almanac — a virtualized, 1994-style scrolling TV guide with now/next, a live current-time playhead, and keyboard navigation. Scales to tens of thousands of channels.
  • Immersion stack — Theater, Dim, and Ambient-backlight modes (à la YouTube), composable and keyboard-driven.
  • Graceful dead-stream handling — "the orb clouds over" no-signal card, automatic fallback URLs, and auto-skip.
  • The Lexicon — optional in-world vocabulary (guide → The Almanac, search → Scry) with a one-click "mundane mode"; screen-reader labels always stay plain-English.
  • Accessible by default — full keyboard map + help overlay, ARIA roles/live regions, visible focus rings, and a complete prefers-reduced-motion kill-switch.

Security posture

Every stream URL comes from a public, third-party, mutable playlist — so the Orb treats all of it as hostile input. The browser only ever talks to its own origin; the Rust relay is the single egress point, and all SSRF risk is concentrated in one auditable module.

Control Implementation
SSRF defense Resolves DNS itself, rejects the whole host if any resolved IP is private / loopback / link-local / CGNAT / cloud-metadata (169.254.169.254) / IPv6 ULA+link-local, then connects to that exact validated IP — no re-resolve, defeating DNS-rebinding. Fail-closed.
HTTPS-only egress Non-https upstreams are refused outright.
Bounded redirects Each redirect hop is re-validated through the same SSRF gate.
Strict CSP default-src 'none'; no unsafe-inline / unsafe-eval; scripting, styling, and XHR all locked to 'self'.
Untrusted-input rendering Playlist/EPG fields are inserted as text only (never innerHTML); URL schemes allow-listed; field/length caps guard against client-side DoS.
Hardened serving Path-traversal-safe static handler, nosniff, no-referrer, X-Frame-Options: DENY, locked Permissions-Policy.
Supply chain HLS.js pinned to an exact version and Subresource-Integrity verified.
Observability /metrics (Prometheus) counts relay outcomes including SSRF blocks; structured JSON logs record host + outcome, never the raw URL (query strings can carry stream tokens).

Verified

The current build passes its full probe battery: all SSRF vectors rejected (403/400), CSP headers present with no unsafe-*, path traversal blocked, a real Apple HLS manifest fetched and its nested URLs rewritten through the relay, and the live iptv-org catalog (~39k channels) retrieved end-to-end through the hardened path. Rust unit tests and JS syntax checks are green with zero build warnings.

Quick start

Full experience (serves the SPA and the relay from one origin):

cd server
cargo run --release
# → http://127.0.0.1:8088

Front-end only (no relay; uses the built-in mock realm and CORS-clean test streams):

cd web
python3 -m http.server 8099
# → http://127.0.0.1:8099

Keyboard

Key Action Key Action
09 Tune channel T Theater mode
↑ / ↓ Volume · guide nav D Dim mode
PgUp/PgDn Channel up / down A Ambient glow
Backspace Last channel F Fullscreen
G Toggle the Almanac ? Help

Append ?provider=mock or ?provider=iptv to force a data source.

Architecture

┌─────────────────────────────────────────────────────────────┐
│  Browser (same origin — no CORS, untainted ambient canvas)   │
│                                                              │
│   index.html ── app.js ──┬── player.js   (HLS.js, controls)  │
│                          ├── zapper.js   (tuning, OSD)       │
│                          ├── guide.js    (virtualized EPG)   │
│                          ├── ambient.js  (backlight)         │
│                          └── providers/                      │
│                              ├── source-provider.js  ◄── the │
│                              ├── mock.js              interface
│                              └── iptv-org.js                 │
└───────────────────────────────┬─────────────────────────────┘
                                 │  /  ·  /relay  ·  /metrics
┌───────────────────────────────▼─────────────────────────────┐
│  Rust server (binds 127.0.0.1)                               │
│   main.rs   static serving + security headers + observability│
│   relay.rs  HLS proxy + manifest URL rewrite + redirects     │
│   ssrf.rs   resolve → validate IP → connect (sole egress)    │
└───────────────────────────────┬─────────────────────────────┘
                                 ▼
                  Public HLS origins  ·  iptv-org JSON API

Everything in the UI talks only to the SourceProvider contract — never directly to iptv-org or any one source. MockProvider was built first to keep the UI provably source-agnostic; a future LocalMediaProvider (your own library, packaged to HLS) drops in alongside it.

Tech stack

Roadmap

Now (v1): hardened same-origin relay · iptv-org provider · zapping · virtualized guide · theater/dim/ambient · dead-stream handling · observability.

Next: stream health prober + scoring · session resurrection · off-thread XMLTV parsing · service-worker PWA.

Later: The Scryer's Lens (live stream trust/provenance overlay) · The Chronicle (channel-lineup-as-code with diff/audit) · Cursed Channels (adversarial test harness that proves the defenses) · The Wizard's Workbench (compose your own channels; export as a signed "Spellbook") · LocalMediaProvider for self-hosted media.

Project structure

web/                    Static SPA
  index.html            CRT shell + markup
  styles.css            Red/black CRT theme (all effects, responsive, a11y)
  app.js                Bootstrap, global state, keyboard map, modes
  player.js             HLS.js wiring, ghost controls, dead-stream handling
  zapper.js             Channel tuning, OSD, scrying-static transition
  guide.js              Virtualized EPG overlay
  ambient.js            Ambient backlight canvas
  lexicon.js            In-world vocabulary + mundane-mode
  providers/            SourceProvider contract + Mock + iptv-org
  lib/                  Pinned, SRI-verified HLS.js
server/                 Rust same-origin server + hardened relay
  src/{main,relay,ssrf}.rs

Disclaimer

This project does not host, store, or transmit any media. It indexes publicly available stream URLs aggregated by the iptv-org project. You are solely responsible for ensuring any stream you access is licensed and lawful in your jurisdiction.

Acknowledgments

  • Developed as a parallel exploration alongside a peer's NAS-to-CRT "media as 24/7 channels" project.
  • Channel data and the public stream index come from the iptv-org community project.

License

MIT — code only. Channel data and streams are the property of their respective owners.

S
Description
Streaming IPTV excersise, rust server. My contribution and brain exercises in streaming security. Go see Ring's it's cooler.
Readme 384 KiB
Languages
JavaScript 53.8%
Rust 30.1%
CSS 10.9%
HTML 5.2%