Skip to content

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

约 2744 字大约 9 分钟

MediaMTX视频

2026-01-16

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. 背景与关键结论

  1. “写入成功”与“能播放”是两件事
  • 写入成功:/v3/config/paths/get/<path> 能返回该 path 的完整配置;/v3/config/paths/list 的 itemCount 增加。
  • 能播放:MediaMTX 需要能从服务器侧访问到 source 指定的 RTSP/RTMP/HLS 等源地址。网络不可达会导致 WebRTC/HLS session 报错。
  1. 使用 IP 访问 API 失败(authentication error / connection refused)常见原因
  • MediaMTX API 只允许 localhost 免鉴权,远程访问需要明确配置权限或账号密码

  • 端口没开放或服务没监听到指定地址(或被防火墙拒绝)

  • 使用了错误端口(例如没写 :9997,默认走 80)

  • 请求走了反向代理(Nginx/网关)导致鉴权规则不同

  1. “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 down

5.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 docker0

5.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/jwt

  • authInternalUsers 是否允许来源 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 场景)

  1. 控制面(API)与数据面(WebRTC/HLS/RTSP)分离考虑
  • API 建议仅内网可访问,或加固鉴权、TLS

  • 播放端口(如 WebRTC 8889/HLS 8888)按业务需要暴露

  1. 每台 MediaMTX 必须能访问其负责的源地址
  • 如果采用“拉模式”(source=rtsp://…),必须保证服务器对摄像机网段可达

  • 如果摄像机网段复杂或跨网段,优先考虑“推模式”或在摄像机内网部署代理/NVR 再推到 MediaMTX

  1. 避免使用与 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

贡献者

  • flycodeuflycodeu

公告板

2025-03-04正式迁移知识库到此项目