Files
op-packages/luci-app-homeproxy-pro/README.md
T

114 lines
9.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<div align="center">
# luci-app-homeproxy-pro
**The modern ImmortalWrt proxy platform for ARM64 / AMD64**
基于 sing-box 1.14 内核的现代代理平台 — 简洁、高效、开箱即用。
</div>
## 项目定位
本项目是试验性产品,对 [homeproxy-pro](https://github.com/szwjp/luci-app-homeproxy-pro) 架构重构版:以 sing-box **1.14** 内核为唯一目标,
充分利用 1.14 引入的新特性,不再兼容 1.13 及更早内核。
## 运行要求
- **ImmortalWrt ≥ 25.12**(`apk` 或 `opkg` 均可安装)。
- sing-box ≥ 1.14.0 是硬要求;低于 1.14 时服务拒绝启动并记录明确日志。
## 与上游 szwjp/luci-app-homeproxy-pro 对比
### 代码组织
| 维度 | upstream 形态 | pro 形态 | 证据 |
|---|---|---|---|
| 后端架构 | 单文件巨型(`generate_client.uc` 1217 行 / 40 KB;`parse_uri.uc` ~400 行 / 15 KB) | orchestrator + 5 子层(`parser` / `config` / `generator` / `subscription` / `runtime`)+ 公共库(`homeproxy-pro.uc` / `firewall_utils.uc`)+ table-driven adapters | `root/etc/homeproxy-pro/scripts/{config,parser,generator,subscription,runtime}/` |
| 前端架构 | 单一 66 KB `client.js` | `client.js` thin 入口 + 8 个 Tab 模块(`access` / `common` / `dns` / `nodes` / `routing` / `subscription` / `tun_dns` / `udp_nat`)+ 共享 helpers + 集中 `RPC.declare` | `htdocs/luci-static/resources/view/homeproxy-pro/client/` |
| 协议建模 | 单 `parse_uri.uc` 内 13 个 scheme 分支 | `parser/{uri,flatten,normalize,mapping,protocols,validator}.uc` 6 个文件 + canonical Node 模型 + adapter table | `root/etc/homeproxy-pro/scripts/parser/` + `config/{model,adapter}.uc` |
| Tab 模块化 | 1 个 `client.js` 含 12 个 Tab 渲染 | `homeproxy-pro.js` (1161 行 helpers) + 4 顶层 view + 8 个 `client/*.js`;helpers 集中 RPC / MD5 / validators / statusPoller / renderSectionAdd / uploadCertificate | `view/homeproxy-pro/client/{routing,nodes,dns,access,subscription,udp_nat,tun_dns,common}.js` |
### 稳定性
| 维度 | upstream 形态 | pro 形态 | 证据 |
|---|---|---|---|
| reload 事务 | 写完直接 restart | 生成 → `sing-box check` → 新实例 probe → 健康门(连续采样)→ 提为 known-good;不健康自动回滚 | `root/etc/init.d/homeproxy-pro` + `runtime/{config,health}.sh` |
| 健康门 | `ubus` + `pgrep` 简单轮询 | `hp_wait_service` 连续 N 次采样(默认 3/30s)+ `netstat -p` 端口归属校验;不健康自动 rollback | `runtime/health.sh:hp_wait_service` |
| UCI 1.14 迁移 | r10/r11 自述较弱 | `migrate_config.uc` 36 checks 覆盖 1.14 DNS renames / `dns_server.address` 拆分 / `rcode://` → predefined rule / `rule_set_ipcidr_match_source` rename / `block-out`/`block-dns` → `action='reject'` / `auto_firewall` 重分发 / `block-dns` default-server | `scripts/migrate_config.uc` + `tests/ucode/test_migrate_config.sh` |
| sing-box 版本门 | 无 | `hp_require_singbox()` 在 start 时显式拒绝 `<1.14`,启动失败记录明确日志 | `runtime/service.sh:hp_require_singbox` |
### 安全
| 维度 | upstream 形态 | pro 形态 | 证据 |
|---|---|---|---|
| capabilities | `CAP_SYS_PTRACE` + `CAP_NET_RAW` + `CAP_NET_ADMIN` + `CAP_NET_BIND_SERVICE`(4 个) | 仅 `CAP_NET_ADMIN` + `CAP_NET_BIND_SERVICE`(2 个) | `root/etc/capabilities/homeproxy-pro.json` + arch-guard guard 12 |
| 路径白名单(cert / rule) | 仅前端 UI 校验 | `validateHomeProxyPath()` 拒 traversal + relative,限 `/etc/homeproxy-pro/` 与 `/tmp/homeproxy_*`;`validateCertificatePath()` 限 `/etc/homeproxy-pro/certs/` `/etc/acme/` `/etc/ssl/`;前后端列表 arch-guard 29 锁同步 | `homeproxy-pro.uc:56 / :104` + `homeproxy-pro.js:HP_CERT_PATH_ROOTS` |
| 订阅 token 脱敏 | 调用点各自脱敏 | `wGETVerbose()` 内部脱敏(scheme/host/port 保留,userinfo / path / query 全脱;mock 与生产 `redactUrl` 由 arch-guard 35 锁一致) | `homeproxy-pro.uc:226 (redactUrl)` + arch-guard 14 / 35 |
| crontab 权限 | `sed -i`(GNU-only)+ mv 后留给 0644 | `sed + mv` 跨 busybox / GNU / BSD + `chmod 600` 修 root crontab 0644 → 0600 | `runtime/service.sh:hp_crontab_drop` |
| procd jail mount | 默认未对所有模式 mount | tun/wireguard 自动 unjail(要 host netns),其他模式 mount HP_DIR + /etc/acme + /etc/ssl + /tmp/dhcp.leases + /etc/localtime + /etc/TZ | `runtime/service.sh:hp_procd_client_instance` |
| cert upload 并发 | 4 个按钮共用 `/tmp/homeproxy_certificate.tmp` | 4 个按钮各自 `/tmp/homeproxy_cert_<name>.tmp`,ACL 显式列 4 个写路径 | `homeproxy-pro.js:uploadCertificate` + `acl.d/luci-app-homeproxy-pro.json` |
| firewall 字段白名单 | 部分值校验 | `firewall_pre.uc` `tun_name` 严格 `^[A-Za-z0-9_.-]{1,15}$` 防 nft 注入;`firewall_post.ut` 每个 UCI 派生值走 `*_to_nftarr()` 校验器(guard 11 锁模板全覆盖) | `firewall_pre.uc:32` + `firewall_utils.uc` |
### 测试 / CI
| 维度 | upstream 形态 | pro 形态 | 证据 |
|---|---|---|---|
| 架构守卫 | 无 | `tests/arch-guard.sh` **47 个 guard / 164 个 check** 锁跨文件一致性(UCICONFIG_DIR / ACL / capabilities / conffiles / CERT_PATH_ROOTS / `redactUrl` mock / uCode 语法 / sing-box floor / adapter 共享表 / …) | `tests/arch-guard.sh` (guards 1-49,编号跳过 20 与 44) |
| 测试规模 | 7 个脚本 / 约 27 个 check | `tests/` 下 82 个文件:ucode 套件 + 8 个 frontend 验证器 + golden snapshot + mocks + 离线 runtime 测试;arch-guard 单跑 164 个 check | `tests/print-stats.sh` 实测 |
| CI | `build` + `i18n` 两条平行 workflow | `build` 用 `workflow_call` 依赖 `arch-test`;`arch-test` 8 步(翻译 fast gate → toolchain cache → toolchain 校验 → `tests/run.sh` 唯一套件入口 → 模板检查);`on-target` 手动 ssh + 不安装 | `.github/workflows/{arch-test,build,on-target}.yml` |
| uCode dialect pin | 跟随 upstream HEAD(已放宽) | pin `UCODE_REV=85922056ef7abeace3cca3ab28bc1ac2d88e31b1`(完整 40 位 commit)+ `test_ucode_grammar.sh` canary 锁 strict 语法(拒 `export function … }` 无 `;`、对象/数组解构) | `tests/toolchain/build-ucode-linux.sh:UCODE_REV` + `tests/ucode/test_ucode_grammar.sh` |
| MD5 实现 | 388 行 minified snippet;vmess 分支漏 `vmess_global_padding` | RFC 1321 完整实现 + `tests/frontend-md5.js` 锁 RFC 向量 + 与 Node `crypto.createHash('md5')` 双向 cross-check(44 / 44 PASS) | `homeproxy-pro.js:calcStringMD5` + `tests/frontend-md5.js` |
### UX / Ops
| 维度 | upstream 形态 | pro 形态 | 证据 |
|---|---|---|---|
| Status 语义 | 2 态(RUNNING / NOT RUNNING) | 3 态(+ **STATUS UNKNOWN** 黄),区分 "rpc 没回" vs "service 死了" | `homeproxy-pro.js:statusLabel` + `client.js:renderStatus` |
| 前端特异性 bug 修复 | `stubValidator` 缺 `factory` 致 ip6addr TypeError;`L.bind(hp.renderSectionAdd, …)` 把 factory 塞 `extra_class` 槽致 `InvalidCharacterError` | 已修:`stubValidator` 持 `factory: validation`;`renderSectionAdd` 改薄 wrap(arch-guard 22 / 23 锁 binding 形态) | `view/homeproxy-pro/client.js:73` + `homeproxy-pro.js:1018-1026` |
| 协议增改成本 | 改 110 行 ternary(README 旧行) | 改 5 个表行:`model.uc CREDENTIALS` + `loader.uc PROTOCOL_OPTIONS` + `adapter.uc OPTION_FIELDS` + `fixtures/` + golden snapshot;arch-guard 5 强制 fixtures 同步 | `config/{model,loader,adapter}.uc` + `tests/fixtures/generators/` |
| 资源更新 | jsdelivr 单一镜像 | 4 镜像 fallback(`fastly.jsdelivr.net` / `gcore.jsdelivr.net` / `cdn.jsdelivr.net` / `raw.githubusercontent.com`)+ UI「上次成功时间」(arch-guard 17 / 18 锁) | `runtime/dns.sh` + arch-guard 17 / 18 |
| ECH 上传 | 后端 case 缺失 | 补齐 `client_ech_conf` 标签 + `isValidECHConfig()` PEM 校验;ACL 显式列 4 个 tmp 路径 | `homeproxy-pro.uc:isValidECHConfig` + `luci.homeproxy-pro:certificate_write` |
**一句话总结**:pro 的核心价值是**把"单文件能跑"变成"orchestrator + table-driven adapter + 可独立测试的模块"**,并把约束、质量、回滚三件事从靠人盯变成靠代码执行(arch-guard 164 checks 静态锁住跨文件不变量)。
## 自编译(OpenWrt buildroot)
```sh
make menuconfig
```
勾选 **luci-app-homeproxy-pro**,以及 **LuCI → Translations → 简体中文 (zh_Hans)**。
后者不勾的话翻译包不会构建,且不报错,只在日志里留一行
`WARNING: skipping luci-i18n-homeproxy-pro-zh-cn -- package not selected`。
```sh
make package/luci-app-homeproxy-pro/compile V=s -j1
ls bin/packages/<target>/<subtarget>/base/ | grep -i homeproxy-pro
```
应同时得到两个包:
```
luci-app-homeproxy-pro-28.10.1.14-r37.apk
luci-i18n-homeproxy-pro-zh-cn-28.10.1.14-r37.apk
```
本包不编译 sing-box,固件须自带 1.14+,否则依赖解析失败。
## 已知限制
- **试验性**:不承诺 API/配置稳定,重大变更可能在 minor 版本里发生。
- **真机实测单平台**:本仓库只在 x86-64 软路由上做过端到端验证。
- 本包不会编译 sing-box。系统固件必须自带 sing-box 1.14+;否则依赖解析直接失败。
## 贡献
欢迎 issue / PR。架构边界规则是可执行的,固化在 `tests/arch-guard.sh`(PR 必跑,
每条规则都注明对应的 guard);架构层面的变更请先开 issue 讨论,避免在
PR review 里来回拉扯。
## License
[GPL-2.0-only](LICENSE) — 版权归 ImmortalWrt.org 与各贡献者。