MediaMTX Control API 鉴权与网络路由排障技术文档

MediaMTX Control API 鉴权与网络路由排障技术文档(Linux / 服务器部署)
本文档基于一次典型的「后端写入 MediaMTX path 配置成功,但拉流失败 / API 通过 IP 访问异常」场景整理,覆盖以下内容:
如何配置 MediaMTX Control API 的账号、密码与权限(允许哪些 IP 调用 API)
如何验证 path 是否写入成功(区分“写入成功”和“拉流失败”)
如何排查路由/网段冲突(尤其是 Docker 默认网段 172.17.0.0/16 抢路由)
如何关闭 Docker 或规避冲突
常用诊断命令与现象解释
适用环境:Linux 服务器(systemd)、MediaMTX v1.15.x、SpringBoot 后端通过 API 写入 /v3/config/paths/*。
1. 背景与关键结论
- “写入成功”与“能播放”是两件事
- 写入成功:
/v3/config/paths/get/<path>能返回该 path 的完整配置;/v3/config/paths/list的 itemCount 增加。 - 能播放:MediaMTX 需要能从服务器侧访问到 source 指定的 RTSP/RTMP/HLS 等源地址。网络不可达会导致 WebRTC/HLS session 报错。
- 使用 IP 访问 API 失败(authentication error / connection refused)常见原因
MediaMTX API 只允许 localhost 免鉴权,远程访问需要明确配置权限或账号密码
端口没开放或服务没监听到指定地址(或被防火墙拒绝)
使用了错误端口(例如没写 :9997,默认走 80)
请求走了反向代理(Nginx/网关)导致鉴权规则不同
- “no route to host” 通常是路由或网段冲突
- 典型:真实设备使用 172.17.x.x,而 Docker 默认网桥 docker0 正好是 172.17.0.0/16,系统会把这段网段的流量导向 docker0,导致实际无法到达真实设备。
2. MediaMTX Control API 鉴权与权限配置
MediaMTX 在 mediamtx.yml 中通过 authMethod 和 authInternalUsers 控制鉴权与权限。
2.1 内置鉴权(authMethod: internal)
启用 internal:
authMethod: internal在 authInternalUsers 中定义用户、允许的来源 IP(ips)和权限(permissions)。
2.1.1 只允许本机访问 API(默认常见配置思路)
如果希望 API 仅允许服务器本机调用(后端与 MediaMTX 同机),可以将 API 权限只放开给 localhost:
authInternalUsers:
- user: any
pass:
ips: ['127.0.0.1', '::1']
permissions:
- action: api
- action: metrics
- action: pprof说明:
user: any 表示任意用户名(含匿名)
ips 表示允许来源 IP,只有来自这些 IP 的请求可以使用此条规则
permissions 的 action 为 api/metrics/pprof 表示可以调用对应接口
此配置适合:后端部署在同一台机器,通过 http://127.0.0.1:9997 调用 API。
2.1.2 放开指定内网 IP 访问 API
如果后端不与 MediaMTX 同机,而是通过内网 IP 调用 API,需要把后端服务器的来源 IP 加入允许列表。
例如允许来源为 172.16.214.240 的调用:
authInternalUsers:
- user: any
pass:
ips: ['127.0.0.1', '::1', '172.16.214.240']
permissions:
- action: api注意:
这里的 ips 是“请求发起方”的 IP(也就是访问 API 的那台机器的源地址)
如果 API 前面有反代(Nginx/负载均衡),MediaMTX 看到的源 IP 可能是反代 IP,需要配合 apiTrustedProxies 与反代的 X-Forwarded-For
2.1.3 使用固定账号密码访问 API
如果希望远程调用 API 时必须带账号密码,不建议继续用 user: any。应创建一个管理员用户:
authInternalUsers:
- user: admin
pass: "StrongPasswordHere"
ips: ['172.16.214.0/24']
permissions:
- action: api
- action: metrics调用时需要携带 Basic Auth(curl 示例):
curl -u admin:StrongPasswordHere http://172.16.214.240:9997/v3/config/paths/list说明:
ips 支持 CIDR(例如 172.16.214.0/24)
Basic Auth 仅在 HTTP 明文下不安全,生产建议在可信内网或启用 TLS/HTTPS(见 2.2)
2.1.4 常见误区:以为“写入 API”不需要权限
当 authMethod: internal 时,API 是否免鉴权取决于 authInternalUsers 的规则匹配。很多默认示例会允许 localhost 免鉴权,但对非 localhost 会要求认证或直接拒绝。
2.2 启用 API HTTPS(可选)
如果要在不可信网络中暴露 API,建议启用 apiEncryption: yes 并配置证书(略)。至少应通过内网、专用网络或反向代理 TLS 终止来保护接口。
3. MediaMTX API 连通性与写入验证
3.1 确认 MediaMTX 是否监听 API 端口
查看监听:
ss -lntp | grep 9997典型输出:
LISTEN 0 4096 *:9997 *:* users:(("mediamtx",pid=3161417,fd=14))说明:
*:9997 表示监听所有地址
如果只监听 127.0.0.1:9997,则外部 IP 访问会失败(connection refused)
3.2 验证 API 列表是否有数据(写入是否存在)
本机访问:
curl -s http://127.0.0.1:9997/v3/config/paths/list | python3 -m json.tool | head -n 30重点关注:
- itemCount 是否大于 1(默认至少会有 all_others)
3.3 验证某个 path 是否写入成功
curl -s http://127.0.0.1:9997/v3/config/paths/get/cam_172.17.234.204_ch00000_sub | python3 -m json.tool如果能返回该 path 的完整 JSON,说明写入已生效。
3.4 手工写入一个测试 path(用于确认 API 写入链路)
curl -v -X POST "http://127.0.0.1:9997/v3/config/paths/add/test123" \
-H "Content-Type: application/json" \
-d '{"source":"publisher"}'返回 {"status":"ok"} 说明写入成功。
3.5 日志现象解释:reloading configuration (API request)
当通过 API 修改配置时,MediaMTX 通常会输出类似日志:
INF reloading configuration (API request)如果你在后端日志里提示“注册 OK”,但 MediaMTX 日志完全没有 reloading,常见解释:
后端实际请求没有打到这台 MediaMTX(URL 配错、端口错、DNS/hosts 指向错、访问了别的实例)
后端请求被网关拦截或失败但被吞掉(需要在后端打印 HTTP 返回码与响应体)
API 权限不允许但后端没有正确处理错误响应
4. “写入成功但播放失败”的排障流程
当 WebRTC/HLS/RTSP 读取时报错,例如:
ERR [path ...] [RTSP source] dial tcp <ip>:554: connect: no route to host这说明:MediaMTX 在服务器上无法访问 source 指定的 RTSP 源地址。
排障步骤按顺序执行。
4.1 查看本机 IP 与网卡
ip -4 addr关注:
真实业务网卡(如 ens3f0)的 IP 和网段
是否存在 docker0、cni0 等虚拟网卡占用了与设备相同的网段
4.2 查看到目标 IP 的路由选择
ip route get 172.17.234.204如果输出类似:
172.17.234.204 dev docker0 src 172.17.0.1说明系统认为目标在 docker0 网段内,会把包发给 docker0。这几乎一定导致不可达(除非目标确实在该 docker 网络里)。
4.3 查看系统路由表,判断是否被“占用”
ip route重点看是否存在类似:
172.17.0.0/16 dev docker0 proto kernel scope link src 172.17.0.1这表示 172.17.0.0/16 被 docker0 抢占。
4.4 验证端口可达性
ping -c 2 172.17.234.204
nc -vz 172.17.234.204 554结果解释:
ping 不通:多为路由/VLAN/防火墙或地址根本不存在
ping 通但 554 不通:端口被拦、设备不在 554、或设备限制访问
5. Docker 网段冲突与解决办法
5.1 为什么会冲突
Docker 默认网桥 docker0 常用网段 172.17.0.0/16。 如果你的真实设备(摄像机/交换机/现场网)也使用 172.17.x.x,Linux 路由会优先把该网段流量导向 docker0,从而“劫持”了本应走真实网卡的流量。
典型表现:
ip route get 172.17.x.x 显示 dev docker0
MediaMTX 拉流报 no route to host
在 Windows 本地正常(因为 Windows 没有 docker0 抢这段路由),但服务器不通
5.2 关闭 Docker(不再需要 Docker 的场景)
临时关闭:
sudo systemctl stop docker
sudo systemctl stop containerd永久关闭(禁用自启):
sudo systemctl stop docker
sudo systemctl disable docker
sudo systemctl stop containerd
sudo systemctl disable containerd仅关闭 docker0 网卡(Docker 仍可能重建):
sudo ip link set docker0 down5.3 保留 Docker,但避免网段冲突
修改 Docker 的默认 bridge 网段,让 docker0 不再使用 172.17.0.0/16。
sudo vi /etc/docker/daemon.json示例(将 bridge 改为 172.31.0.1/16):
{
"bip": "172.31.0.1/16",
"default-address-pools": [
{ "base": "172.31.0.0/16", "size": 24 }
]
}重启:
sudo systemctl restart docker验证 docker0 网段是否变化:
ip -4 addr show docker0
ip route | grep docker05.4 使用更精确的静态路由覆盖 docker0(适合你已知真实网关的情况)
如果真实设备网段是 172.17.234.0/24,并且应通过业务网卡 ens3f0 的网关(示例)172.16.214.1 到达,可添加更精确路由:
sudo ip route add 172.17.234.0/24 via 172.16.214.1 dev ens3f0验证:
ip route get 172.17.234.204应不再显示 dev docker0。
注意:需要真实存在到该网段的上游路由器,否则即使加了路由也会不通。
6. Nginx 是否需要配置
是否需要 Nginx,取决于你的目标。
6.1 不需要 Nginx 的情况
SpringBoot 与 MediaMTX 同机,通过 http://127.0.0.1:9997 调用 API
或内网直连
http://<mediamtx-host>:9997,并在 MediaMTX 内部鉴权放行来源 IP
这种情况下,Nginx 不是必需项。
6.2 需要 Nginx 的情况
想把 API 统一暴露在 80/443(隐藏 9997)
想做 TLS/HTTPS(Nginx 终止 TLS)
想做统一认证(例如 Basic/Auth/JWT 在 Nginx 层)
多实例 MediaMTX,需要一个统一入口转发(按域名、路径、端口或 upstream 规则)
提示:如果你用 Nginx 反代并希望 MediaMTX 按真实来源 IP 控制权限,需要:
Nginx 配置 X-Forwarded-For
MediaMTX 配置 apiTrustedProxies,并将 Nginx 的 IP 加进去,让 MediaMTX 从 header 取真实 IP
7. 常用检查清单(按现象定位)
7.1 API “connection refused”
MediaMTX 是否运行、是否监听 9997:
ss -lntp | grep 9997是否写错端口:未写 :9997 会去 80
防火墙是否拦截:sudo ufw status 或 iptables -S(视系统而定)
7.2 API “authentication error”
authMethod 是否开启
internal/http/jwtauthInternalUsers 是否允许来源 IP 拥有 api 权限
如果走了 Nginx 反代,MediaMTX 看到的来源 IP 可能是反代 IP(导致权限匹配失败)
7.3 写入成功但 MediaMTX 没有 “reloading configuration”
后端请求是否真正到达该实例(检查 URL/端口/DNS/容器网络)
后端是否吞了错误(打印 HTTP code 与响应体)
是否写到另一个 MediaMTX 实例或另一个环境
7.4 “no route to host”
ip route get <目标IP>是否指向 docker0/cni0 等虚拟网卡是否网段冲突(172.17.x.x 常见与 docker0 冲突)
是否缺少上游路由
8. 建议的部署实践(多 MediaMTX 场景)
- 控制面(API)与数据面(WebRTC/HLS/RTSP)分离考虑
API 建议仅内网可访问,或加固鉴权、TLS
播放端口(如 WebRTC 8889/HLS 8888)按业务需要暴露
- 每台 MediaMTX 必须能访问其负责的源地址
如果采用“拉模式”(source=rtsp://…),必须保证服务器对摄像机网段可达
如果摄像机网段复杂或跨网段,优先考虑“推模式”或在摄像机内网部署代理/NVR 再推到 MediaMTX
- 避免使用与 Docker/K8s 常用网段冲突的真实网络规划
- 尽量不要让真实设备使用 172.17.0.0/16、10.244.0.0/16、10.96.0.0/12 等常见容器网段
9. 附:最小命令集(现场排查常用)
# 1) 看本机 IP
ip -4 addr
# 2) 看路由表
ip route
# 3) 看访问目标 IP 会走哪个网卡
ip route get <target-ip>
# 4) 看端口监听
ss -lntp | egrep '(:9997|:8889|:8888|:8554)'
# 5) API list / get 验证写入
curl -s http://127.0.0.1:9997/v3/config/paths/list | python3 -m json.tool | head
curl -s http://127.0.0.1:9997/v3/config/paths/get/<path> | python3 -m json.tool
# 6) 端口可达性
ping -c 2 <target-ip>
nc -vz <target-ip> 554贡献者
flycodeu
版权所有
版权归属:flycodeu
