MediaMTX 開 Port 風險與 VPN 收斂架構指南
本指南專注於推流伺服器端的網絡邊界防禦:如何科學評估 MediaMTX 開放公網 Port 的潛在威脅、如何透過 VPN 收斂架構完全下架裸露的 RTMP/SRT 端口,並引入動態 IP 白名單 Hot Reload 機制。
1. 現況架構與網絡拓撲
目前系統對公網曝露的端口分佈如下:
| Port | 網路協定 | 實際用途 |
|---|---|---|
443 |
Xray VLESS Reality | 供中國大陸現場跨越 GFW 使用的代理出口(保持獨立) |
1935 |
RTMP (明碼) | 台灣現場戶外推流 → 曝露於公網的 MediaMTX Ingest 入口 |
8890 |
SRT (特徵明顯) | 備用高丟包現場推流 → 曝露於公網的 MediaMTX Ingest 入口 |
鏈路一:台灣戶外直接推流鏈(本次安全重構核心)
flowchart TD A["手機 PrismLive / Moblin"] -->|未收斂拓撲| E["MediaMTX 公網直接曝露
公網 IP:1935/8890
暴露主要攻擊面"] E --> F["OBS 本機拉流"]
鏈路二:中國大陸現場科學上網鏈(完全獨立,不經過 MediaMTX)
flowchart LR
A["中國現場 iPhone"] --> B["Shadowrocket VLESS Reality"]
B --> C["伺服器 Xray:443 出口"]
C --> D["跨境直推 Twitch 伺服器"]
常見誤解釐清:兩條推流鏈是否有交集?
| 鏈路一(台灣戶外) | 鏈路二(中國大陸現場) | |
|---|---|---|
| 推流來源 | 台灣手機 | 中國大陸現場 iPhone |
| 推流目的地 | 本機 MediaMTX | Twitch(直接) |
| 經過 MediaMTX | ✅ 是 | ❌ 否 |
| 翻牆工具 | WireGuard(台灣境內不需翻牆) | Shadowrocket + VLESS+Reality |
| 主要安全風險 | 1935/8890 port 暴露 | Xray 被 GFW 識別或封鎖 |
| 本頁涵蓋範圍 | ✅ 是 | ❌ 否(見 VPN 代理指南) |
2. MediaMTX 面臨的安全問題
在安全威脅建模中,網絡邊界防禦遵循「三階段風險模型」。必須正視的是:開放公網端口必然引發探測,隱蔽不等於安全。
核心概念:VPN 收斂架構的核心價值在於降低「攻擊面(Attack Surface)」,將對外的曝露點從多個服務端口收攏至單一高強度加密通道,而非直接提高 MediaMTX 內部應用程式本身的代碼安全性。
| 曝露端口 | 階段 1 背景掃描 | 階段 2 協議識別 | 階段 3 攻擊面風險評估 |
|---|---|---|---|
443 Reality |
必然命中 | 極難看穿 (偽裝真實 TLS 1.3) | 低風險,具備探測防禦 |
1935 RTMP |
必然命中 | 秒級識別 (無任何偽裝機制) | 高風險,易遭突發串流覆蓋與拒絕服務 |
8890 SRT |
必然命中 | 秒級識別 (握手特徵固定) | 高風險,未授權探測與頻寬消耗 |
用詞嚴謹性補充:Reality 的「極難看穿」指的是它的設計目標為顯著提高主動探測與協議識別的難度,並非保證絕對不可識別——沒有任何協定能做這種保證。同理,「必然命中」指的是掃描發現只是時間問題,並非每次掃描都會立即命中。
3. MediaMTX 加密現況檢查
檢查伺服器部署的 mediamtx.yml 核心傳輸層配置:
rtmpEncryption: "no" # RTMP 明文傳輸
rtspEncryption: "no" # RTSP 明文傳輸
srtReadPassphrase: # 未配置文件加密密鑰
srtPublishPassphrase: # 未配置文件加密密鑰
hlsEncryption: false # HLS 切片未啟用靜態加密
釐清一個容易誤解的地方:「沒加密」不代表這些協議完全沒有封包格式。SRT
本身一直都有自己的傳輸層機制(ARQ 重傳、FEC
前向糾錯、封包序號等),這些不受上述設定影響,一直都在運作;沒設
passphrase 代表的是沒啟用它內建的 AES Payload
Encryption,也就是媒體「內容」沒加密,跟傳輸層機制無關。RTMP
同樣有自己完整的協定框架(chunk、message 格式等),只是沒有走
TLS(RTMPS),所以內容以明碼傳輸。
4. MediaMTX 認證漏洞缺陷
原配置檔案中關於發布端權限的宣告存在極大安全隱患:
authInternalUsers:
- user: any
pass:
ips: []
permissions:
- action: publish
path: live/key1
5. 方案 A:VPN 收斂架構(攻擊面最小化)
為了阻止全球自動化掃描器對 1935 與 8890 端口的常態探測,最有效的手段是在邊界路由器與防火牆上完全關閉這些端口的公網對外映射。
%%{init: {"themeVariables": {}}}%%
flowchart LR
A["手機直播端"] -->|WireGuard UDP 隧道| B["VPN Gateway"]
B -->|虛擬內網網卡 10.0.0.1| C["MediaMTX:1935/8890"]
封包解裝流程解析:VPN Server 作為隧道終點,會解封裝 VPN 封包,因此能看到其中承載的是 RTMP/SRT 流量。對於 Internet 公網上的第三方探測器而言,僅能捕獲符合密碼學隨機分佈的 UDP 封包,從根本上抹除了直播服務的特徵指紋。
6. Hysteria2 vs WireGuard 選型
當 VPN 收斂架構應用於現場推流場景時,其選型邏輯與常規科學上網迥異:
🛡️ 台灣本地固定網絡環境 → 首選 WireGuard
- 核心優勢:協議極度輕量、封裝開銷極低、核心態運行。
- 手機端生態:官方客戶端極其成熟,支援 Split Tunnel 路由分流。
⚡ 飯店/會場 Wi-Fi 等高阻礙環境 → 備選 Hysteria2
- 核心優勢:基於 QUIC,Brutal 壅塞控制演算法對抗戶外弱網高丟包。
- 網絡伪裝:模擬標準 HTTP/3 流量,輕易穿透企業級防火牆對 UDP 的惡意限制。
7. 方案 B:動態 IP 白名單工具
若現場環境不便安裝 VPN 客戶端,則必須開啟公網端口,此時必須依賴動態白名單工具進行最小範圍的曝露控制。
該工具基於 Node.js 運行,透過精準文字標記(Marker)動態定位並更新
mediamtx.yml 內的 ips 授權池,觸發
MediaMTX 的 Hot Reload(熱加載) 機制。
# mediamtx.yml 內的動態標記範例
authInternalUsers:
- user: liveu_streamer
pass: $2b$10$BvR... (bcrypt雜湊)
ips: ["220.135.x.x"] # @dynamic-ip-pool: production-field
permissions:
- action: publish
8. 方案比較:VPN 收斂 vs IP 白名單自動化
| 面向 | 方案 A:VPN 收斂(第 5 節) | 方案 B:IP 白名單自動化(第 7 節) |
|---|---|---|
| 1935/8890 對外可見性 | 完全下架,掃描器連 handshake 都進不去 | 仍然開放,仍會被掃描發現(階段 1 無法避免) |
| RTMP/SRT 協議是否仍「裸奔」 | 對 Internet 而言只看得到 VPN 流量,RTMP/SRT 封包只存在 VPN 隧道內部 | 是,協議本身仍無偽裝、無加密,只是有 IP 關卡擋著 |
| 用戶端設定成本 | 需安裝 VPN client 並保持連線 | 只要瀏覽器登入點一下,無需安裝額外 App |
| 架設成本 | 需架設 WireGuard/Hysteria2 server | 主要是部署 Cloudflare Tunnel |
| 動態 IP 的處理 | 不受影響(走 VPN 虛擬 IP,跟公網 IP 無關) | 需要工具主動更新,否則白名單會過期失效 |
| 適合場景 | 長期、固定授權用戶的日常使用 | 想要輕量化、用戶不想安裝 VPN、臨時開放的場景 |
是否可以兩者疊加?
可以,而且是更穩健的做法:VPN 收斂當主要防線(1935/8890 完全不對公網開放),IP 白名單工具當備援或給不方便安裝 VPN 的臨時用戶使用——如果某些場景下需要暫時開放 1935/8890 給未安裝 VPN 的用戶測試,白名單機制能把「開放範圍」限制到最小,而不是完全不設防。
9. 五層縱深防禦與最終架構
健全的系統不依賴單一防線。本架構透過多層獨立關卡構建標準的縱深防禦(Defense in Depth)體系:
graph TD
L1["【第一層:VPN 網絡邊界】
公網 1935/8890 完全關閉,未授權封包在邊界直接丟棄。"]
L2["【第二層:動態 IP 白名單】
限制僅允許信任的現場出口公網 IP 建立連接。"]
L3["【第三層:發佈端強認證】
MediaMTX 驗證強密碼,拒絕 any 匿名 publish 行為。"]
L4["【第四層:連線速率限制】
限制單一 IP 握手頻率,阻斷憑證碰撞與資源消耗。"]
L5["【第五層:自動阻斷守護】
Fail2Ban 監控日誌,連續認證失敗直接執行核心級黑名單封鎖。"]
L1 --> L2 --> L3 --> L4 --> L5
整體整合架構圖
graph TD
subgraph TW_Field ["════════ 台灣現場戶外 ════════"]
Client["手機 / 攝像機推流端"] -->|僅允許打虛擬內網 IP 10.0.0.1| WG["[第一層: WireGuard 加密隧道]"]
end
subgraph Cloud_Boundary ["════════ 雲端防禦邊界 ════════"]
WG -->|解封裝 VPN 流量| IPTables["[第二層: iptables 網絡層動態白名單過濾池]"]
end
subgraph MMTX_Defense ["════════ MediaMTX 縱深防禦體系 (第三至五層) ════════"]
MMTX["MediaMTX 核心五層縱深"]
B1["- 監聽綁定: 10.0.0.1 (公網對外不可見)"]
B2["- 發佈控制: authInternalUsers 密碼校驗"]
B3["- 守護進程: Fail2Ban 實時日誌審查"]
MMTX --> B1 --> B2 --> B3
end
OBS["OBS Studio 控制台"]
IPTables --> MMTX
B3 -->|內網迴圈拉流| OBS
Platforms["Twitch / YouTube 平台"]
OBS -->|安全轉發| Platforms
10. 邊界安全檢查清單
MediaMTX 認證(立即處理)
-
檢查
mediamtx.yml,確認user: any佔位符已徹底移除。 -
確認
srtPublishPassphrase/srtReadPassphrase已填上密碼,啟用 AES Payload Encryption。 - 確認 SRT 與 RTMP 發布密碼皆使用複雜的純英數字組合,避免特殊字符引發設備解析異常。
- 評估是否加裝 fail2ban 或連線速率限制。
VPN 收斂架構(方案 A)
- 架設 WireGuard server(固定網路日常推流用)。
-
WireGuard 設定 split
tunnel,
AllowedIPs只涵蓋 MediaMTX 網段。 - MediaMTX 監聽介面 bind 到 VPN 虛擬網卡 IP;若在 Windows 上遇到開機綁定失敗,改用防火牆規則限制來源網段。
- 推流 App 網址改成 VPN 內網 IP(不是公網 IP/DDNS)。
- 確認新 WireGuard port 跟既有 Hysteria2(若也用 UDP 443)沒有 port 衝突。
- Router 上把 1935、8890 的 port forward 規則移除。
- 保留現有 Hysteria2 server 一組 client 設定,作為戶外/不可控網路的備援。
-
確認常駐守護進程已正確配置
Restart=always,防止極端網絡衝擊導致邊界服務崩潰。
IP 白名單自動更新工具(方案 B)
-
mediamtx.yml對應行加上# @dynamic-ip-pool: 名稱標記。 -
MEDIAMTX_YML_PATH環境變數指向正確路徑。 -
用
add-user.js建立帳號,確認密碼有 bcrypt 雜湊存進users.json。 -
server-ecdh-keys.json絕對不要加進任何 git repo 或雲端備份。 -
服務只監聽
127.0.0.1,沒有直接 port forward。 - 透過 Cloudflare Tunnel 對外開放,確認前後端在同一個 Express app。
- 若日後把 cloudflared 跟 Node.js 拆到不同主機,記得補上 HTTPS。
- 確認登入速率限制生效(15 分鐘內最多 8 次)。
長期維護
- 定期檢查 MediaMTX、Xray、WireGuard、Node.js 依賴套件的版本更新。
- 不用的服務/port forward 規則養成隨手關閉的習慣,避免遺忘造成意外曝露。
- 改設定檔後若沒生效,先確認是否屬於 MediaMTX 不支援 hot reload 的少數欄位,而非程式邏輯錯誤。