Nginx实现FLV视频流代理转发:跨域与鉴权踩坑全记录
前端用 flv.js 播放 HTTP-FLV 视频流时,经常会遇到跨域、HTTPS 混合内容、鉴权等问题。本文记录了我用 Nginx 反向代理解决这些问题的完整过程,以及踩过的坑:HEAD 误判、GET 才触发 401、上游地址混淆等。
一、问题背景:为什么要做 FLV 代理?
前端用 flv.js 播放 HTTP-FLV 时,通常会遇到两个现实问题:
1. 跨域(CORS)
原始视频流地址来自另一个域名/IP,例如:
1 | http://19.15.67.125/slvideo_SYY_172/hls/47c18e6792155981a28f3951977db417.flv?token=... |
浏览器直接请求会被 CORS 拦截,导致无法播放。
2. HTTPS 页面混合内容(Mixed Content)
如果前端页面是 https://,而视频源站是 http://,浏览器会直接拦截或提示不安全。
最稳的方式是:让前端始终请求”同源/同协议”的代理地址,由 Nginx 去转发到源站。
为了解决这些问题,我选择用 Nginx 反向代理:前端请求 Nginx,本机/同域返回并加 CORS 头,Nginx 转发到真实源站。
二、先把关系搞清楚:三类地址最容易混淆
这次踩坑里最容易搞错的是:**哪个是”源站”,哪个是”Nginx 代理服务器”**。
| 类型 | 地址 |
|---|---|
| Nginx 代理服务器(我的机器) | http://10.144.32.219:18001 |
| 真实 FLV 源站(视频平台/摄像头出口) | http://19.15.67.125 |
| 前端最终应该请求的地址 | http://10.144.32.219:18001/video-proxy/... |
一开始我误把
10.144.32.219当成上游源站写进了proxy_pass,导致逻辑变成”代理转发到自己”,怎么都不对。
经验结论
以 /api/video/play 返回的 data.httpflv 的 host 为准:它返回的是 19.15.67.125,那 Nginx 的 proxy_pass 就必须指向 19.15.67.125。
三、一个很隐蔽的坑:curl -I 会误导你(HEAD ≠ GET)
我最开始用:
1 | curl -I "http://19.15.67.125/xxx.flv?token=..." |
结果看到 200 OK,还以为源站没问题。
但后来改用真正拉数据的方式:
1 | curl -v --range 0-1023 --output NUL "http://19.15.67.125/xxx.flv?token=..." |
马上暴露真实情况:401 Unauthorized。
为什么会这样?
curl -I发的是 HEAD 请求,只要响应头,不取 body- 很多流媒体/鉴权服务对 HEAD 的处理很”宽松”或直接返回空头;真正的权限校验是在 GET 才触发
- 所以判定视频流是否可拉,必须用 GET(最好带 Range)测试
结论:不要用 HEAD 判断 FLV 是否可用,请用
GET + Range
四、核心方案:Nginx 反向代理配置
最终配置(固定上游 + 路径透传)
我选择在独立端口 18001 上单独开一个 server,并限定只匹配 /video-proxy/,避免误伤其它请求。
1 | server { |
为什么 proxy_pass 末尾一定要有 /?
| 写法 | 效果 |
|---|---|
proxy_pass http://19.15.67.125/; |
会把 /video-proxy/ 前缀剥掉后透传到源站 ✅ |
proxy_pass http://19.15.67.125; |
路径拼接规则会变,容易把 /video-proxy/ 一起带过去造成 404 ❌ |
这点是流媒体代理里最常见的”明明能连上但总 404”的坑。
五、前端拼接规则
原始地址:
1 | http://19.15.67.125/slvideo_SYY_172/hls/xxx.flv?token=xxx |
前端最终请求(同源代理):
1 | http://10.144.32.219:18001/video-proxy/slvideo_SYY_172/hls/xxx.flv?token=xxx |
示例代码(核心思路是只取 pathname + search):
1 | const originalFlv = data.httpflv; // http://19.15.67.125/xxx.flv?token=... |
六、验证与排错
1) 语法检查并重载(Windows)
1 | nginx.exe -t |
2) 端口监听确认
1 | netstat -ano | findstr :18001 |
3) 用 GET + Range 测试代理
1 | curl -v --range 0-1023 --output NUL "http://10.144.32.219:18001/video-proxy/slvideo_SYY_172/hls/xxx.flv?token=xxx" |
期望:200 或 206 Partial Content,不是 401/403/502/504
4) 如果出现 401:这是鉴权问题,不是跨域问题
这次对话里最关键的真相是:源站对 curl 的 GET 请求返回 401 Unauthorized。
这说明:
- token 可能很快过期(几秒到几分钟)
- 或者源站除了 token 还校验 Referer/Cookie/Authorization/User-Agent
- 代理配置再完美,鉴权不过依旧会 401
可选:透传常见鉴权 header
1 | proxy_set_header Referer $http_referer; |
安全提醒:透传 Cookie/Authorization 之前最好加访问控制(白名单/内网),避免变成开放代理。
七、Windows 部署补充
Windows 下 Nginx 放哪都能跑,但会影响:
include mime.types;这类相对路径能否找到logs/是否有写权限- 你是否能稳定重载/开机自启
推荐固定目录:C:\nginx\
用”明确前缀和配置文件”的方式启动:
1 | C:\nginx\nginx.exe -p C:\nginx\ -c conf\nginx.conf |
重载同理:
1 | C:\nginx\nginx.exe -p C:\nginx\ -c conf\nginx.conf -s reload |
八、踩坑总结
| 坑 | 解决方案 |
|---|---|
| host 搞错 | 以 API 返回的 httpflv host 为准 |
| HEAD 验证误导 | 必须用 GET + Range 测试 |
| 401 当成跨域问题 | 401 是鉴权问题,代理不能绕过权限 |
| Windows Nginx 路径混乱 | 固定 -p 和 -c 参数启动 |
| 端口不通 | Windows 防火墙/安全组都要开放 |
结语
通过 Nginx 反向代理,我们成功解决了 FLV 视频流的跨域和 HTTPS 混合内容问题。关键在于:搞清楚源站地址、用正确的方式验证、理解 401 是鉴权而非跨域问题。希望这篇踩坑记录能帮到你!
💡 提示:如果需要在 HTTPS 环境下使用,只需将代理 server 配到 443 端口并配置 SSL 证书即可。