收起左侧

【第2篇】解决腾讯EO的IPV4访问V6 文件下载限速问题

1
回复
82
查看
[ 复制链接 ]

2

主题

6

回帖

0

牛值

🛩️ARM内测用户组

文章如果有费解的地方麻烦留言指出,我将更新贴子方便更多人阅读理解。

阿里云基础版体验地址

这篇文章解决的是一个很具体、也很常见的问题:

  • 家里的飞牛 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回源域名

访问流程可以理解成下面这样:

  1. 你平时打开 fn.域名.xyz,还是正常用腾讯 EO 访问飞牛控制台。
  2. 当飞牛前端发起 /multiple-download 请求时,请求先到腾讯 EO。
  3. 腾讯 EO 边缘函数把当前请求里的 fnos-token 从 Cookie 里取出来,拼进 302 链接参数里跳转链接。
  4. 浏览器被 302 到 fn-share.域名.xyz
  5. 阿里云 ESA 把 URL 里的 sign 重新改写回 cookie: fnos-token=...,再回源到飞牛分享服务端口 5666
  6. 因为控制台域名和分享域名不是同一个域,所以阿里云 ESA 还要补一个 Access-Control-Allow-Origin,解决预览时的跨域问题。

适用前提

本文默认你已经完成下面这些基础条件:

  1. 飞牛 NAS 有公网 IPv6。
  2. 飞牛 NAS 里 系统设置 -> 远程访问 -> DDNS 已经把 AAAA 记录同步到 fn-ipv6.域名.xyz
  3. 腾讯 EO 的 fn.域名.xyz 已经可以正常打开飞牛控制台。
  4. 域名托管在腾讯云 DNS。
  5. 你已经准备好一个阿里云 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 参数里。

对应的触发条件建议至少满足下面三项:

  1. 主机名是 fn.域名.xyz
  2. 路径是 /multiple-download/multiple-download*
  3. 请求方法是 GET

如果你还发现飞牛某些下载链路会落到 /download,也可以一并纳入下载专用逻辑里处理。

第二步:阿里云 ESA 站点里准备分享域名

阿里云 ESA 这一侧不是拿来跑整个飞牛控制台的,而是只跑下载和预览相关流量。

建议你单独准备一个分享域名,例如:

fn-share.域名.xyz

然后让这个子域名走阿里云 ESA。

这样做的好处有两个:

  • 下载流量和控制台流量彻底拆开,问题更好定位;
  • 即使后面要加防盗链、封 WebSocket,也只影响分享域名,不会把主控制台一起伤到。

第三步:在阿里云 ESA 里配置回源规则

这一步的目标,是让 fn-share.域名.xyz 的下载请求最终回到家里那台飞牛 NAS,而且走的是飞牛分享服务对应的端口。

我当前 ESA 站点里能看到这条回源规则:

image.png

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

image.png

这里你至少要保证下面这些点是对的:

  • 匹配主机名:fn-share.域名.xyz
  • 回源目标:fn-ipv6.域名.xyz
  • 回源协议:HTTP
  • 回源端口:5666

如果你的飞牛不是跑在 5666,那就把这里改成你自己的实际端口。

第四步:在阿里云 ESA 里把参数还原成 Cookie

前面腾讯 EO 已经把 fnos-token 带到了 URL 参数 sign 里传到阿里云ESA这边。

所以 ESA 这一侧要做的事,就是在请求回源前补一个请求头:

cookie: fnos-token=...

我当前这条规则放在阿里云 ESA 的“转换规则 -> 修改请求头”里:

image.png

规则建议这样写:

匹配条件

  • 主机名 = 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 规则放在“转换规则 -> 修改响应头”里:

image.png

这条规则的核心配置如下:

匹配条件

  • 主机名 = fn-share.域名.xyz

修改响应头

  • 类型:动态
  • 操作方式:添加
  • 响应头名称:Access-Control-Allow-Origin
  • 响应头值:
regex_replace(
    http.request.headers["origin"],
    "^(https?)://(?:([^.]+)\\.)?[^.]+\\.[^.]+$",
    "${1}://${2}.域名.xyz"
)

这段表达式的意思,是把请求里的 Origin 动态改写成你自己的根域名体系,然后回给浏览器。

注意:⬆️ 这里记得替换成你自己的域名。

关于这条 CORS 规则,我建议你额外注意两点

第六步:在阿里云 ESA 里补两条防护规则 (可选)

因为阿里云 ESA 免费版的 WebSocket 实测并不稳定,写的是免费版不支持WebSocket,实测是支持的但是不稳定(约等于没法用),所以分享域名最好只承接下载和预览,不要给它完整飞牛控制台能力。

我当前把这部分放在“转换规则 -> 自定义响应码”里:

image.png

规则一:防止别的网站盗链你的分享域名

我现在的规则如下:

image.png

我当前页面里给这条规则返回的是 404,也可以直接返回 403502 随便设置。

如果你只想限制分享域名,而不想把整个根域名下的其他子站一起带上,那么可以把第一段条件收窄成:

http.host eq "fn-share.域名.xyz"

规则二:直接阻断 WebSocket 和无意义入口探测

我现在的规则如下:

image.png

返回码我这里用的是 404

这一条的目标是:

  • 明确阻断别人拿分享域名去尝试建 WebSocket;
  • 顺手把分享域名根路径和 /s/ 这种无意义入口也拦掉,避免它被当成控制台入口探测。

如果你只想保留最纯粹的“封 WebSocket”,那把后面 "/""/s/" 这部分删掉也可以。

第七步:确认转换规则总览是否完整

确认三类规则都已经具备:

  1. 请求头改写:把 sign 变回 fnos-token Cookie;
  2. 响应头改写:给分享域名补 Access-Control-Allow-Origin
  3. 自定义响应码:给分享域名补防盗链和 WebSocket 阻断。

第八步:怎么验证它真的生效了

推荐你按下面的顺序验证:

  1. 先正常打开 fn.域名.xyz,确认飞牛控制台依旧正常。
  2. 进入文件管理,找一个明显超过 10 MB 的文件做下载测试。
  3. 看浏览器网络请求,应该先命中 POST fn.域名.xyz/multiple-download 返回一个token。
  4. 随后应该出现一个 302,跳到 fn-share.域名.xyz/multiple-download?sign=...&token=...
  5. 页面未显示Bad Request,文件开始正常下载,到文件下载记录里复制下载链接看子域名为分享域名即成功。
  6. 再测试一次文件预览,确认浏览器控制台不再报 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-downloadtokenfnos-token 这些名字,都是当前测试环境里实际观察到的结果。

飞牛一旦改了前端下载逻辑,这篇文章里的规则就要跟着改。

3. 阿里云 ESA 免费版不适合承接完整飞牛控制台

至少在我这里,免费版 WebSocket 的表现是不稳定的。

所以这篇文章的重点从来不是“把飞牛全站切到阿里云 ESA”,而是:

  • 交互留给腾讯 EO;
  • 下载分给阿里云 ESA。

这样才是一个更稳妥的落地方式。

我对这套方案的最终建议

如果你和我一样,已经把飞牛控制台稳定跑在腾讯 EO 上,但又受不了大文件下载速度,那这套分流方式值得试。

它的本质不是“谁更强”,而是把两个平台放到更适合它们的位置上:

  • 腾讯 EO 负责飞牛控制台和 WebSocket;
  • 阿里云 ESA 负责分享域名、文件下载和文件预览。

这样既保留了日常使用体验,也把下载链路单独优化出来了。

参考文档


收藏
送赞
分享

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x

1

主题

25

回帖

0

牛值

江湖小虾

这个厉害了,没看懂,再看一遍~

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则