背景
肥猫云在四月份以后改用了独立的客户端,取代了订阅模式,导致家里的每个设备都要安装客户端,太麻烦了。
官方推出了openwrt的版本,经过分析后,是一个netflow+mihomo的套壳项目。
概述
肥猫云 Lite 原包 luci-app-fcclient_3.0.7-202605210720_all.ipk 是一个 OpenWrt 路由器上的套壳代理方案,由三个组件叠加而成:
LuCI 管理界面 (Lua)
↕
netflow 后端 (Go binary) ← 套壳层
↕
mihomo (Go binary) ← 代理核心
组件拆解
1. 代理核心:mihomo
版本: Mihomo Meta v1.19.27 (linux arm64, go1.26.4)
负责实际的代理功能。以子进程方式运行,由 netflow 后端启动和管理。
运行参数:
mihomo -d /etc/netflow/mihomo -f <临时配置文件>
-d /etc/netflow/mihomo— 工作目录(geoip/geosite 等数据库所在目录)-f <临时文件>— 配置文件由 netflow 动态生成,存放在/tmp/.nf_*
关键特性:
- 使用 geodata 模式(
geoip.dat+geosite.dat) - 支持 VLESS Reality、Shadowsocks、Trojan 等多种协议
- 自带 RESTful API(外部控制端口 9091)
- TUN 模式支持(但默认关闭)
2. 套壳层:netflow 后端
位置: /usr/bin/netflow → 符号链接到 netflow_aarch64(Go binary,UPX 压缩)
端口: 127.0.0.1:9190
技术: Go 语言,编译为静态链接二进制,UPX 压缩减少体积
职责
| 功能 | 实现方式 |
|---|---|
| 管理 mihomo | 作为父进程启动/停止 mihomo,监控其运行状态 |
| 订阅更新 | 调用 v2board 面板 API 获取节点列表 |
| 配置生成 | 解密订阅数据 → 生成 mihomo 配置文件 → 写入临时文件 |
| 数据加密 | 使用 /etc/netflow/.dev_salt 做 AES 加密 |
| iptables 管理 | 理论上负责设置透明代理规则,但实际未生效 |
配置存储
UCI 配置 (/etc/config/netflow)
├── netflow.config # 基本设置(端口、模式等)
└── netflow.v2board # 订阅登录信息(加密存储)
文件存储
├── /etc/netflow/config.yaml # mihomo 配置文件(或临时文件)
├── /etc/netflow/mihomo/ # mihomo 工作目录
│ ├── mihomo # mihomo 二进制
│ ├── geoip.dat # IP 地理数据库
│ ├── geosite.dat # 域名分类数据库
│ └── config.yaml # 启动后的配置文件
├── /etc/netflow/v2board/
│ └── subscribe.enc # 加密的订阅数据
└── /etc/netflow/.dev_salt # 设备专属加密盐
加密机制
安装时生成 .dev_salt(32 字节随机数 → 64 位 hex)
↓
UCI 中存储的密码/api_url → ENC:base64(AES(salt, 明文))
↓
订阅数据 → subscribe.enc → AES(salt, 节点JSON)
3. 管理界面:LuCI
位置:
- 控制器:
/usr/lib/lua/luci/controller/netflow.lua - 视图:
/usr/lib/lua/luci/view/netflow/main.htm - 权限:
/usr/share/rpcd/acl.d/luci-app-fcclient.json
负责在 OpenWrt 的 Web 管理界面提供操作面板,功能包括:
- 输入/修改订阅账号
- 查看连接状态
- 切换代理模式
- 触发订阅更新
RPC 权限文件定义了后端 API 的访问控制。
数据流
订阅更新流程
用户点击"更新订阅"
↓
LuCI → RPC → netflow 后端 (127.0.0.1:9190)
↓
netflow 解密 UCI 中的 api_url / token
↓
调用 v2board 面板 API → 获取节点列表
↓
AES 加密 → 写入 subscribe.enc
↓
解密 subscribe.enc → 生成 mihomo config.yaml
↓
重启 mihomo 进程
代理数据流
局域网设备
↓ (iptables REDIRECT / TPROXY / 手动设代理)
mihomo (7890 mixed / 7892 redir)
↓ (规则匹配: GEOIP / GEOSITE / DOMAIN-SUFFIX)
代理策略组 (手动 / url-test / fallback)
↓ (VLESS Reality 加密隧道)
节点服务器 (35.78.84.79)
↓
目标网站
v2board API 对接
netflow 后端实现了 v2board 面板的客户端协议:
api/v1/passport/auth/login— 登录获取 tokenapi/v1/user/getSubscribe— 获取订阅元信息api/v1/client/subscribe— 获取实际节点配置
关键设计缺陷
1. iptables 规则未正确配置
prerm 脚本中有 iptables 清理命令,证明 netflow 应该管理透明代理:
iptables -t nat -D PREROUTING -j NETFLOW
iptables -t nat -D PREROUTING -p dport 53 -j REDIRECT --to-ports 7874
但实际运行时 nat 表是空的。可能是:
- netflow 二进制的 UPX 压缩导致这段代码被省略了
- 或者此功能在当前版本已移除
2. 订阅加密导致配置不透明
subscribe.enc 使用设备专属 salt 加密,导致:
- 无法直接查看/修改节点配置
- 无法将订阅数据迁移到另一台设备
- mihomo 的配置文件必须由 netflow 生成,无法直接编辑
3. 节点域名依赖特殊 DNS
节点使用的域名(如 a002-lite01.llguangli25n.com)在公共 DNS 中不存在,只有通过 fcclient App 的 TUN/fake-ip 系统才能解析。路由器上的 mihomo 无法直接解析这些域名。
关键发现
订阅系统分析
- Mac App 使用新 API:
fcapi.apiv2.a047.com/api/v1/passport/auth/login - 路由器 使用旧 v2board API,返回过期节点
- 订阅元数据 API:
user/getSubscribe?auth_data=JWT返回套餐/UUID/订阅地址 - 实际节点配置服务器:
fcsblka.fcsubcn.cc:2096(定制 TLS,无法从外部连接)
找到真实节点 IP
- 通过 Mac 的
netstat观察到所有节点都连接到35.78.84.79 - 路由器 ping 该 IP 可达 (~41ms)
获取jwt token
完整的过程在这里:
# ============================================
# 第1步:登录获取 JWT令牌
# ============================================
curl -X POST "https://fcapi.apiv2.a047.com/api/v1/passport/auth/login" \
-H "User-Agent: fcclient/3.0.7" \
-H "Content-Type: application/json" \
-d '{"email":"xxxxxxxxx@gmail.com","password":"xxxxxxx"}'
# 返回结果:
{
"status": "success",
"data": {
"token": "dW4h1Z87kQQ9vDHrMxxxxxxxxxxxx",
"auth_data": "eyJ0eXAiOiJKV1QiLCJhxxxxxxxxx.eyJpZCI6MTkyOTg3LCJxxxxxxxxxzdmMGVkMGVhM2VkOWZmYWM0ZWU0NjgyZWFiOTI0NjYifQ.7WpSShJZjn2a3IvVxxxxxxxxiC79LMqLnO1xZw"
}
}
# ============================================
# 第2步:获取订阅元信息(套餐/UUID/流量/订阅地址)
# ============================================
# 用上一步返回的 auth_data 作为 query 参数
curl "https://fcapi.apiv2.a047.com/api/v1/user/getSubscribe?auth_data=eyJ0eXAiOiJKV1QixxxxxxxJ9.eyJpZCI6MTkyOTg3LCJzZXNzxxxxxxxxGVkMGVhM2VkOWZmYWM0ZWU0xxxxxx0NjYifQ.7WpSShJZjn2a3IvVxxxxxxxxC79LMqLnO1xZw" \
-H "User-Agent: fcclient/3.0.7"
# 返回结果:
{
"status": "success",
"data": {
"plan_id": 5,
"token": "dW4h1Z87kQQ9vDHrMgzrmDBlGrDIo3Gm",
"expired_at": 1825999987,
"u": 394537826,
"d": 7870981628,
"transfer_enable": 64424509440,
"email": "xxxxxxxxx@gmail.com",
"uuid": "5xxxxx7-cxxx2-4xxe-89xxx7-67dbbxxxx2",
"plan": { "name": "肥猫小包", "id": 5, "transfer_enable": 60 },
"subscribe_url": "https://fcsblka.fcsubcn.cc:2096/api/v1/client/subscribe?token=dW4h1Z87kQQ9vDHrMgzrmDBlGrDIo3Gm",
"reset_day": 24
}
}
最终方案
架构
去掉netflow,直接使用mihomo作为透明代理
局域网设备 → 路由器 (iptables 透明代理) → mihomo → 35.78.84.79 (VLESS Reality 节点) → 外网
配置要点
- 60 个 VLESS Reality 节点 (HK20/TW10/SG10/JP10/US10),全部指向
35.78.84.79 - 策略组: 🚀 节点选择(手动) / 自动选择(url-test) / 故障转移(fallback)
- 规则: .cn/GEOIP 直连,google/github/youtube 走代理,其余兜底代理
- Web 面板:
http://192.168.1.1/yacd/(Yacd-meta),API 密钥netflow_secret
部署的文件
| 文件 | 说明 |
|---|---|
/etc/netflow/mihomo/config.yaml |
mihomo 主配置 (60 节点 + 策略 + 规则) |
/etc/init.d/mihomo |
procd 服务管理脚本 (开机自启 + 崩溃重启) |
/root/tproxy.sh |
iptables 透明代理启停脚本 (start/stop/status) |
/root/watchdog.sh |
看门狗 (cron 每分钟执行,挂了自动重启,重启失败则关 iptables) |
/etc/rc.local |
开机启动 mihomo + 透明代理 |
/www/yacd/ |
Yacd-meta Web 面板 (可通过 http://192.168.1.1/yacd/ 访问) |
命令速查
# mihomo 服务管理
/etc/init.d/mihomo start|stop|restart|status
/etc/init.d/mihomo enable|disable # 开机自启
# 透明代理
/root/tproxy.sh start|stop|status|restart
# 查看日志
logread -e mihomo
cat /tmp/netflow_mihomo.log
# Web 面板
http://192.168.1.1/yacd/ # 连接 192.168.1.1:9091 密钥 netflow_secret
# 添加规则 (sed 免 vi)
sed -i '/DOMAIN-SUFFIX,google.com/i\ - DOMAIN-SUFFIX,baidu.com,DIRECT' /etc/netflow/mihomo/config.yaml
/etc/init.d/mihomo restart
容错机制
| 场景 | 结果 |
|---|---|
| mihomo 崩溃 | procd 自动重启 + 看门狗兜底 |
| mihomo 重启失败 | 看门狗自动关闭 iptables,网络恢复 |
| DNS 失效 | dnsmasq 直接响应,不依赖 mihomo DNS |
待办/风险
35.78.84.79可能是动态 IP,失效后需重新获取- 订阅数据无法直接获取,依赖 Mac 抓包找 IP
- dnsmasq 上游配置
127.0.0.1#7874如需调整
对比:我们最终的路由器方案
| 方面 | 肥猫云原版 | 我们的方案 |
|---|---|---|
| mihomo 管理 | netflow 后端生成临时配置 | 直接编辑固定配置文件 |
| 透明代理 | 依赖 netflow 设置 iptables | 独立 tproxy.sh 脚本管理 TPROXY |
| 规则管理 | 通过订阅数据固定生成 | rule-provider / GEOSITE 自动更新 |
| 设备白名单 | 无内置支持 | TPROXY 按源 IP 限制 |
| 日志管理 | 无独立配置 | procd init 脚本托管 |
| 看门狗 | 无 | cron 脚本监控+自动恢复 |
| 容错 | mihomo 挂了 iptables 还劫持 | 看门狗自动关闭 TPROXY |
| DNS | 无独立防污染 | sniffer + force-dns-mapping |
| Web 面板 | LuCI 界面 | Yacd + external-controller |
评论
评论功能即将上线,敬请期待。