Loading
XUEAYI_SPACE
0%
INITIALIZING
飞牛 fnConnect 逆向实录:让 Docker Emby 走官方中转的完整过程
DOC_ID // 3f06beONLINE

飞牛 fnConnect 逆向实录:让 Docker Emby 走官方中转的完整过程

2026-10-5
知行合一
1630 CHARS
#FNOS#EMBY#FNCONNECT
XUEAYI_SPACE

背景

家里人在外地,想通过飞牛(fnOS)的 fnConnect 中转远程看 Emby。问题在于:fnConnect 只代理"应用商店安装的应用",我自己 docker 跑的 Emby(18096 端口,挂着刮削代理和番剧库)没有桌面图标、也没有中转通道。目标很明确:不重新部署、保留全部 docker 环境变量,让家人登录飞牛 Web 桌面就能点开 Emby。

一、fnConnect 是怎么代理应用流量的(第一手逆向)

全部结论来自对自建 NAS(fnOS 1.2.0701)的实查,非二手资料:
  • 进程三件套:trim-connect(主服务)+ pxy(常驻出站隧道,连中转服务器 43.226.56.35:7202)+ trim_open_gateway。开启 fnConnect 后系统自动签发 Let's Encrypt 证书(CN=用户名.5ddd.com)并配置泛解析。
  • 中转层没有通用端口转发:中转服务器上一票端口 TCP 握手都通、但 TLS/HTTP 全部无响应——它们只讲 pxy 的私有隧道协议。浏览器唯一入口是 443,按 SNI 分流。
  • 端口型应用走三级子域名:nginx 访问日志里抓到远程用户实际访问的是 openlist.xueayi.5ddd.com(<应用名小写>.<FN ID>.<中转域名>)。OpenList 自己的日志证实中转链路把远程用户真实 IP 透传了进来,头一两次 403(未授权提示页 /trimfn/apperror)之后就正常了。
  • 路径型应用走主域:影视是 https://xueayi.5ddd.com/v/...,由 nginx 静态 location 反代(配置里只有一个 server 块、零动态上游,vhost 分流完全不经过 nginx)。
  • 映射的源头是应用注册:trim-connect 与系统服务总线(/run/trim_app_cgi/netsvr)之间有常驻 RPC,"哪个子域名转到哪个端口"完全由应用中心注册数据决定。随机编一个子域名,403 页面与 emby 的逐字节相同——查不到注册就没有拨号目标。

二、注册体系的三张表

  • appcenter 库(PostgreSQL):app(身份/service_url 模板)、app_service(http://${host}:${port}/ 这类入口)、app_open(桌面打开方式)。
  • trim_sac 库 entry 表:桌面图标注册,is_admin 字段就是 GUI 里那个"仅管理员/所有用户"开关。
  • 有趣的发现:OpenList 的端口存在 app_env 表里且是混淆值(env.obfuscate=true),而 qBittorrent 等是直接把端口写死在 url 模板里。
  • 死胡同:entry.fn_connect_allow_proxy 全系统只有 trim_sac 引用,trim-connect 根本不读它——网上猜的"翻这个开关就能让 docker 走中转"是错的。

三、失败尝试一:直接插库伪造注册

模仿 OpenList 往三张表插行指向 18096,外加图标文件和 /var/apps/Emby 目录。结果:桌面图标出现了,但 emby.xueayi.5ddd.com 依旧 403。结论:子域映射由应用中心服务运行时经 RPC 下发并带包校验,裸 DB 行骗得过桌面、骗不过 trim-connect。已完整回滚(顺带踩了 PostgreSQL desc 保留字和 heredoc 吃掉 ${host} 两个小坑)。

四、失败尝试二:官方 fnpack 打"壳应用"

按官方开发者文档用 fnpack 1.2.3 打了一个不含服务程序的壳包(manifest 声明 service_port=18096,生命周期脚本全是 no-op,status 只探测 127.0.0.1:18096)。打包成功,但安装后桌面无图标——安装链上的初始化校验没有走通。这条路理论上是正路(不重部署、纯注册),但调试成本超出收益,先放弃。

五、成功方案:应用中心原生 Emby + 数据移植

应用商店里的 Emby(EmbyServer4-9,v4.9.42)是原生包(is_docker=f,直接跑二进制),没有 compose 也就没有环境变量——但数据完全可以搬过来:
  1. 迁移:cmd/main stop 后,把 docker 的 /config(722MB,剔除可再生的 cache 和转码临时目录)整体复制到原生应用的 programdata(/var/apps/EmbyServer4-9/var),chown 给应用用户 EmbyServer(uid 980)。全新初始化的空库改名 var.fresh-bak 留底。
  1. 单独代理:原生应用没有独立 systemd 单元(挂在 trim_app_center.service 下),注入点是它自己的 cmd/service-setup——在 SERVICE_COMMAND= 前插入三行 export HTTP_PROXY/HTTPS_PROXY/NO_PROXY(从 docker 容器原样照抄)。Emby 是 .NET 程序,认这套变量,日志里 mb3admin/GitHub 请求 200 实锤生效。只作用于这一个进程。
  1. 媒体授权:原生应用跑在 uid 980 下,而媒体目录是 911:911 的 700 权限、/vol1/1000 整个是 0000——docker 时代靠 root 才没事。必须在 GUI 的"授权目录"里把媒体目录授权给应用(fnOS 会沿路径打 ACL)。另外在根目录建了 /anime → /vol1/1000/anime_HC550 软链,库里存的原容器路径原样可用。
  1. 一个假故障:迁移后 GUI 报"启动失败",实际服务一直活着——是进程号文件在迁移中变成空文件,导致状态检查误判"未运行",再点启动就撞上 8096 端口占用。清干净重启一次即愈。

六、收尾

  • 旧 docker 容器已删(镜像保留 760MB),compose 和完整 docker inspect 快照留在 /vol1/1000/docker_HC550/emby/,随时 docker compose up -d 回滚;
  • frpc 隧道 emby 目标从 18096 改 8096(frpc.sh off + add),emby.cn.xueayi.site 验证 302 全链路通;
  • Sun-Panel 两张导航卡(公网直连域和局域网地址)同步切到 8096。

七、备忘

  • 应用升级会重写 cmd/service-setup,代理三行会被冲掉——需要在 SERVICE_COMMAND= 前重新注入(脚本里留了 fnconnect-migration 注释标记方便检索)。
  • fnConnect 中转按会员带宽走(40Mbps),家人日常看片没问题;自己的重度使用仍然走 frp 直连线路更宽。
  • "只有 Emby 走代理"是个误会:fnConnect 本来就是按需的入站通道,没人远程访问就是零流量,NAS 的出站流量(刮削/下载/局域网播放)从不经过它;再把不想暴露的应用设成"仅管理员"即可。
脚本与中间产物见:fnos-emby-migration(Gitea)。
NAVIGATION // Related Articles
Loading...