Repository navigation
Releases: Zoragyx/dsh-phone-pair
Release list
DSH 手机版 · 配对版 1.0.3(支持局域网 http 配对)
DSH 手机版 · 配对版 1.0.3 —— 局域网 http 配对(推翻 1.0.2 的一个判断)
1.0.2 的说明里写着「局域网 http 仍然有意不支持」。这一版把它改了,因为那个判断站不住:
- 上游
@linxin666/dsh-remote-web-ui本来就支持局域网 http。它签发的设备 Cookie 只在走 TLS 时才加Secure,源码注释写得很直白:LAN pairing runs on plain HTTP, where a Secure cookie is simply dropped by the browser and the phone would silently lose its session. —— 也就是说"电脑走 http、手机走 https"这套组合从头到尾只有我们这一侧在挡。 - 后果是真实用户整条路走不通:一位测试员的电脑绑在
0.0.0.0,面板给的是http://100.68.26.79:19387/pair-accept?pair=…(Tailscale 地址)。1.0.2 只会回一句「需要完整的配对链接」,他无论怎么复制都配不上。 - 我们当时的顾虑(打开 cleartext 明文流量会放宽信任边界)是对的,但解法不该是"要求所有人改用公网 https",而是只放行内网地址。这一版就是这么做的。
修了什么
| 现象 | 1.0.2 | 1.0.3 |
|---|---|---|
面板切到「局域网地址」,粘 http://192.168.1.5:19387/pair-accept?pair=… |
拒绝(只认 https://) |
接受,直接配对 |
Tailscale 用户(http://100.68.x.x:19387/…) |
拒绝,全流程走不通 | 接受(100.64.0.0/10 是 CGNAT 私网段) |
http:// + 公网域名 |
拒绝 | 仍然拒绝,提示改用 https / 面板的「公网地址」 |
放行范围写死在 PairLinks.isPrivateHost():10. / 172.16-31. / 192.168. / 169.254. / 100.64-127. / 127.、*.local / .lan / .home / .internal / .ts.net、以及单段主机名(mDNS/NetBIOS,如 desktop、my-pc.local)。
配套改动
- Cookie 的
Secure标志按 scheme 决定:https 加; secure,http 不加。不这样改,WebView 会直接丢弃这条 Cookie,表现为「配对成功、一刷新就掉线」。 - 内置资源拦截(85 个客户端 bundle / 28.2 MB)从"仅 https 同源"放宽为"http 或 https,但 host 必须等于已配对主机"。
AndroidManifest.xml打开usesCleartextTraffic(Android 默认禁止明文),但真正的门在代码里:只有内网地址的 http 链接能通过解析,WebView 的导航仍被shouldOverrideUrlLoading限制在已配对主机上,公网 http 站点进不来。- 配对链接的 intent-filter 增加
httpscheme:点开局域网链接也能直接进 App。 - 配对浮层引导文案写清"两种链接都能用",
关于页版本号改 1.0.3。
顺手补的文档
- 新增
tester-troubleshooting.md(测试员版排查步骤,可直接转给测试员):先看版本 → 再看面板顶部状态 → 同一网络直接走局域网 → 想走公网才去修中继红字 → 浏览器"无法保存确认状态"怎么办 → 还不行要提供哪 5 项信息。 - 工程树与发布树的 README「常见问题」表、插件 README「排错」表同步改成 1.0.3 的说法(局域网 http 从"不支持"改为"支持,仅限内网地址")。
怎么升级
- 下载本页的
DSH-Phone-Pair-1.0.3.apk,直接覆盖安装(与 1.0.0 / 1.0.1 / 1.0.2 同一把签名 key,不必先卸载,数据保留); - 电脑上打开「远程访问」面板 → 选网络(同一网络用「局域网地址」,在外网用「公网地址」)→ 点『复制链接』 → 发到手机 → 在 App 的配对页粘贴;
- 在 App「设置 / 帮助 → 关于」里看到
DSH 手机版 · 配对版 1.0.3就装对了。
走局域网地址的前提是手机和电脑在同一个网络(同一个 Wi-Fi,或都在同一个 Tailscale 网络里)。公网地址则要求电脑侧的中继是正常的(面板顶部显示「固定域名:正常」)。
校验
| 项 | 值 |
|---|---|
| 文件 | DSH-Phone-Pair-1.0.3.apk |
| 大小 | 12,373,348 字节(约 11.8 MiB) |
| SHA256 | 60875A94160F3F736F5CAB1E829964D29BA0DF099FA221D3282576B2604D2CEB |
| 包名 / 版本 | com.dsh.phone.pair / versionCode 4、versionName 1.0.3 |
| 最低系统 | Android 8.0(API 26),targetSdk 34 |
| 签名 | CN=DSH Phone,SHA-256 b9204950d591bb3329ec137180673a98e2899e32fff91f23889585cc78ec1a0f(可覆盖升级) |
| 内置资源 | 85 个文件 / 28.2 MB(离线也能画界面) |
单元测试(JVM,无 JUnit 依赖):PairLinksTest 74 通过 / 0 失败(新增 12 条局域网/私网地址用例:192.168.、10.、172.20.、100.64.、100.68.26.79(测试员那条)、*.local、单段主机名、无 scheme 补 http、公网 http 仍拒绝、10.evil.com 这类伪前缀不认),AssetIndexTest 33 通过 / 0 失败。
DSH 手机版 · 配对版 1.0.2(配对链接更好懂)
DSH 手机版 · 配对版 1.0.2 —— 不让「复制粘贴」再把人挡在门外
这一版是照着真实测试反馈改的(感谢 B 站网友 RikiYuko 的两条报障)。功能没变,改的是"人话"。
修了什么
1. App 里粘贴过去,总说「输入完整的链接」
旧版的链接解析只认一种形状:https://<host>/pair-accept?pair=<码>。而面板上能复制到的其实有三种"看着像链接、其实不合格"的东西:
| 你复制的 | 实际是什么 | 旧版反应 |
|---|---|---|
| 屏幕上看得见的那截文字 | 面板是 CSS 省略号截断显示的(…/pair-accept?pair=fcb…),你选中的是残链接 |
拒绝 |
| 点了『复制令牌』 | 那是给 Docker / 反向代理环境用的裸令牌,不是链接 | 拒绝 |
面板回退时的 http://192.168… |
局域网地址(http),手机端只走 https | 拒绝 |
三种情况旧版都只回一句「需要完整的配对链接」,谁也猜不出问题在哪。1.0.2 起:
- 容错:粘贴时自动忽略零宽字符、不换行空格、换行(微信/QQ 转发经常塞这些),也接受不带
https://的裸链接(自动补上); - 会说话:分别提示
- 「链接被截断了(结尾是省略号 …)……请改点『复制链接』按钮」
- 「这是『配对令牌』,不是配对链接」
- 「这是局域网地址(
http://…),手机端只使用 https 地址」 - 「链接里缺少
?pair=参数」/「配对码不足 8 位」
- 配对浮层的引导也换成:「点『复制链接』(不是『复制令牌』)」;面板上如果写着「固定域名同步失败」或只剩局域网地址,会先让你在电脑侧修好。
局域网 http 仍然有意不支持:要支持它得在清单里打开 cleartext 明文流量、并放宽同源判断,安全代价不划算。所以我们选择"准确告诉你怎么做对",而不是"降低安全门槛"。
2. 手机浏览器点「继续」提示「暂时无法保存确认状态,请重试」
这句不是本 App 的文案,是 DSH 自己的「预览版说明」弹窗(welcomeError):它要把"已确认"写回电脑,而多数情况下是浏览器没带上配对 Cookie —— 微信/QQ 内置浏览器、无痕模式、手输网址或另存书签再打开,都会这样。
正确姿势(已写进 README 的「常见问题」):
- 从聊天窗口里直接点开配对链接(别手输、别存书签后再打开);
- 用系统 Chrome / Edge,关掉无痕,别用"阻止第三方 Cookie";
- 或者直接用配对版 App:设备凭据存在 App 本地,不走浏览器 Cookie,最省事。
顺手补的文档
- 两个 README(工程树 + 发布树)新增「常见问题(都来自真实测试反馈)」表:链接被截断 / 复制成了令牌 / 局域网地址 / 面板红字「固定域名同步失败」(本机
HTTPS_PROXY指向没启动的代理时,插件的 fetch 会直接失败)/ 浏览器无法保存确认状态。 - 插件 README 的「排错」表补上同样五条。
- 把配对码到底在哪写清楚了:面板入口 = 设置按钮旁边的手机图标,或「设置 → Web 插件 → 远程访问」(单独装插件时在设置里的插件行);并且强调点『复制链接』,不是『复制令牌』。
怎么升级
- 下载本页的
DSH-Phone-Pair-1.0.2.apk,直接覆盖安装(与 1.0.0 / 1.0.1 同一把签名 key,不必先卸载,数据保留); - 电脑上打开「远程访问」面板 → 刷新二维码 → 点『复制链接』 → 发到手机 → 在 App 的配对页粘贴;
- 在 App「设置 / 帮助 → 关于」里看到
DSH 手机版 · 配对版 1.0.2就装对了。
校验
| 项 | 值 |
|---|---|
| 文件 | DSH-Phone-Pair-1.0.2.apk |
| 大小 | 12,373,348 字节(约 11.8 MiB) |
| SHA256 | 3614516B4F1CEECC50B081E4CDA5440707689B4FA737A51E8461500A6BDD80B0 |
| 包名 / 版本 | com.dsh.phone.pair / versionCode 3、versionName 1.0.2 |
| 最低系统 | Android 8.0(API 26),targetSdk 34 |
| 签名 | CN=DSH Phone,SHA-256 b9204950d591bb3329ec137180673a98e2899e32fff91f23889585cc78ec1a0f(可覆盖升级) |
| 内置资源 | 85 个文件 / 28.2 MB(离线也能画界面) |
单元测试(JVM,无 JUnit 依赖):PairLinksTest 62 通过 / 0 失败(含省略号截断、零宽字符、无 scheme 链接、局域网 http、五类提示文案),AssetIndexTest 33 通过 / 0 失败。
DSH 手机版 · 配对版 1.0.1(修复首次配对失败)
DSH 手机版 · 配对版 1.0.1 —— 修复「第一次配对必然失败」
这个版本只修一个 bug,但它是致命的。
现象
全新安装的 App 永远完不成第一次配对,一直提示:
配对失败:配对链接可能已过期,请在电脑上重新生成
即使配对链接完全有效——同一条链接在手机浏览器里能正常配对(这也是最容易误判的地方:
看起来像链接或中继的问题,其实是 App 自己的问题)。而且失败是"秒失败":刚点开始配对就报错。
原因
App 用「已经记住的那台电脑的地址」去读服务器的配对 cookie,而"记住这台电脑"这一步写在
配对成功之后:
没记住电脑 → 不去读 cookie → 读不到新 cookie → 判定没配对成功 → 不记住电脑 → …
死循环,所以第一次配对永远出不来。这个判断又是本地同步做的,于是表现为"刚粘上就失败"。
浏览器不受影响(没有这段逻辑),因此会出现"浏览器好使、App 不好使"。
修复
java/com/dsh/phone/MainActivity.java的readPairCookie():在还没记住电脑时,回退使用
你刚粘贴的那条链接里的主机去读 cookie(并加了注释说明这个死锁,防止以后再犯)。- 版本号:
versionCode 1 → 2、versionName 1.0 → 1.0.1。
装好后在 App 里「设置 / 帮助 → 关于」能看到DSH 手机版 · 配对版 1.0.1,可用来确认装对了。
升级与配对(三步)
- 下载本页的
DSH-Phone-Pair-1.0.1.apk覆盖安装(与 1.0.0 同一把签名 key,不用先卸载,数据保留); - 电脑上打开 DSH →「远程访问」面板 → 刷新二维码 → 复制链接;
- 手机上把链接粘进 App →「开始配对」。
小提示:配对链接只有最新签发的那一条有效——点「刷新二维码」会让之前复制出去的链接立刻失效
(服务端的配对 token 有效期为 10 分钟)。所以复制之后请尽快粘贴,中途不要再点刷新。
校验
| 项 | 值 |
|---|---|
| 文件 | DSH-Phone-Pair-1.0.1.apk |
| 大小 | 12,369,252 字节 |
| SHA256 | 5690470F3668A2BDD85681CBFF12312BF000AFAEE55D7E82325AF04D76717B76 |
| 包名 / 版本 | com.dsh.phone.pair / versionCode 2、versionName 1.0.1 |
| 最低系统 | Android 8.0(API 26) |
| 签名 | CN=DSH Phone, OU=Personal, O=DSH Phone(与 1.0.0 同一把 key) |
| 权限 | 仅 INTERNET、ACCESS_NETWORK_STATE |
DSH 手机版 · 配对版 1.0
DSH 手机版 · 配对版 1.0
安卓手机上的 DSH 客户端。通用配对版:安装包不含任何凭据、不含任何电脑地址,可以随便转发;每个人装好后配对自己电脑即可。
下载
| 文件 | 大小 | SHA256 |
|---|---|---|
DSH-Phone-Pair-1.0.apk |
12,373,348 字节 | 863F7B3175EE089FAE9FD358F1DA43E7181DF3311E727C922A24E58C8C3FAB76 |
- 包名
com.dsh.phone.pair· 应用名「DSH 手机版 · 配对版」 · versionName 1.0(versionCode 1) - minSdk 26(Android 8.0)· targetSdk 34 · 权限只有
INTERNET与ACCESS_NETWORK_STATE - 签名证书 SHA-256
b9204950d591bb3329ec137180673a98e2899e32fff91f23889585cc78ec1a0f(自签名) - 约 28 MB 前端(85 个内容哈希资源)已打进包里,首次打开不必等下载界面
装好之后怎么用
- 电脑侧(每台一次):装 DSH → 装插件
@linxin666/dsh-remote-web-ui(自带 cloudflared,不需要 Cloudflare 账号或域名)→ 打开它的「自动隧道」→ 复制配对链接https://<id>.dsh-market.com/pair-accept?pair=<code>。 - 手机侧:装 APK → 设置本机密码(PBKDF2-HMAC-SHA256,10 万次迭代,只存手机)→ 点开或粘贴配对链接 → 进入你自己的 DSH 界面。
- 之后每次打开只要输密码。设备凭据有效期一年,电脑重启、换 IP、换网络都不用重新配对。
本仓库的 plugin/dsh-phone-pair-kit 是可选配套插件,装上会自动把上面第 1 步的开关打开:
pnpm add github:Zoragyx/dsh-phone-pair#path:plugin/dsh-phone-pair-kit
# ↑ 这条需要本机有 git;没装 git 就在仓库页面 Code → Download ZIP,
# 解压后 pnpm add <解压目录>\plugin\dsh-phone-pair-kit这一版做了什么
- 通用化:构建期不再把
BASE_URL/BASE_HOST/DEVICE_ID编译进包,改成运行期从配对链接学习站点,凭据存手机本地。 - 修掉一个首次配对必现的 bug:配对成功后是 303 跳转
/pair-accept → /pair-app?grant=…,旧逻辑在未配对时把跳转交给系统浏览器,导致 cookie 写不进、界面停在「配对失败」。现在按配对链接的 host 放行跳转。 - 同源闸门:只有目标站点自己的路径才从包内直接提供资源。
- 密码锁屏 + 退到后台再回来重新验证;「复位本机」一键清掉密码与配对。
验证(本轮实测)
| 检查 | 结果 |
|---|---|
| 单元测试 | PairLinksTest passed=50、AssetIndexTest passed=33 |
| 真数据命中 | 外壳 85 个 URL → hits: 85 ; misses: 0 |
| 包内资源逐字节比对 | 85/85 verified byte-identical, 29,546,654 bytes (28.2 MB) |
| 凭据审计 | verdict : OK - no build-time credential or cookie inside the package |
| 全新配对链路 | 公网兑换 200 → /pair-app?grant=… → 新凭据解锁 200 → 撤销后设备数不变 |
| 打包 | zipalign 通过 · apksigner verify 通过 · aapt2 badging 包名/版本/权限正确 |
注意
- 电脑关机就不能用:App 只是手机端界面,DSH 与 Agent 都跑在电脑上。关机、睡眠、退出 DSH 都会断开,唤醒后 1~2 分钟自动恢复,不需要重新配对。
- 配对成功的设备 = 完全控制凭据(聊天、会话、设置、凭据、Agent 预设、产出物)。只在自己的手机上配对,配对链接默认 10 分钟过期。
- 电脑上的 DSH 始终保持
127.0.0.1回环绑定,公网可达性由 cloudflared 出站隧道提供;不想要就在面板里撤销设备。 - 中继(
dsh-market.com)偶发 530/截断只影响外壳那几十 KB,界面资源都在包内。
灵感来源与致谢
- 这个 App 的灵感与配对思路来自开源插件
@linxin666/dsh-remote-web-ui(作者 linxin666,源码仓库 https://github.com/zhu1090093659/dsh-web,Apache-2.0):/pair-accept?pair=<code>一次性令牌、/pair-app手机版界面壳、可撤销的设备会话、固定域名中继<id>.dsh-market.com、设置页的「远程访问」面板与二维码都出自它。感谢原作者 linxin666。 - 在这个思路上,本项目独立完成了手机端:安卓 WebView 外壳、本机密码锁屏、离线优先缓存、把约 28 MB 前端资源打进包内、从配对链接运行期学习主机,以及构建/审计/验证/发布的全套脚本;另附配套插件
plugin/dsh-phone-pair-kit。本仓库不包含上游插件的源码。 - 插件骨架的写法参考了
dsh-orb(作者 mini-yifan,MIT),谨致谢意。 - APK 内置的前端资源来自 DSH 自己的 Web 界面(构建时从使用者电脑抓取),版权归 DSH 作者;如认为不宜随 APK 分发,告知后会立刻删除该资产或改为不含内置前端的构建。
- 本项目是社区第三方作品,与 DeepSeek / DSH 官方及上述作者没有隶属关系,也未声称获得其背书;**若说明或做法有任何不妥,请提 issue,我们会立即修改或下架。**完整清单见仓库根目录
NOTICE.md。
许可
本项目自己的代码:MIT,见 LICENSE。第三方组件(@linxin666/dsh-remote-web-ui Apache-2.0、dsh-orb MIT、cloudflared Apache-2.0)各自遵循自己的许可,详见 NOTICE.md。