# NAS媒体刮削TMDB接口访问问题完整排查\+落地文档 # NAS 媒体刮削 TMDB 接口访问问题完整排查 \+ 落地文档 > 文档来源:本次全部对话记录整理,包含:故障现象、完整排错过程、根因分析、两套可落地解决方案、配置模板、验证命令、故障清单 > 环境:MacOS Clash Verge Rev、群晖 NAS(Mihomo\+Hysteria2 正常)、飞牛 fnOS(Docker 部署 MoviePilot、tinyMediaManager) > > ## 目录 1. 故障现象汇总 2. 前期网络排错全过程(curl、TLS、Hysteria2 排查) 3. 根因分析 4. 方案一【主方案|推荐日常使用】飞牛容器复用群晖 Mihomo 代理 5. 方案二【备用兜底方案】Cloudflare Worker TMDB 中转(鉴权 \+ 缓存,无需代理) 6. 两套方案切换规则 7. 统一故障排查清单 8. 附录:测试命令、参考脚本 --- # 1\. 故障现象汇总 ## 1\.1 网络侧现象 1. MacOS 客户端:Clash Verge Rev(Mihomo 内核),Hysteria2 节点,访问`api.themoviedb.org`正常,TMDB 接口可访问。 2. 群晖 NAS:部署 Mihomo,**同一份 config\.yaml、相同内核版本**,Hysteria2 节点正常,MoviePilot、TinyMediaManager 媒体刮削,TMDB 接口调用全部正常。 3. 飞牛 fnOS: - 飞牛系统无系统级全局代理; - 飞牛 Docker 内部署 Mihomo,订阅同样 Hysteria2 节点,节点列表加载成功,但所有 Hysteria2 节点 TLS 握手失败,`SSL_ERROR_SYSCALL`; - 在飞牛上部署 MoviePilot、tinyMediaManager,调用 TMDB API 接口全部超时失败,无法刮削媒体元数据。 > 测试现象:curl 访问`https://api.themoviedb.org`,TLS 握手卡在 Client Hello 后直接断开,报错:`curl: (35) OpenSSL SSL_connect: SSL_ERROR_SYSCALL`。 > > ## 1\.2 测试过程关键现象 1. 裸网直接访问`api.themoviedb.org:443`:TCP 能建立连接,TLS 握手中断,SNI 被网络拦截。 2. 使用本地 SOCKS5 代理(7890),未使用`--socks5-hostname`:本地解析域名,拿到污染 IP,握手失败;使用`--socks5-hostname`,域名交由代理远端解析。 3. Hysteria2 依赖 UDP QUIC 协议;飞牛 fnOS 的 OVS 虚拟交换机 \+ 家庭路由器会拦截 UDP 出站,导致 HY2 QUIC 握手超时。 4. 飞牛 Docker 容器**不会自动继承宿主机的代理**,容器内程序(MoviePilot/TMM)不会自动走宿主机 Mihomo。 --- # 2\. 前期网络排错全过程记录 ## 2\.1 基础 curl 裸网测试 ```bash # 测试80端口HTTP curl -v api.themoviedb.org # HTTPS裸网测试,TLS握手失败 curl -v https://api.themoviedb.org ``` 现象:TCP 连接成功,发送 TLS Client Hello 之后直接断开,报错 `SSL_ERROR_SYSCALL`。 > 尝试指定 TLS 版本`--tls-max 1.2`,依旧握手失败。 > > ## 2\.2 SOCKS 代理测试(本地 7890 端口) ```bash # 错误:本地解析域名 curl -v --socks5 127.0.0.1:7890 https://api.themoviedb.org # 正确:远端域名解析(socks5h) curl -v --socks5-hostname 127.0.0.1:7890 https://api.themoviedb.org # 验证代理出口IP curl -v --socks5-hostname 127.0.0.1:7890 https://ifconfig.me ``` > 结论:`--socks5` 是本地解析域名,容易拿到污染 IP;**`--socks5-hostname`** 将域名解析交给远端代理服务器,规避 DNS 污染。 > > ## 2\.3 协议选型评估:mieru /anytls/hysteria2 |协议|特点|本次环境适配性| |---|---|---| |Hysteria2|QUIC/UDP,速度好;**强依赖 UDP 出站**|Mac / 群晖正常;飞牛 fnOS 受 OVS、路由器 UDP 拦截,无法稳定运行| |AnyTLS|TCP 隧道,不依赖 UDP;存在内层 TLS1\.3 报文被篡改风险|UDP 不通场景备选,稳定性弱于 HY2| |Mieru|TCP 隧道,抗干扰;同样 TCP 底层,TLS1\.3 握手存在概率异常|备选| > 结论:飞牛环境不适合本地部署 Hysteria2,放弃在飞牛本机跑代理。 > > ## 2\.4 Mihomo 日志排查方法(飞牛 Docker) 1. 修改 Mihomo 配置,开启 debug 日志 ```yaml log-level: debug external-controller: 127.0.0.1:9090 ``` 2. 查看容器实时日志 ```bash # 查看容器名 docker ps | grep mihomo # 实时跟踪日志 docker logs -f --tail 100 mihomo # 导出日志到文件 docker logs mihomo > mihomo-debug.log ``` 3. 关键词识别 - `quic: connection timed out` → UDP 出站被拦截(本次核心问题) - `unsupported proxy type: hysteria2` → Mihomo 内核版本过低 - `tls: certificate verify failed` → 需要`skip-cert-verify: true` > 验证连通性(飞牛容器内 curl 测试) > > ```bash docker exec -it moviepilot curl -v --socks5-hostname 群晖IP:7890 https://api.themoviedb.org/3/movie/550?api_key=你的TMDBKEY ``` --- # 3\. 根因分析 1. 飞牛 fnOS 自带 OVS 虚拟交换机,会拦截 UDP 数据包;家庭路由器 / 光猫也会限制 UDP 出站,Hysteria2(QUIC/UDP)无法正常建立隧道。 2. 飞牛 Docker 容器隔离:容器内程序不会自动复用宿主机代理,MoviePilot、TMM 裸网访问 TMDB,遭遇 DNS 污染 \+ SNI 阻断。 3. Mac、群晖网络环境 UDP 不受限,所以同样配置、同样节点可以正常工作。 > 最终方案思路:**不再在飞牛部署 Mihomo 代理**,采用双冗余架构: > ✅ 主方案:飞牛容器内 MoviePilot/TMM 直接复用**群晖 Mihomo 的 SOCKS5 代理** > ✅ 备用方案:CF Worker 中转 TMDB API,**完全不需要代理**,群晖 / 代理故障时兜底刮削。 > > --- # 4\. 方案一【主方案|推荐日常使用】飞牛容器复用群晖 Mihomo 代理 ## 4\.1 群晖 Mihomo 前置配置(必须) 群晖 Mihomo `config.yaml` 关键配置,**允许局域网访问** ```yaml mixed-port: 7890 allow-lan: true listen-address: 0.0.0.0 ipv6: false ``` > 要求:群晖防火墙放行 7890 端口;飞牛与群晖在同一局域网,无跨 VLAN 隔离。 > > ## 4\.2 MoviePilot docker\-compose\.yml(飞牛 fnOS) > 修改:`192.168.1.100` 替换为**群晖内网 IP**;修改 volume 路径为飞牛实际路径 > > ```yaml version: "3.8" services: moviepilot: image: jxxghp/moviepilot:latest container_name: moviepilot restart: unless-stopped ports: - "3000:3000" volumes: - /volume1/moviepilot:/app/config environment: - TZ=Asia/Shanghai # socks5h = 远端域名解析,规避DNS污染 - PROXY_HOST=socks5h://192.168.1.100:7890 # Github资源加速,解决插件下载失败 - GITHUB_PROXY=https://mirror.ghproxy.com/ network_mode: bridge ``` ### MoviePilot WebUI 配置 - TMDB 地址保持官方默认,**PROXY\_HOST 已由环境变量注入,无需重复填写** - 填入你的 TMDB API Key > 启动命令:`docker-compose up -d` > > ## 4\.3 TinyMediaManager \(TMM\) docker\-compose\.yml(飞牛 fnOS) ```yaml version: "3.8" services: tinymediamanager: image: tinymediamanager/tinymediamanager:latest container_name: tinymediamanager restart: unless-stopped ports: - "4000:4000" volumes: - /volume1/tmm:/config environment: - TZ=Asia/Shanghai - ALL_PROXY=socks5h://192.168.1.100:7890 - NO_PROXY=127.0.0.1,localhost,192.168.0.0/16 network_mode: bridge ``` ### TMM WebUI 代理配置(推荐优先使用网页内配置,比环境变量更稳定) - Proxy type: `SOCKS5` - Host:群晖内网 IP - Port:7890 - ✅ 勾选:Resolve hostnames remotely(远端域名解析,等价 socks5h) ## 4\.4 连通验证命令 ```bash docker exec -it moviepilot curl -v --socks5-hostname 192.168.1.100:7890 https://api.themoviedb.org/3/movie/550?api_key=你的TMDB密钥 ``` > 返回 JSON 代表链路正常。 > > --- # 5\. 方案二【备用兜底方案】Cloudflare Worker TMDB 中转(鉴权 \+ 缓存,无需代理) > 适用场景:群晖关机、代理节点失效、UDP 链路彻底不可用。仅接管 TMDB 接口,Github、豆瓣等其他外网 API 仍然需要代理。 > 免费限制:CF Worker 免费版每日 10 万次请求,日常刮削完全够用。 > > ## 5\.1 主中转 Worker 脚本(鉴权 \+ 缓存) 登录 Cloudflare 后台 → Workers \& Pages → 创建 Worker,清空原有代码粘贴下面代码 ```javascript export default { async fetch(request, env) { // ========== 自定义你的访问密钥,自行修改 ========== const ACCESS_SECRET = "自定义随机密钥"; // 缓存有效期,单位秒:3600=1小时;600=10分钟;86400=24小时 const CACHE_TTL = 3600; // ================================================ const auth = request.headers.get("X-Tmdb-Secret"); if (!auth || auth !== ACCESS_SECRET) { return new Response("Access Denied", { status: 403 }); } const targetHost = "api.themoviedb.org"; const url = new URL(request.url); url.hostname = targetHost; const newReq = new Request(url, request); newReq.headers.set("Host", targetHost); // GET请求开启缓存,提升速度、节约额度 if (request.method === "GET") { const cacheKey = new Request(newReq.url, newReq); const cache = caches.default; let response = await cache.match(cacheKey); if (!response) { response = await fetch(newReq); response = new Response(response.body, response); response.headers.set("Cache-Control", `s-maxage=${CACHE_TTL}`); await cache.put(cacheKey, response.clone()); } return response; } // POST等其他请求直接透传,不缓存 return await fetch(newReq); } } ``` 保存部署,得到 worker 域名,示例 `tmdb-proxy.xxx.workers.dev` ## 5\.2 缓存清理三种方案 1. **单影片临时绕过缓存(最简单)** 请求地址末尾追加:`&_nocache=随机数字` 示例: `https://tmdb-proxy.xxx.workers.dev/3/movie/550?api_key=xxx&_nocache=20260925` 2. **全局一键清空全部缓存(批量重刷媒体库)** 修改 Worker 代码任意一行,重新部署;CF 所有边缘节点缓存自动全部失效。 3. **精准单条缓存删除(进阶 Purge Worker)** 新建独立 Worker(tmdb\-purge),粘贴下面代码,密钥和主 Worker 保持一致 ```javascript export default { async fetch(request, env) { const ACCESS_SECRET = "和主Worker相同的密钥"; const auth = request.headers.get("X-Tmdb-Secret"); if (!auth || auth !== ACCESS_SECRET) { return new Response("Access Denied", { status: 403 }); } const url = new URL(request.url); const targetPath = url.searchParams.get("path"); if (!targetPath) { return new Response("Missing ?path=/3/movie/550", { status: 400 }); } // 替换为你的主worker域名 const cacheUrl = new URL(`https://tmdb-proxy.xxx.workers.dev${targetPath}`); const cacheReq = new Request(cacheUrl); const cache = caches.default; await cache.delete(cacheReq); return new Response(`Purged: ${cacheUrl.toString()}`); } } ``` 调用示例: ```bash curl -v -H "X-Tmdb-Secret: 自定义随机密钥" "https://tmdb-purge.xxx.workers.dev/?path=/3/movie/550?api_key=你的TMDBKEY" ``` ## 5\.3 MoviePilot 切换 CF Worker 配置 1. 清空 PROXY\_HOST(关闭代理) 2. TMDB API 地址:`https://tmdb-proxy.xxx.workers.dev/3` 3. 自定义请求头添加一行: `X-Tmdb-Secret: 自定义随机密钥` 4. 保留原有 TMDB API Key ## 5\.4 TMM 切换 CF Worker 配置 1. TMDB API URL 替换为 worker 地址 `https://tmdb-proxy.xxx.workers.dev/3` 2. Custom HTTP Headers 添加:`X-Tmdb-Secret: 自定义随机密钥` 3. 关闭 TMM 内部代理设置 ## 5\.5 curl 测试命令 ```bash curl -v -H "X-Tmdb-Secret: 自定义随机密钥" "https://tmdb-proxy.xxx.workers.dev/3/movie/550?api_key=你的TMDBKEY" ``` 返回 JSON 即为正常。 --- # 6\. 两套方案切换规则 |方案|适用场景|优点|缺点| |---|---|---|---| |复用群晖 Mihomo(主方案)|日常长期使用,群晖保持开机|全覆盖 TMDB/Github/ 豆瓣,无额度限制,速度稳定|依赖群晖在线,群晖关机则刮削失效| |CF Worker 中转(备用)|群晖关机、代理节点故障、UDP 被拦截|零代理依赖,不受 UDP/OVS 限制,自带缓存加速|仅 TMDB 接口生效,CF 免费版有每日额度上限| > 使用策略:日常使用主方案;代理故障 / 群晖关机,临时切换到 CF Worker 兜底刮削。 > > --- # 7\. 统一故障排查清单 1. ❌ 容器内不要填写`127.0.0.1`作为代理地址,容器内 \[127\.0\.0\.1\]\(127\.0\.0\.1\) 指向容器自身,必须填写群晖内网 IP。 2. ✅ 群晖 Mihomo 必须开启`allow-lan: true`,监听地址`0.0.0.0`,否则飞牛无法访问 7890 端口。 3. ✅ 飞牛环境关闭 IPv6,规避 TLS 握手异常。 4. ❌ 放弃飞牛本地部署 Hysteria2,OVS \+ 路由器 UDP 拦截属于硬限制。 5. ✅ MoviePilot/TMM 优先使用软件原生内置代理配置,优于`ALL_PROXY`环境变量。 6. 测试链路优先使用`--socks5-hostname`,远端解析域名,规避 DNS 污染。 7. 代理测试失败优先查看 Mihomo debug 日志,定位是 UDP 超时、证书错误还是鉴权错误。 --- # 8\. 附录:常用命令汇总 ```bash # 查看docker容器 docker ps | grep mihomo docker ps | grep moviepilot # 实时查看mihomo日志 docker logs -f --tail 100 mihomo # 进入moviepilot容器curl测试代理连通 docker exec -it moviepilot curl -v --socks5-hostname 群晖IP:7890 https://api.themoviedb.org/3/movie/550?api_key=你的TMDBKEY # 测试CF Worker中转 curl -v -H "X-Tmdb-Secret: 自定义密钥" "https://tmdb-proxy.xxx.workers.dev/3/movie/550?api_key=你的TMDBKEY" ``` --- 如果你想要,我可以再输出 **Markdown 纯文本版本**(不带任何 canvas 标签,直接复制到 Typora/Obsidian/ 语雀保存)。你要 Markdown 版本吗? > (注:部分内容可能由 AI 生成)