@dsh-mobile/pairing
September 1, 2026 · View on GitHub
DSH Mobile 的 Host 插件。正式版可安装在日常 :3080 或 lab :3082 web profile 中;每个 DSH 进程独立提供配对管理、回环 Host Gateway、WebRTC Direct 与加密 Tunnel Fallback。
数据路径
- Host Gateway 只监听回环地址,提供信令和加密 Tunnel 入口。产品 UI 在 APK 里,Gateway 不提供浏览器 Shell。
- Quick Tunnel 或手工配置的 Custom Endpoint 将这个有界 Gateway 暴露为 Public Endpoint。
- GET /pair 铸造五分钟、单次使用的 v4 offer;Android QR 使用 dsh-mobile://pair 深链。
- Automatic 立刻走加密 Tunnel;同网 Direct 只在短宽限内可以抢赢,迟到的 Direct 不得抢走已打开的 Tunnel。
- 首配签发的 Device Token 持续有效,直到 Host 侧撤销。
没有 TURN、运行时 CDN 或维护者域名依赖。Tunnel Fallback 可以走用户自己的 Host Public Endpoint,也可以显式选择官方或自托管的加密 Relay。Relay 只转发密文消息;超过旧单帧上限的 sealed frame 由 Client/Host transport 透明分片和重组。
在 GUI 中配对
打开 设置 → 插件 → 插件配置 → DSH Mobile:
- 展开卡片可查看当前 Public Endpoint 和 Host Identity。
- 二维码只给 Android APK。
- “刷新二维码”会立即铸造新的五分钟单次 offer。
- “打开完整设备管理”还可查看设备、刷新既有设备二维码和执行 Host 侧撤销。
配置位置
正式版安装:
pnpm add github:NOirBRight/dsh-mobile-pairing#v0.1.12
然后把 @dsh-mobile/pairing 加入 profile 的 dsh.profile.bundles。包内的 cordis.patch.yml 会插入 Remote loader;默认配置面向日常 :3080:
- id: dsh-mobile-pairing
config:
dshHost: 127.0.0.1
dshPort: 3080
gatewayBind: 127.0.0.1
gatewayPort: 0
lab profile 使用 :3082 时,将该 profile 的配置覆盖为 dshPort: 3082 和独立的 gatewayPort。产品默认是一台 Host 一个 Gateway(gatewayPort: 0);手机只连接二维码里的 Public Endpoint,不会连到维护者机器。可选的 dsh-pair-mux 只跑在操作者自己的 Host 上回环,后端端口必须由环境变量显式给出。
| 键 | 默认 | 说明 |
|---|---|---|
| appUrl | dsh-mobile://pair | Android QR / Deep Link 入口 |
| endpointMode | quick | GUI 只显示 quick(临时地址)和 relay(Relay);custom 仅作为旧配置兼容模式保留 |
| customEndpointUrl | 无 | 旧 operator overlay 兼容字段;不在当前 GUI 选项中显示 |
| relayUrl | 无 | relay 模式下必填,必须是无凭据的 WSS URL |
| gatewayBind / gatewayPort | 127.0.0.1 / 0 | Host Gateway 始终只允许回环绑定 |
| cloudflaredPath | cloudflared | 默认 Quick Tunnel 可执行文件 |
| quickTunnelCommand / quickTunnelArgs | cloudflared 默认 argv | 可换成 natapp / cpolar / frpc 等能打印 HTTPS URL 的命令 |
| quickTunnelEndpointPattern | trycloudflare.com | 从子进程日志里抽出 HTTPS 端点的正则 |
| stunUrls | [stun:stun.cloudflare.com:3478] | 仅 STUN;TURN/TURNS 会 fail loud |
| dshHost / dshPort | 127.0.0.1 / 3080 | 有界 Gateway 的 DSH 上游;lab 写成 3082 |
| codeTtlMs | 300000 | 首配 offer/code 有效期 |
Quick Tunnel 其它提供者
默认是 cloudflared。下面只是配置样例,不打进 APK,也不作为产品默认依赖。{gateway} 会换成回环 Gateway URL。
# natapp
quickTunnelCommand: natapp
quickTunnelArgs: ['-authtoken', 'YOUR_TOKEN']
quickTunnelEndpointPattern: 'https://[a-z0-9-]+\\.natapp4?\\.cc\\b'
# cpolar
quickTunnelCommand: cpolar
quickTunnelArgs: ['http', '{gateway}']
quickTunnelEndpointPattern: 'https://[a-z0-9-]+\\.cpolar\\.(?:cn|top)\\b'
# frpc(仅旧 operator overlay 兼容;新用户使用 Relay)
quickTunnelCommand: frpc
quickTunnelArgs: ['-c', '/etc/frp/frpc.toml']
quickTunnelEndpointPattern: 'https://mobile\\.example\\.com\\b'
域名与 Relay
- 临时域名:endpointMode: quick 自动生成,不能手工固定。
- 旧 Custom Endpoint:仅为已有 operator overlay 保留兼容,不在当前 GUI 选项中展示;Relay 用户只选择两个预置 Relay 区域。
- Relay:选择 endpointMode: relay 并填写 relayUrl。官方区域和 Docker 自托管部署见 relay/deploy/README.md。每个 Client Instance 使用独立 Room。
- dsh.noirbright.top、dshweb.noirbright.top、dshapp.noirbright.top 等个人域名只能作为个人恢复基础设施,不是产品默认值或依赖。
严禁启动共享同一 DSH_HOME 的第二个 DSH 进程来承载本插件。
维护边界
- 单一来源:本仓库是
@dsh-mobile/pairing的唯一来源;dsh-mobile等下游通过已发布的 tag/tarball 消费,不维护第二份源码镜像。 - 设置图标兼容性:设置导航的远程图标通过临时 DOM patch 替换官方齿轮(官方
settings.section暂无 icon 字段)。这是已接受的临时兼容性限制,Host 导航结构变更时静默回落为默认齿轮,不影响配对与会话功能。
验证
npm test
npm run typecheck
npm run build
npm run verify:packed
npm pack --dry-run
verify:packed 只消费已提交的 fixtures/alpha1/tarballs/*.tgz 和 PROVENANCE.json,校验归档安全性、哈希、清单、导出、入口点与完整依赖闭包(按 npm semver 规则,并保留冲突依赖的嵌套版本),再在空缓存、空 store、无效 registry、隔离 userconfig 和显式 allowlist 环境中安装发布 tarball,冒烟测试 Host Webserver、Connection、Pairing 的根入口及其 ModuleLoader 客户端入口;捕获缺失导出与未声明的运行时依赖,无需联网或源码 node_modules,临时目录清理不跟随符号链接且不覆盖首个错误。PROVENANCE.json 同时绑定干净 alpha.1/e2e 来源证据与最终 0.1.12 root tarball 的 SHA-256/SHA-512。
Release installation (Latest)
Host pairing gateway, QR/device management, WebRTC Direct, and encrypted tunnel fallback. The release artifact targets DeepSeek Harness 0.1.2-alpha.1 and contains built Host/Client files only; it has no sibling-repository source, workstation path, link:, or workspace: dependency.
Latest installation (the URL never contains a version):
dsh plugin --profile web add --force \
https://github.com/NOirBRight/dsh-mobile-pairing/releases/latest/download/dsh-mobile-pairing.tgz
Fixed-version installation:
dsh plugin --profile web add --force \
https://github.com/NOirBRight/dsh-mobile-pairing/releases/download/v0.1.12/dsh-mobile-pairing.tgz
Update, uninstall, and verify:
# Update to the latest Release
dsh plugin --profile web add --force \
https://github.com/NOirBRight/dsh-mobile-pairing/releases/latest/download/dsh-mobile-pairing.tgz
# Verify the loaded version
dsh plugin --profile web list
dsh plugin --profile web doctor
# Uninstall only this plugin
dsh plugin --profile web remove @dsh-mobile/pairing
Configuration: use the plugin section in Settings for Web UI plugins, or the profile dsh.profile.bundles entry for Host-only plugins. Start with this README's minimal YAML/JSON example and provide credentials/backend addresses explicitly.
Rollback: rerun the fixed v0.1.12 command, verify the profile list, then restart the Web service once. Inspect journalctl --user -u dsh-web.service and dsh plugin --profile web doctor; never put a source checkout in the production profile.
Release and integrity: v0.1.12 · SHA256SUMS.