88f2ff44aa8dea7ccb1ab03c8b7254f7ac4646a8
设备把自己当 USB 网卡挂给上游主机时会出现 usb0(驱动 configfs-gadget.g1, IP 192.168.68.1)。该链路只通向 PC,被当成出口后所有出站都 context deadline exceeded,客户端看到 socks connect failed rep=0x01。 误选原因:score_iface_as_cellular 给 usb0 与真出口 wwan0 都打 175 分。 usb0 靠名称命中 patterns 里的 usb(+80)与非默认路由(+40);wwan0 的 bam-dmux 驱动不在白名单里,白丢 +100。detect_cellular_iface 用 -gt 比较, list_ifaces 按名排序让 usb0 先入选,平分下无法被顶替。 改动: - lib.sh 新增 iface_is_usb_gadget(),按驱动名与 gadget 总线路径识别, 并并入 is_virtual_or_skip_iface(usb0 评分 175 -> 0) - 驱动白名单补 bam-dmux/bam_dmux/qcom-ipa/ipa_wan;名称权重 80 -> 40, 确保驱动证据始终压过名称猜测 - 新增 detect_cellular_iface_via_mm(),把 ModemManager bearer 的 interface: 作为第 0 步权威来源 - detect_cellular_iface / resolve_cellular 全链路拒绝 gadget 网卡, 取不到真出口时按 REQUIRE_CELLULAR_IFACE 直接失败而不是绑错 - generate/install/upgrade/watch/detect/verify 各入口独立设闸, verify.sh 发现出口是 gadget 时直接 exit 4 并给出修复命令 - 默认 CELLULAR_IFACE_PATTERNS 去掉 usb/enx;upgrade.sh 与根 install.sh 就地迁移已有 settings.conf,旧机器升级即修复 - 新增 tests/detect-gadget.sh:18 条离线断言,无需真机
cellular-proxy
轻量 「走代理 = 走数据流量」(无 frp,512MB 友好)。
语义
| 流量 | 出口 |
|---|---|
| 不走 本代理 | 系统默认(通常 WiFi) |
| 走 本代理 | 一律数据网卡(自动探测并 bind) |
★ 一条命令(安装 / 升级通用)
curl -fsSL 'https://gitea.chickliu.fun/Hermes/cellular-proxy/raw/branch/main/install.sh' | sudo bash
| 机器状态 | 行为 |
|---|---|
| 未安装 | 全量安装:探测网卡 → 下 sing-box → 启动 → 验证 |
| 已安装 | 增量升级:保留密钥/网卡/账密,更新 UI/scripts,默认不重下二进制 |
不需要记 --upgrade / --install,同一条命令反复执行即可。
可选覆盖(首次安装常用):
curl -fsSL 'https://gitea.chickliu.fun/Hermes/cellular-proxy/raw/branch/main/install.sh' | sudo bash -s -- \
--iface wwan0 \
--secret '面板密钥' \
--user proxy \
--pass '代理密码'
| 选项 | 说明 |
|---|---|
| (无参数) | 自动:未装→安装,已装→升级 |
--force-install |
已装也强制全量安装 |
--force-binary |
升级时强制重下 sing-box |
--ui-only |
只更新 9090 面板 |
--rebind |
升级时重新探测数据网卡 |
--verify |
升级后做出口验证(升级默认跳过) |
--iface |
强制指定数据网卡 |
--secret |
面板密钥(默认随机;升级不改已有) |
--user / --pass |
代理鉴权 |
--port / --panel-port |
默认 7890 / 9090 |
--memory |
MemoryMax MB,默认 96 |
--skip-start / --skip-verify |
跳过启动或验证 |
已装后的快捷方式
装过一次后也可用:
sudo cpxy upgrade # 等同再跑上面那条 curl(增量)
sudo cpxy upgrade --ui-only
sudo cpxy upgrade --force-binary
sudo cpxy upgrade --verify
| 保留 | 默认跳过 | 会更新 |
|---|---|---|
settings.conf / PANEL_SECRET / 代理账密 |
重下 sing-box(已存在则复用) | UI 面板 |
CELLULAR_IFACE 绑定 |
重新探测网卡 | scripts / cpxy / systemd |
| 端口与 MemoryMax | 出口公网验证 | 重生 config.json 并 restart |
常用运维:
cpxy verify
cpxy rebind
cpxy status | logs
cpxy auth --user u --pass p
cpxy auth --show | --clear
cpxy watch status # WWAN 自动监控
cpxy watch once # 手动跑一轮检查
重拨 / rep=0x01 自愈
| 层级 | 做法 |
|---|---|
| 绑定(推荐) | 默认 BIND_SOURCE_IP=false:只 bind_interface=wwanX,不 pin 私网源 IP,重拨换地址通常不用 regenerate |
| 监控 | cellular-proxy-watch:ip monitor + ModemManager 重拨/重注册日志 + 60s 轮询;网卡改名/掉线/stale pin 或 MM 抖动后自动等数据面再 generate |
| MM 标准(省流量) | 默认 WATCH_MM_EVENTS=true:只读本机 journalctl -u ModemManager,不做公网探针;命中 registration/packet service 等状态变化后 settle→等 IPv4→restart |
| 兜底 timer | 每 2 分钟 oneshot 再检查一次 |
| 手动 | cpxy rebind && cpxy verify |
关监控:ENABLE_CELLULAR_WATCH=false 后 cpxy upgrade,或 cpxy watch stop。
若必须 pin 源 IP:BIND_SOURCE_IP=true(依赖 watch 同步,否则会再次 stale)。
- 代理:
LAN-IP:7890(HTTP + SOCKS5) - 面板:
http://LAN-IP:9090/ui/(密钥在安装结束输出 /settings.conf) - UI 可直接配置代理账号密码(管理 API 默认
9091,与面板 secret 相同)
自动探测逻辑(摘要)
顺序如下,前一步命中即返回:
- ModemManager bearer(
mmcli -b报的interface:)—— 最权威,优先采用 - 驱动像蜂窝/USB 拨号:
qmi_wwan、cdc_mbim、cdc_ether、rndis_host、bam-dmux、rmnet*等(+100) - 名称含
wwan/wwp/ppp/rmnet/ccmni…(+40,弱启发式) - 不是 系统默认路由网卡(默认通常是 WiFi)
- 多默认路由时取次要默认口
- 回退:任意非默认且有 IPv4 的物理网卡
探测失败会直接报错并提示用 --iface。
绝不绑定 USB gadget 网卡
设备把自己当 USB 网卡挂给上游主机时会出现 usb0 / rndis0(驱动 configfs-gadget、
g_ether 等)。那是「本机 → PC」的下行链路,一旦被当成代理出口,所有出站都会
context deadline exceeded,SOCKS5 客户端看到的就是 socks connect failed rep=0x01。
因此:
iface_is_usb_gadget()按驱动名与 gadget 总线路径识别这类接口,打分阶段直接跳过;- 默认探测关键词不再包含
usb/enx,升级时会自动从已有settings.conf里剔除; - 即使手工把
CELLULAR_IFACE=usb0写进配置或用--iface usb0,detect/generate/install/upgrade/watch都会拒绝并改用 ModemManager 的结果; - 真正的 USB 上行模组(
rndis_host、cdc_*、qmi_wwan)是 host 侧驱动,不受影响。
回归测试(不需要真机,纯离线,覆盖 18 条断言):
bash tests/detect-gadget.sh
手动安装
git clone https://gitea.chickliu.fun/Hermes/cellular-proxy.git
cd cellular-proxy
sudo ./scripts/install.sh # 同样会自动探测并绑定
资源
- 单进程 sing-box
- 中文静态面板(animal-island-ui 视觉 token,单文件无 React)
- 默认
MemoryMax=96MB
二进制从哪里下?
优先 Gitea Release 预置包(一键安装默认走 Gitea,无需访问 GitHub):
https://gitea.chickliu.fun/Hermes/cellular-proxy/releases/download/bin-v1.11.7/sing-box-1.11.7-linux-amd64.tar.gz
https://gitea.chickliu.fun/Hermes/cellular-proxy/releases/download/bin-v1.11.7/sing-box-1.11.7-linux-arm64.tar.gz
https://gitea.chickliu.fun/Hermes/cellular-proxy/releases/download/bin-v1.11.7/sing-box-1.11.7-linux-armv7.tar.gz
下载顺序:Gitea 整包 → Gitea 分片合并(兜底) → GitHub 代理(https://git.86482425.xyz) → 直连 GitHub。
代理账号密码
| 方式 | 命令 / 入口 |
|---|---|
| UI | http://LAN-IP:9090/ui/ → 面板 secret → 代理账号密码 |
| CLI | sudo cpxy auth --user u --pass p |
| 安装时 | --user / --pass |
管理 API:POST http://LAN-IP:9091/proxy-auth,Header Authorization: Bearer $PANEL_SECRET。