mysamimi/rtmp-http-tunnel

GitHub: mysamimi/rtmp-http-tunnel

该工具通过将本地 RTMP 流拆分为混淆的 HLS 分段并经 HTTPS 并发上传至远程服务器进行缓冲重构,来解决受限网络下直播推流遭遇限速、丢包和封锁的问题。

Stars: 0 | Forks: 0

# rtmp-http-tunnel `rtmp-http-tunnel` 是一个使用 Go 语言编写的轻量级、高弹性的开源流媒体中继工具。它旨在绕过在向 YouTube、Twitch 或 Aparat 等平台进行直播推流时遇到的网络限速、深度包检测 (DPI) 以及高抖动网络环境(例如受限的网络连接)。 ## 问题所在 标准的 RTMP 推流通过单一且持久的 TCP 连接(通常是 1935 端口)进行。在不稳定或受到严格审查的网络中,这种单一连接很容易被限速、遭受丢包(导致推流断开)或完全被防火墙阻止。此外,网络绑定(结合多个 WAN 连接)也无法轻易地动态分发单一的原始 RTMP 流。 ## 解决方案 `rtmp-http-tunnel` 通过将您的本地 RTMP 流拆分为小型的、经过混淆的 HLS 分段(通常每个 2 秒),并使用工作池通过安全的 HTTPS(443 端口)并发上传它们,从而解决了这个问题。 远程服务器对这些分段进行缓冲(例如 60 秒)以吸收丢包和网络抖动,然后按顺序重构它们,最后通过管道将其作为连续的 RTMP 流重新导向 YouTube/Twitch。 ``` +----------+ +-------------------------+ +-------------------------+ +-----------------+ | OBS / | RTMP | Local Client | HTTPS | Remote Server | RTMP | YouTube/Twitch | | Encoder | -------> | (RTMP Ingest -> Chunks) | =======> | (Jitter Buffer -> RTMP) | -------> | Ingest Server | +----------+ (Port +-------------------------+ POSTs +-------------------------+ (Port +-----------------+ 1935) (Port 1935) 443) ``` ## 功能 - **多流支持(多客户端与多服务器):** 通过将多个独立的流路由到动态路径 endpoint(例如 `/s/stream_abc/upload`),可以在同一服务器端口上同时进行中继。 - **智能过期策略:** 客户端会查询服务器的 `/health` endpoint 以动态发现缓冲持续时间配置。如果本地分块超过了服务器窗口期,客户端会在本地将其丢弃(并避免上传),从而节省带宽。 - **后台非活跃会话清理:** 服务器运行一个后台例程,安全地终止非活跃的流媒体会话进程,释放端口、docker 容器,并清理临时磁盘资产。 - **Docker 化的 FFmpeg 集成:** 在轻量级容器内运行视频处理。如果 Docker 可用,则无需在客户端或服务器上安装和配置本地 FFmpeg 构建版本。 - **并发分块上传:** 利用工作池并行上传分段,自然地利用多连接负载均衡器或软件网络绑定。 - **防 DPI 的 XOR 混淆:** 在应用层使用简单密钥对分块字节进行加扰,以绕过针对视频头的深度包检测 (DPI)。 - **MPEG-TS 完整性验证:** 在抵达时自动验证解密的数据包,如果存在 `obfuscation_key` 不匹配的情况,会立即向您发出警告。 - **抗弹性抖动缓冲:** 在将分块馈送至接收平台之前,服务器会缓冲一个可配置的滑动窗口(例如 60 秒),能够吸收长达 60 秒的完全客户端断开连接,且不会中断目标推流。 - **优雅关闭:** 实现了适当的 OS 信号捕获。通过 `Ctrl+C` 关闭客户端或服务器会立即停止子进程,关闭 HTTP 监听器,释放端口,并干净地终止 Docker 容器。 ## 环境要求 - **Go**(1.20 或更高版本) - **选项 A(推荐):** 在客户端和服务器机器上均运行 **Docker**(应用程序将自动管理 `linuxserver/ffmpeg` 容器)。 - **选项 B(原生):** 在两台机器上均已安装 **FFmpeg** 并添加到 PATH 中。注意:在客户端,您的 FFmpeg 构建版本必须支持 RTMP 监听(`-listen 1`)。启用了 `librtmp` 的 FFmpeg 构建可能无法监听;建议使用标准的 Homebrew 或 Linux 软件包管理器构建版本。 ## 配置 将 `config.json.example` 复制为 `config.json` 并调整参数: ``` { "mode": "client", "client": { "server_url": "https://your-server-ip:8443", "auth_token": "a-strong-random-shared-secret-token", "obfuscation_key": "some-secret-xor-obfuscation-key", "concurrency": 4, "chunk_duration": 2, "use_docker": true, "docker_image": "linuxserver/ffmpeg", "max_upload_retries": 5, "streams": [ { "stream_path": "stream_abc123", "input_url": "rtmp://0.0.0.0:1935", "temp_dir": "./tmp_client/stream_abc123" }, { "stream_path": "stream_xyz456", "input_url": "srt://0.0.0.0:9000", "temp_dir": "./tmp_client/stream_xyz456" } ] }, "server": { "listen_addr": ":8443", "auth_token": "a-strong-random-shared-secret-token", "obfuscation_key": "some-secret-xor-obfuscation-key", "buffer_duration": 60, "rebuffer_duration": 4, "chunk_duration": 2, "inactive_session_timeout": 120, "tls_cert_file": "/etc/letsencrypt/live/your-server-ip/fullchain.pem", "tls_key_file": "/etc/letsencrypt/live/your-server-ip/privkey.pem", "use_docker": true, "docker_image": "linuxserver/ffmpeg", "streams": [ { "path": "stream_abc123", "target_rtmp_url": "rtmp://a.rtmp.youtube.com/live2/key-for-stream-1", "temp_dir": "./tmp_server/stream_abc123" }, { "path": "stream_xyz456", "target_rtmp_url": "rtmp://a.rtmp.youtube.com/live2/key-for-stream-2", "temp_dir": "./tmp_server/stream_xyz456" } ] } } ``` ### 关键参数: - `"concurrency"`:每个客户端流的并发 HTTP 上传工作线程数。 - `"max_upload_retries"`:客户端在跳过/丢弃某个分块前尝试上传的次数。 - `"inactive_session_timeout"`:服务器端非活动超时时间(秒)。如果在此持续时间内未收到某个流的上传分块,服务器将终止其流媒体进程并进行清理。 - `"auth_token"`:必需的共享 bearer token。客户端和服务器端的值必须匹配。 - `"obfuscation_key"`:必需的共享 XOR 密钥。客户端和服务器端的值必须匹配。 - `"buffer_duration"` 和 `"chunk_duration"`:在服务器上,`buffer_duration` 必须大于 `chunk_duration`;否则服务器将拒绝启动。 - `"rebuffer_duration"`:在流已经启动一次后的可选快速恢复缓冲区。省略时默认约为两个分块。将其设置为较小的值(如 `4`)可以在客户端重启后快速恢复,同时保持较大的初始 `buffer_duration`。 - `"streams"`(客户端):本地流处理 pipeline 数组,定义: - `"stream_path"`:服务器路由标识符(`/s/{stream_path}/upload`)。 - `"input_url"`:通用输入 URL。支持的格式: - RTMP(监听器):`rtmp://0.0.0.0:1935`(零 IP 主机绑定监听器) - RTMP(拉取/连接):`rtmp://192.168.1.100:1935/live/app` - SRT(监听器):`srt://0.0.0.0:9000`(自动追加 `?mode=listener`) - SRT(呼叫者/拉取):`srt://192.168.1.100:9000`(自动追加 `?mode=caller`) - UDP(监听器):`udp://0.0.0.0:1234`(自动追加 `?listen`) - UDP(多播拉取):`udp://239.1.1.1:1234` - HTTP/HLS:`http://example.com/stream.m3u8` - `"temp_dir"`:本地化分块资产的路径。 - `"streams"`(服务器):静态注册路径定义的数组。 - `"path"`:预期的 URL 路由标识符。 - `"target_rtmp_url"`:出站 RTMP 接收服务器(例如 YouTube RTMP URL + 密钥)。 - `"temp_dir"`:本地化服务器缓冲分块的路径。 ### 启动验证 应用程序需要有效的配置文件。如果 `config.json` 缺失或无效,启动将会失败,而不会回退到不安全的默认设置。 验证检查包括: - `mode` 必须是 `client` 或 `server`(或使用 `-mode` 覆盖)。 - 客户端的 `server_url` 必须是 `http` 或 `https`。 - `auth_token`、`obfuscation_key`、流路径、输入 URL、目标 URL 和临时目录必须存在。 - 流路径只能包含字母、数字、`.`、`_` 和 `-`;不允许使用斜杠,因为路径会用于 `/s/{stream_path}/...` 路由。 - 流路径在所选的客户端或服务器配置中必须唯一。 - TLS 证书和密钥路径必须成对配置。 ## 使用方法 ### 1. 运行服务器(VPS / 数据中心) 确保您的防火墙允许监听端口(例如 `8443`)上的流量。运行: ``` go run main.go -mode server -config config.json ``` ### 2. 运行客户端(本地机器) 运行客户端程序: ``` go run main.go -mode client -config config.json ``` ### 3. 开始推流 将您的编码器(例如 OBS)配置为推流到它们各自的端口。 例如,对于第一个流: - **服务器:** `rtmp://127.0.0.1:1935/live/app` - **推流密钥:** (可留空或填入任意虚拟密钥) 对于第二个流: - **服务器:** `rtmp://127.0.0.1:1936/live/app` - **推流密钥:** (可留空或填入任意虚拟密钥) OBS 开始推流后,客户端会将流进行分段、混淆,并将分块中继到 `/s/{stream_path}/upload`。服务器将它们隔离缓冲,并将重构后的流转发到匹配的 `target_rtmp_url`。 ## 安全限制 - 上传请求限制每个分块最大 50 MB。过大的分块将被拒绝并返回 HTTP `413`,以确保不会静默接受损坏/被截断的媒体。 - 客户端会丢弃对服务器缓冲窗口而言过于陈旧的分块。如果服务器健康 endpoint 无法访问,客户端将使用保守的回退窗口。 - 建议在实际部署中使用 HTTPS。目前,客户端接受自签名的 TLS 证书以简化 VPS 设置,因此请确保 `auth_token` 足够强且保密。 ## 故障排除 ### 配置缺失或无效 如果启动失败并提示 `Invalid configuration`,请修复日志中指出的字段。应用程序不会使用占位符默认值运行。 ### 解密警告 如果服务器记录了以下内容: `[Receiver] WARNING: Decrypted chunk does not start with MPEG-TS sync byte (0x47, 'G')...` 这意味着服务器无法解密传入的分块。请仔细检查客户端和服务器配置中的 `"obfuscation_key"` 是否完全一致。 ### 端口冲突 如果您收到 `port is already allocated` 或 `bind: address already in use` 错误: - 在服务器上:停止后台运行的任何现有服务器进程: killall rtmp-http-tunnel - 在客户端(Docker)上:清理任何仍然占用该端口的孤立容器: docker rm -f $(docker ps -a -q --filter name=rtmp-http-tunnel-client-)
标签:EVTX分析, Go语言, 抗丢包, 日志审计, 流媒体中继, 流量伪装, 程序破解, 网络穿透, 网络通信, 请求拦截