Skip to content

Latest commit

 

History

History
240 lines (169 loc) · 9.57 KB

File metadata and controls

240 lines (169 loc) · 9.57 KB
id howto-debug-bundle
type how-to
status current
tags
how-to
diagnostics
debug
cloudflare
pcap

Debug bundle workflow

Overview

Two complementary tools work together to diagnose stream failures:

  1. iptv-tunerr debug-bundle — collects Tunerr-side state (recent stream attempts, provider profile, CF learned state, cookie metadata, env vars) into a directory or tarball.
  2. scripts/analyze-bundle.py — ingests that directory (plus optionally PMS.log, Tunerr stdout log, and a pcap capture) and produces a ranked findings report.

Together they turn "I don't know why this channel fails" into "here are the top 3 findings with evidence."


iptv-tunerr debug-bundle

What it collects

File Source Description
stream-attempts.json Live server /debug/stream-attempts.json Last 500 stream attempts: channel, UA used, HTTP status, CF block flag, bytes
provider-profile.json Live server /provider/profile.json Provider autopilot state: learned tuner cap, CF block hits, penalized hosts, HLS instability
cf-learned.json IPTV_TUNERR_CF_LEARNED_FILE or beside jar Per-host: working UA found by cycling, CF-tagged flag, timestamp
cookie-meta.json IPTV_TUNERR_COOKIE_JAR_FILE Cookie names, domains, expiry — no cookie values (safe to share)
env.json Process environment All IPTV_TUNERR_* vars, secrets (_PASS, _TOKEN, _KEY, _USER) redacted
bundle-info.json Generated Timestamp, version, collection summary

Basic usage

# Collect from running server (default: http://localhost:5004)
iptv-tunerr debug-bundle

# Custom server URL and output directory
iptv-tunerr debug-bundle -url http://mytuner:5004 -out ./debug-scratch

# Also create a shareable .tar.gz
iptv-tunerr debug-bundle -out ./debug-scratch --tar

# Offline only (no live server — just local state files)
iptv-tunerr debug-bundle -out ./debug-scratch --no-server

Flags reference

Flag Default Description
-url http://localhost:5004 Base URL of running Tunerr server
-out debug-scratch/ Output directory (created if needed)
--tar false Also write tunerr-debug-TIMESTAMP.tar.gz
--redact true Redact _PASS/_TOKEN/_KEY/_USER from env vars
--no-server false Skip live server fetch; only collect local state files

Notes

  • cookie-meta.json contains only cookie names, domains, paths, and expiry timestamps — never the cookie values. Safe to include in bug reports.
  • Secrets are redacted from env.json by default. If you need the full env for debugging your own setup locally, use --redact=false (but do not share the result).
  • The debug-scratch/ default output directory is also the default input for analyze-bundle.py, so the two tools work together without extra flag-passing.

scripts/analyze-bundle.py

What it does

Auto-detects log files in a directory, parses them, normalizes timestamps to UTC, and runs a pattern-matching finding engine. Output is a ranked report of what went wrong.

Prerequisites

  • Python 3.8+
  • tshark (from Wireshark) — only required if you have a .pcap or .pcapng file to analyze. Install with apt install tshark or brew install wireshark. Optional: the script works without it for the other sources.

Inputs (auto-detected from directory)

File type Detection What's extracted
Tunerr JSONL stream attempts Content-sniffed for capsule_id/channel_id JSON fields CF blocks, HTTP statuses, UA used, bytes
Tunerr stdout log Content-sniffed for [iptv-tunerr] prefix Gateway events, CF bootstrap events, UA cycling results
Plex Media Server log Content-sniffed for Plex Media Server header or plex.tv in content DVR tune/stop events, /stream/ HTTP calls
pcap capture .pcap/.pcapng extension On-wire HTTP requests (UA), HTTP response status, JA3 TLS fingerprints
cf-learned.json Filename match Per-host CF state
cookie-meta.json or cookie jar JSON Filename/content match cf_clearance presence, expiry

Basic usage

# Analyze everything in ./debug-scratch/
python3 scripts/analyze-bundle.py ./debug-scratch/

# Save report to file
python3 scripts/analyze-bundle.py ./debug-scratch/ --output report.txt

# Machine-readable JSON output
python3 scripts/analyze-bundle.py ./debug-scratch/ --json

# Override specific file paths (auto-detection still runs for the rest)
python3 scripts/analyze-bundle.py ./debug-scratch/ \
  --pms /var/log/plex/Plex\ Media\ Server.log \
  --pcap /tmp/capture.pcap

Findings the script detects

Finding What it means
CF_BLOCK_UNRESOLVED CF block seen in stream attempts, no working UA in cf-learned.json
CF_BLOCK_RESOLVED CF block seen but UA cycling found a working UA (informational — it worked)
CF_HOST_NO_WORKING_UA Host is CF-tagged in cf-learned.json but no working UA is stored
CF_CLEARANCE_EXPIRED cf_clearance cookie in jar has passed its expiry time
UA_MISMATCH_PCAP On-wire UA from pcap differs from Tunerr log — suggests proxy/MITM rewriting headers
TLS_FINGERPRINT_GO_STDLIB Go stdlib JA3 fingerprint detected in pcap — CF may still score bot even with correct UA
PLEX_TUNE_NO_TUNERR_RECV Plex log shows a tune request but Tunerr log shows no corresponding stream start
PLEX_STOP_NO_TUNERR_STREAM Plex log shows session stop with no prior Tunerr stream events for that channel
STREAM_FAILURES High failure rate in stream attempts for a specific channel or host

Report sections

  1. Sources detected — what files were found and parsed
  2. Findings — ranked by severity (error > warning > info), each with confidence score and evidence events
  3. pcap notes — JA3 fingerprints seen, known Go stdlib fingerprint detection
  4. CF learned state — per-host: CF-tagged, cf_clearance present/TTL, working UA
  5. Cookie jar metadata — which cookies are present, their expiry
  6. Event timeline — last 60 events across all sources, normalized to UTC

Exit codes

  • 0 — no error-severity findings
  • 1 — one or more error-severity findings found (useful for CI/scripted analysis)

Full capture workflow (the RKDavies method)

This is the recommended workflow when you have a reproducible stream failure and want to get the most complete diagnosis.

Step 1 — Start capturing

Before reproducing the failure:

# Collect Tunerr state (run this while Tunerr is running)
iptv-tunerr debug-bundle --out ./debug-scratch

# If you have tcpdump available, capture on-wire traffic
# (capture on the interface Tunerr uses for outbound provider requests)
tcpdump -i eth0 -w ./debug-scratch/capture.pcap &

Step 2 — Reproduce the failure

In Plex, try to play the failing channel. Let it fail, or play for ~30 seconds.

Step 3 — Collect the rest

# Stop tcpdump
kill %1

# Copy Plex log (adjust path for your platform)
cp /var/lib/plexmediaserver/Library/Application\ Support/Plex\ Media\ Server/Logs/Plex\ Media\ Server.log \
   ./debug-scratch/Plex\ Media\ Server.log

# Copy Tunerr stdout log if you are redirecting it
cp /var/log/iptvtunerr/tunerr.log ./debug-scratch/tunerr.log
# or use journalctl:
journalctl -u iptvtunerr --since "5 minutes ago" > ./debug-scratch/tunerr.log

Step 4 — Analyze

python3 scripts/analyze-bundle.py ./debug-scratch/ --output report.txt
cat report.txt

Step 5 — Share (if filing a bug report)

iptv-tunerr debug-bundle --out ./debug-scratch --tar
# Share: tunerr-debug-TIMESTAMP.tar.gz + report.txt
# The tarball does NOT contain pcap (too large) or PMS.log (potentially private)
# Attach those separately only if asked

Common diagnosis patterns

"CF blocks on every stream"

Finding: CF_BLOCK_UNRESOLVED (error, confidence: 0.95)
Evidence: 5 stream attempts → HTTP 403/503, cf_block=true
cf-learned.json: host is cf_tagged, working_ua=""

Action: Run iptv-tunerr cf-status to confirm no learned UA. If cycling failed, try manual cookie import. See cloudflare-bypass.md.

"TLS fingerprint Go stdlib detected"

Finding: TLS_FINGERPRINT_GO_STDLIB (warning, confidence: 0.8)
JA3 in pcap: 771,49195-49199-...  (known Go stdlib pattern)

This means CF might score your requests as a bot even if the UA is correct. The only current workaround is importing a browser's cf_clearance cookie. TLS fingerprint spoofing (utls) is a future work item.

"Plex tunes but Tunerr never receives the request"

Finding: PLEX_TUNE_NO_TUNERR_RECV (warning, confidence: 0.7)
Plex log: DVR tune at 2026-03-19T14:32:01Z channel 105
Tunerr log: no /stream/ request in ±30s window

Suggests the tuner URL Plex is using is stale or wrong. Check IPTV_TUNERR_BASE_URL and whether Plex's registered tuner points at the right host:port.

"UA mismatch between log and pcap"

Finding: UA_MISMATCH_PCAP (error, confidence: 0.85)
Tunerr log: user_agent="Mozilla/5.0 (Firefox)"
On-wire pcap: User-Agent: IptvTunerr/1.0

Something between Tunerr and the provider is rewriting the User-Agent. Check for transparent proxies, nginx reverse proxies, or Docker networking that might strip headers.


See also