259 lines
7.9 KiB
Markdown
259 lines
7.9 KiB
Markdown
# NAS(群晖\+飞牛)MoviePilot/TMM TMDB刮削 终极稳定技术方案
|
||||
|
|
|
|||
|
|
## 一、问题背景与核心故障根源
|
|||
|
|
|
|||
|
|
### 1\.1 设备环境差异
|
|||
|
|
|
|||
|
|
- **群晖NAS**:Mihomo代理正常、Hysteria2节点正常、UDP链路通畅、全局代理生效,MoviePilot/TMM刮削全部正常。
|
|||
|
|
|
|||
|
|
- **飞牛fnOS**:无系统全局代理、OVS虚拟交换机拦截UDP、Hysteria2(QUIC/UDP)链路大面积失效,导致所有TMDB API请求超时/握手失败,媒体刮削完全不可用。
|
|||
|
|
|
|||
|
|
### 1\.2 核心技术故障定论
|
|||
|
|
|
|||
|
|
本次故障**不是节点、密钥、TLS版本、DNS污染问题**,是环境硬限制:
|
|||
|
|
|
|||
|
|
- TMDB CloudFront 强制仅支持 **TLS1\.3**;
|
|||
|
|
|
|||
|
|
- 传统TCP隧道(Vmess/Vless/AnyTLS/Mieru)存在内层TLS1\.3报文损坏缺陷;
|
|||
|
|
|
|||
|
|
- 唯一稳定的Hysteria2(QUIC/UDP)协议,被飞牛fnOS OVS/路由器UDP拦截;
|
|||
|
|
|
|||
|
|
- 飞牛Docker容器**不会自动继承宿主机代理**,裸网访问TMDB必然失败。
|
|||
|
|
|
|||
|
|
**结论**:飞牛无法本地稳定运行HY2代理,放弃飞牛本地代理,采用「双方案冗余架构」解决刮削问题。
|
|||
|
|
|
|||
|
|
## 二、整体架构设计(双冗余方案)
|
|||
|
|
|
|||
|
|
**主方案(长期日常使用)**:飞牛容器复用群晖Mihomo代理(全接口覆盖)
|
|||
|
|
|
|||
|
|
**备方案(断代理兜底)**:Cloudflare Worker带鉴权\+缓存TMDB中转(无需任何代理、纯裸网可用)
|
|||
|
|
|
|||
|
|
两套方案可随时切换,彻底解决飞牛TMDB刮削不稳定问题。
|
|||
|
|
|
|||
|
|
## 三、主方案:飞牛复用群晖Mihomo代理(推荐默认启用)
|
|||
|
|
|
|||
|
|
### 3\.1 前置必备条件(必须配置)
|
|||
|
|
|
|||
|
|
群晖Mihomo **config\.yaml** 核心配置(允许局域网访问):
|
|||
|
|
|
|||
|
|
```yaml
|
|||
|
|
mixed-port: 7890
|
|||
|
|
allow-lan: true
|
|||
|
|
listen-address: 0.0.0.0
|
|||
|
|
ipv6: false
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
群晖防火墙放行 **7890端口**,飞牛与群晖处于同一局域网、无跨VLAN隔离。
|
|||
|
|
|
|||
|
|
### 3\.2 MoviePilot 完整部署配置
|
|||
|
|
|
|||
|
|
飞牛docker\-compose\.yml,直接复用群晖SOCKS5代理,自动解决TMDB/Github/豆瓣全部外网请求。
|
|||
|
|
|
|||
|
|
```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
|
|||
|
|
# 核心代理配置:远端解析域名,规避DNS污染
|
|||
|
|
- PROXY_HOST=socks5h://192.168.1.100:7890
|
|||
|
|
# Github加速,解决插件/资源下载失败
|
|||
|
|
- GITHUB_PROXY=https://mirror.ghproxy.com/
|
|||
|
|
network_mode: bridge
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
⚠️ 替换:`192.168.1.100` 为你的**群晖真实内网IP**,目录按需修改。
|
|||
|
|
|
|||
|
|
### 3\.3 MoviePilot 网页端配置
|
|||
|
|
|
|||
|
|
- 无需修改TMDB接口地址,保持官方默认
|
|||
|
|
|
|||
|
|
- PROXY\_HOST已由环境变量注入,无需重复填写
|
|||
|
|
|
|||
|
|
- 正常填写TMDB API Key即可
|
|||
|
|
|
|||
|
|
### 3\.4 TinyMediaManager\(TMM\) 部署配置
|
|||
|
|
|
|||
|
|
```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
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 3\.5 TMM 网页端代理配置(优先推荐)
|
|||
|
|
|
|||
|
|
- Proxy type: SOCKS5
|
|||
|
|
|
|||
|
|
- Host: 群晖内网IP
|
|||
|
|
|
|||
|
|
- Port: 7890
|
|||
|
|
|
|||
|
|
- 开启:Resolve hostnames remotely(远端域名解析,等价socks5h)
|
|||
|
|
|
|||
|
|
### 3\.6 连通性验证命令(飞牛SSH执行)
|
|||
|
|
|
|||
|
|
```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即为代理通路正常。
|
|||
|
|
|
|||
|
|
## 四、备方案:CF Worker 鉴权\+缓存 TMDB 中转(无代理兜底)
|
|||
|
|
|
|||
|
|
**适用场景**:群晖关机、代理节点故障、飞牛UDP彻底不通,**零代理依赖**完成TMDB刮削。
|
|||
|
|
|
|||
|
|
**核心优势**:TCP链路传输、不受UDP/OVS限制、带密码防盗刷、自带缓存提速、节省TMDB/CF额度。
|
|||
|
|
|
|||
|
|
### 4\.1 主中转Worker代码(鉴权\+缓存)
|
|||
|
|
|
|||
|
|
新建Worker,清空默认代码,粘贴如下完整版:
|
|||
|
|
|
|||
|
|
```javascript
|
|||
|
|
export default {
|
|||
|
|
async fetch(request, env) {
|
|||
|
|
// 自定义你的访问密钥
|
|||
|
|
const ACCESS_SECRET = "自定义随机密钥";
|
|||
|
|
// 缓存有效期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;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return await fetch(newReq);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 4\.2 缓存清理方案(三种方式)
|
|||
|
|
|
|||
|
|
#### 方式1:临时绕过缓存(单影片刷新,最简单)
|
|||
|
|
|
|||
|
|
链接后追加参数:`&_nocache=随机数字`
|
|||
|
|
|
|||
|
|
#### 方式2:全局一键清缓存(批量重刷库)
|
|||
|
|
|
|||
|
|
修改任意一行Worker代码并重新部署,CF边缘节点缓存**全部自动清空**。
|
|||
|
|
|
|||
|
|
#### 方式3:精准单条缓存删除(进阶)
|
|||
|
|
|
|||
|
|
单独部署purge清理Worker,支持指定路径删除缓存(文档末尾附代码)。
|
|||
|
|
|
|||
|
|
### 4\.3 MoviePilot 切换Worker配置
|
|||
|
|
|
|||
|
|
- 清空 **PROXY\_HOST**(关闭代理)
|
|||
|
|
|
|||
|
|
- TMDB API地址:`https://你的worker域名.workers.dev/3`
|
|||
|
|
|
|||
|
|
- 自定义请求头新增:`X-Tmdb-Secret: 你的自定义密钥`
|
|||
|
|
|
|||
|
|
- 保留原有TMDB Key
|
|||
|
|
|
|||
|
|
### 4\.4 TMM 切换Worker配置
|
|||
|
|
|
|||
|
|
- TMDB API URL 替换为Worker地址
|
|||
|
|
|
|||
|
|
- Custom HTTP Headers 添加 `X-Tmdb-Secret: 你的密钥`
|
|||
|
|
|
|||
|
|
- 关闭软件内代理设置
|
|||
|
|
|
|||
|
|
### 4\.5 缓存清理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 });
|
|||
|
|
}
|
|||
|
|
const cacheUrl = new URL(`https://你的主worker域名.workers.dev${targetPath}`);
|
|||
|
|
const cacheReq = new Request(cacheUrl);
|
|||
|
|
const cache = caches.default;
|
|||
|
|
await cache.delete(cacheReq);
|
|||
|
|
return new Response(`Purged: ${cacheUrl.toString()}`);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 五、两套方案取舍标准
|
|||
|
|
|
|||
|
|
|方案|适用场景|优点|缺点|
|
|||
|
|
|---|---|---|---|
|
|||
|
|
|群晖代理复用(主)|日常长期使用、群晖开机|全覆盖(TMDB/Github/豆瓣)、无额度限制、速度稳定|依赖群晖在线|
|
|||
|
|
|CF Worker中转(备)|群晖关机、代理故障、UDP拦截|零代理依赖、抗网络污染、自带缓存加速|仅覆盖TMDB、有每日免费额度|
|
|||
|
|
|
|||
|
|
## 六、通用排坑清单(飞牛专属)
|
|||
|
|
|
|||
|
|
1. **禁止使用127\.0\.0\.1**:容器内回环地址指向自身,必须填写群晖内网IP
|
|||
|
|
|
|||
|
|
2. **必须开启allow\-lan: true**:群晖Mihomo禁止仅监听127\.0\.0\.1
|
|||
|
|
|
|||
|
|
3. **飞牛关闭IPv6**:规避隧道TLS1\.3握手异常
|
|||
|
|
|
|||
|
|
4. **放弃飞牛本地HY2**:fnOS OVS\+路由器UDP拦截为硬故障,无法修复
|
|||
|
|
|
|||
|
|
5. **优先软件内置代理**:MoviePilot/TMM原生代理优于系统环境变量代理
|
|||
|
|
|
|||
|
|
## 七、最终落地规范
|
|||
|
|
|
|||
|
|
- 日常默认:**群晖Mihomo代理复用方案**
|
|||
|
|
|
|||
|
|
- 故障兜底:**CF Worker鉴权缓存中转方案**
|
|||
|
|
|
|||
|
|
- 永久废弃:飞牛本地Hysteria2代理、TCP隧道(AnyTLS/Mieru/Vmess)
|
|||
|
|
|
|||
|
|
> (注:部分内容可能由 AI 生成)
|