文章如果有费解的地方麻烦留言指出,我将更新贴子方便更多人阅读理解。
阿里云基础版体验地址
这篇文章解决的是一个很具体、也很常见的问题:
- 家里的飞牛 NAS 只有公网 IPv6;
- 你已经通过飞牛系统里的 DDNS,把 AAAA 记录同步到了
fn-ipv6.域名.xyz;
- 你也已经通过腾讯 EO 的
fn.域名.xyz 成功把飞牛控制台暴露给 IPv4 网络访问;
- 但是一旦下载大文件,腾讯 EO 这条链路在实测里会明显掉速。
我最后采用的是一套分流方案:
fn.域名.xyz 继续走腾讯 EO,负责登录、控制台(后续指网页桌面)、WebSocket 和日常交互;
fn-share.域名.xyz 走阿里云 ESA,专门负责文件预览、文件下载和分享流量;
/multiple-download 这是飞牛的预览和下载文件的API路径,先由腾讯 EO 边缘函数做一次 302 跳转,把下载请求导到阿里云 ESA;
- 阿里云 ESA 再把请求还原成飞牛能识别的 Cookie 形式,回源到飞牛分享端口。
这样做的核心原因很简单:
- 腾讯 EO 这一侧,日常交互稳定,适合飞牛控制台;
- 阿里云 ESA 免费版在我这里实测下载速度更好,适合大文件走流量;
- 但阿里云 ESA 免费版对 WebSocket 的支持并不稳定,所以不适合把整个飞牛控制台全量迁过去。
说明:本文基于 2026-06-18 的实际控制台界面和现网测试整理。飞牛的下载接口、云厂商套餐能力和飞牛API 后续都可能变化,到时大家可以提醒一下。
这套方案最后长什么样
先看我这套分工:
| 域名 |
作用 |
走哪一层 |
fn-ipv6.域名.xyz |
飞牛 DDNS 的 AAAA 回源域名 |
直达家里公网 IPv6 NAS |
fn.域名.xyz |
飞牛主控制台、登录、WebSocket |
腾讯 EO -> ipv6回源域名 |
fn-share.域名.xyz |
文件预览、文件下载、分享流量 |
阿里云 ESA ->ipv6回源域名 |
访问流程可以理解成下面这样:
- 你平时打开
fn.域名.xyz,还是正常用腾讯 EO 访问飞牛控制台。
- 当飞牛前端发起
/multiple-download 请求时,请求先到腾讯 EO。
- 腾讯 EO 边缘函数把当前请求里的
fnos-token 从 Cookie 里取出来,拼进 302 链接参数里跳转链接。
- 浏览器被 302 到
fn-share.域名.xyz。
- 阿里云 ESA 把 URL 里的
sign 重新改写回 cookie: fnos-token=...,再回源到飞牛分享服务端口 5666。
- 因为控制台域名和分享域名不是同一个域,所以阿里云 ESA 还要补一个
Access-Control-Allow-Origin,解决预览时的跨域问题。
适用前提
本文默认你已经完成下面这些基础条件:
- 飞牛 NAS 有公网 IPv6。
- 飞牛 NAS 里
系统设置 -> 远程访问 -> DDNS 已经把 AAAA 记录同步到 fn-ipv6.域名.xyz。
- 腾讯 EO 的
fn.域名.xyz 已经可以正常打开飞牛控制台。
- 域名托管在腾讯云 DNS。
- 你已经准备好一个阿里云 ESA 免费版站点,并且打算让
fn-share.域名.xyz 走阿里云 ESA。
如果你前面的 IPv4 访问链路还没通,那应该先把基础访问打通,再继续做这一篇里的下载分流。
先确认飞牛为什么能这样分流
我这里的结论是:
- 飞牛的文件预览和文件下载,当前版本会用到
/multiple-download 这个接口;
- 这个接口除了
token 参数,还依赖 fnos-token 这个 Cookie;
- 也就是说,单纯把请求 302 到另一个域名还不够,必须把认证信息一起带过去;
- 浏览器不会主动把
fn.域名.xyz 的 Cookie 自动带到 fn-share.域名.xyz,所以要由 EO 取出 fnos-token,再由 ESA 在回源前重新拼回 Cookie。
这个结论是基于我当前版本飞牛的抓包和测试结果,不是飞牛官方对外承诺的固定接口。后续系统更新后,这个接口名、参数和鉴权方式都有可能变化。
第一步:腾讯 EO 里增加边缘函数
EO 这一侧的任务很单纯:拦截 /multiple-download,把请求重定向到阿里云 ESA 的分享域名。
我当前的函数代码如下:
const esaLink = "https://fn-share.域名.xyz"; // 改成你的飞牛分享域名
addEventListener("fetch", (e) => {
e.respondWith(handleRequest(e.request));
});
async function handleRequest(request) {
const url = new URL(request.url);
const cookieHeader = request.headers.get("Cookie") || "";
const cookies = new Cookies(cookieHeader);
const fnosToken = cookies.get("fnos-token")?.value || "";
const token = url.searchParams.get("token") || "";
let refererPath = "";
try {
const referer = request.headers.get("referer");
if (referer) {
refererPath = new URL(referer).pathname;
}
} catch (err) {
refererPath = "";
}
const target = new URL(esaLink);
url.host = target.host;
return Response.redirect(
target.toString() + `multiple-download?token=${token}&sign=${encodeURIComponent(fnosToken)}`,
302
);
}
这个函数的核心动作只有两步:
- 从 Cookie 里取出
fnos-token;
- 把当前下载请求 302 到
fn-share.域名.xyz/multiple-download?...,并把 fnos-token 放到 sign 参数里。
对应的触发条件建议至少满足下面三项:
- 主机名是
fn.域名.xyz;
- 路径是
/multiple-download 或 /multiple-download*;
- 请求方法是
GET。
如果你还发现飞牛某些下载链路会落到 /download,也可以一并纳入下载专用逻辑里处理。
第二步:阿里云 ESA 站点里准备分享域名
阿里云 ESA 这一侧不是拿来跑整个飞牛控制台的,而是只跑下载和预览相关流量。
建议你单独准备一个分享域名,例如:
fn-share.域名.xyz
然后让这个子域名走阿里云 ESA。
这样做的好处有两个:
- 下载流量和控制台流量彻底拆开,问题更好定位;
- 即使后面要加防盗链、封 WebSocket,也只影响分享域名,不会把主控制台一起伤到。
第三步:在阿里云 ESA 里配置回源规则
这一步的目标,是让 fn-share.域名.xyz 的下载请求最终回到家里那台飞牛 NAS,而且走的是飞牛分享服务对应的端口。
我当前 ESA 站点里能看到这条回源规则:

其中最关键的一条,是把 fn-share.域名.xyz 回源到飞牛的 IPv6 DDNS 域名,并指定分享端口 5666。

这里你至少要保证下面这些点是对的:
- 匹配主机名:
fn-share.域名.xyz
- 回源目标:
fn-ipv6.域名.xyz
- 回源协议:
HTTP
- 回源端口:
5666
如果你的飞牛不是跑在 5666,那就把这里改成你自己的实际端口。
第四步:在阿里云 ESA 里把参数还原成 Cookie
前面腾讯 EO 已经把 fnos-token 带到了 URL 参数 sign 里传到阿里云ESA这边。
所以 ESA 这一侧要做的事,就是在请求回源前补一个请求头:
cookie: fnos-token=...
我当前这条规则放在阿里云 ESA 的“转换规则 -> 修改请求头”里:

规则建议这样写:
匹配条件
- 主机名 =
fn-share.域名.xyz
- URI 路径开头为
/multiple-download
- 请求方法 =
GET
修改请求头
- 类型:动态
- 操作方式:添加
- 请求头名称:
cookie
- 请求头值:
concat("fnos-token=",http.request.uri.args["sign"])
它的作用就是把:
?token=xxx&sign=yyy
还原成:
cookie: fnos-token=yyy
这样飞牛后端才会把这次请求认成一个已登录、可下载的有效请求。
第五步:给分享域名补 CORS 响应头
到这里,文件下载通常已经能跑通了,但文件预览还有一个很容易踩的坑:跨域。
原因是:
- 控制台页面开在
fn.域名.xyz;
- 预览和下载被重定向到了
fn-share.域名.xyz;
- 两边已经不是同一个域,所以浏览器会做 CORS 检查。
如果你不补 CORS 响应头,预览时通常就会直接报跨域错误。
我当前的 ESA 规则放在“转换规则 -> 修改响应头”里:

这条规则的核心配置如下:
匹配条件
修改响应头
- 类型:动态
- 操作方式:添加
- 响应头名称:
Access-Control-Allow-Origin
- 响应头值:
regex_replace(
http.request.headers["origin"],
"^(https?)://(?:([^.]+)\\.)?[^.]+\\.[^.]+$",
"${1}://${2}.域名.xyz"
)
这段表达式的意思,是把请求里的 Origin 动态改写成你自己的根域名体系,然后回给浏览器。
注意:⬆️ 这里记得替换成你自己的域名。
关于这条 CORS 规则,我建议你额外注意两点
第六步:在阿里云 ESA 里补两条防护规则 (可选)
因为阿里云 ESA 免费版的 WebSocket 实测并不稳定,写的是免费版不支持WebSocket,实测是支持的但是不稳定(约等于没法用),所以分享域名最好只承接下载和预览,不要给它完整飞牛控制台能力。
我当前把这部分放在“转换规则 -> 自定义响应码”里:

规则一:防止别的网站盗链你的分享域名
我现在的规则如下:

我当前页面里给这条规则返回的是 404,也可以直接返回 403 或 502 随便设置。
如果你只想限制分享域名,而不想把整个根域名下的其他子站一起带上,那么可以把第一段条件收窄成:
http.host eq "fn-share.域名.xyz"
规则二:直接阻断 WebSocket 和无意义入口探测
我现在的规则如下:

返回码我这里用的是 404。
这一条的目标是:
- 明确阻断别人拿分享域名去尝试建 WebSocket;
- 顺手把分享域名根路径和
/s/ 这种无意义入口也拦掉,避免它被当成控制台入口探测。
如果你只想保留最纯粹的“封 WebSocket”,那把后面 "/" 和 "/s/" 这部分删掉也可以。
第七步:确认转换规则总览是否完整
确认三类规则都已经具备:
- 请求头改写:把
sign 变回 fnos-token Cookie;
- 响应头改写:给分享域名补
Access-Control-Allow-Origin;
- 自定义响应码:给分享域名补防盗链和 WebSocket 阻断。
第八步:怎么验证它真的生效了
推荐你按下面的顺序验证:
- 先正常打开
fn.域名.xyz,确认飞牛控制台依旧正常。
- 进入文件管理,找一个明显超过 10 MB 的文件做下载测试。
- 看浏览器网络请求,应该先命中 POST
fn.域名.xyz/multiple-download 返回一个token。
- 随后应该出现一个 302,跳到
fn-share.域名.xyz/multiple-download?sign=...&token=...。
- 页面未显示Bad Request,文件开始正常下载,到文件下载记录里复制下载链接看子域名为分享域名即成功。
- 再测试一次文件预览,确认浏览器控制台不再报 CORS 错。
如果你已经能看到下面这几个结果,就说明方案基本跑通了:
- 飞牛控制台依然走腾讯 EO;
- 文件下载速度明显比原来更好;
- 文件预览不再跨域报错;
- 分享域名本身不提供稳定 WebSocket,从分享域名进入飞牛控制台出现拦截或者不显示登录组件。
常见故障排查
1. 下载能跳转,但页面提示 `Bad Request`
优先检查这三件事:
- 腾讯 EO 边缘函数有没有把
fnos-token 拼进 sign;
- 阿里云 ESA 的请求头规则有没有真的把
sign 改回 cookie;
- 飞牛当前版本是否仍然使用
fnos-token 作为下载鉴权 Cookie。
2. 下载可以,预览不行,而且浏览器报 CORS
基本就是响应头规则没配对:
Access-Control-Allow-Origin 没回出来;
- 回出来的域名不对;
- 你实际打开控制台的域名和表达式里允许的域名不一致。
3. 分享域名直接打开还能看到页面 (不介意可以忽略)
说明你的自定义响应码规则不够严,或者没有命中。
重点检查:
主机名 是否写成了正确的分享域名;
upgrade 判断是否真的命中了 WebSocket;
- 规则顺序是不是被别的规则抢先处理了。
4. 下载还是慢
这时不要先怀疑规则,先看链路是不是还在走腾讯 EO:
- 如果下载 URL 最终还是停留在
fn.域名.xyz,说明 EO 边缘函数没有命中;
- 如果已经 302 到
fn-share.域名.xyz,再去看 ESA 回源是否正确、飞牛是否真的走到了分享端口。
这套方案的风险和边界
这个方案确实能跑,而且我已经在现网里验证过了,但它不是完全没有代价。
1. fnos-token 被放进了 URL
这是整套方案里最大的风险点。
因为 EO 在 302 时把 fnos-token 放进了 sign 参数,所以它理论上会出现在:
- 浏览器地址历史;
- 某些代理日志;
- 某些云侧日志;
- 某些 Referer 链路里。
所以我的建议是:
- 只在专用的分享域名上使用这套逻辑;
- 全程只走 HTTPS;
- 清楚知道这本质上是在“借用当前登录态”完成下载,而不是官方意义上的临时授权下载。
fnos-token在登录状态失效后一同失效。
2. 这依赖飞牛当前版本的接口实现
/multiple-download、token、fnos-token 这些名字,都是当前测试环境里实际观察到的结果。
飞牛一旦改了前端下载逻辑,这篇文章里的规则就要跟着改。
3. 阿里云 ESA 免费版不适合承接完整飞牛控制台
至少在我这里,免费版 WebSocket 的表现是不稳定的。
所以这篇文章的重点从来不是“把飞牛全站切到阿里云 ESA”,而是:
这样才是一个更稳妥的落地方式。
我对这套方案的最终建议
如果你和我一样,已经把飞牛控制台稳定跑在腾讯 EO 上,但又受不了大文件下载速度,那这套分流方式值得试。
它的本质不是“谁更强”,而是把两个平台放到更适合它们的位置上:
- 腾讯 EO 负责飞牛控制台和 WebSocket;
- 阿里云 ESA 负责分享域名、文件下载和文件预览。
这样既保留了日常使用体验,也把下载链路单独优化出来了。
参考文档