dsh-mesh-access 1.0.0 → 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +17 -0
- package/README.en.md +6 -2
- package/README.md +31 -2
- package/lib/client.js +1 -1
- package/lib/index.js +11 -1
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,22 @@
|
|
|
1
1
|
# 更新日志
|
|
2
2
|
|
|
3
|
+
## 1.0.2 — 把卖点改成「手机远程控制」
|
|
4
|
+
|
|
5
|
+
功能没变,只是把话说对:这东西最主要的用法是**用手机远程控制电脑上的 DSH**(同一个实例、同一份会话),
|
|
6
|
+
「笔记本 / NAS / 电视盒子也能开」降级成附加卖点。
|
|
7
|
+
|
|
8
|
+
- README 中英开头改成手机优先;
|
|
9
|
+
- npm 描述、市场条目中英描述同步;
|
|
10
|
+
- 面板副标题改成「用手机远程控制:手机浏览器打开就是你在电脑上用的那个 DSH」。
|
|
11
|
+
|
|
12
|
+
## 1.0.1 — 修「一直重新连接中」
|
|
13
|
+
|
|
14
|
+
`Origin` 没有跟着 `Host` 一起改写,DSH 的 WebSocket 升级被自己的同源校验挡成 **403**,
|
|
15
|
+
于是 HTTP 一切正常(页面能开、API 能通),但实时通道连不上,界面底部一直显示「重新连接中…」。这一版修掉它,并顺手把长连接的 TCP keepalive 打开。
|
|
16
|
+
|
|
17
|
+
- `rewrite()` 在改写 `Host` 的同时改写 `Origin`(`http://<upstream>`);
|
|
18
|
+
- upgrade 路径两个 socket 都 `setNoDelay(true)` + `setKeepAlive(true, 30000)`,让中继上的空闲长连接不容易被悄悄丢掉。
|
|
19
|
+
|
|
3
20
|
## 1.0.0 — 改名(原名 dsh-phone-tunnel)
|
|
4
21
|
|
|
5
22
|
插件和「手机」没关系:它做的是把组网地址上的请求转给本进程。所以改了名,顺便把定位放宽。
|
package/README.en.md
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
# dsh-mesh-access
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
**Control your DSH from your phone.** Open the address in a phone browser and you get the very
|
|
4
|
+
same UI you are using on the desktop — same instance, same session list, same context. No SSH,
|
|
5
|
+
no second `dsh`, no router to touch.
|
|
6
|
+
|
|
7
|
+
Under the hood it mounts the running DeepSeek Harness web UI onto a mesh/VPN interface, from
|
|
8
|
+
inside the server process.
|
|
5
9
|
|
|
6
10
|
[English](#what-it-does) | [中文](README.md)
|
|
7
11
|
|
package/README.md
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
# dsh-mesh-access
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
**用手机远程控制电脑上的 DSH。** 手机浏览器打开,就是你在电脑上正在用的那个界面 ——
|
|
4
|
+
同一个实例、同一份会话、同一份上下文,不需要 SSH,不需要第二个 `dsh`,也不用碰路由器。
|
|
5
|
+
|
|
6
|
+
底层做法是把正在运行的 DeepSeek Harness 网页界面挂到组网网卡上,在服务进程内部完成。
|
|
5
7
|
|
|
6
8
|
[中文](#它做什么) | [English](README.en.md)
|
|
7
9
|
|
|
@@ -130,3 +132,30 @@ curl -s http://127.0.0.1:3080/api/dsh-mesh-access/status
|
|
|
130
132
|
## 许可
|
|
131
133
|
|
|
132
134
|
MIT。
|
|
135
|
+
|
|
136
|
+
## 常见问题
|
|
137
|
+
|
|
138
|
+
**页面能打开、侧边栏也有,但底部一直「重新连接中…」,工作区列表空着**
|
|
139
|
+
|
|
140
|
+
这是 1.0.0 的 bug,升级到 **1.0.1** 即可。原因:反代把 `Host` 改写成上游(`127.0.0.1:3080`)却没改 `Origin`,DSH 对 WebSocket 升级做同源校验,浏览器带着 `Origin: http://<组网IP>:<端口>` 过来,两边不一致 → 上游直接 `403 Forbidden`。于是普通 HTTP 全通(页面能开、API 能查),实时通道一次都没握上手,浏览器每几秒重试一次,看起来就像“网络一直断”。
|
|
141
|
+
|
|
142
|
+
自查一行就够:
|
|
143
|
+
|
|
144
|
+
```bash
|
|
145
|
+
curl -s -o /dev/null -w '%{http_code}\n' --http1.1 \
|
|
146
|
+
-H 'Connection: Upgrade' -H 'Upgrade: websocket' \
|
|
147
|
+
-H 'Sec-WebSocket-Version: 13' -H 'Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==' \
|
|
148
|
+
-H "Origin: http://<组网IP>:<端口>" \
|
|
149
|
+
-b <你浏览器的 cookie> \
|
|
150
|
+
http://<组网IP>:<端口>/api/remote.mux
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
`101` 是正常,`403` 就是中了这个 bug。
|
|
154
|
+
|
|
155
|
+
**改了端口或组网 IP,面板上的地址还能用吗**
|
|
156
|
+
|
|
157
|
+
不能。反代一开出来,监听地址和上游端口就固定了;「访问地址」里的 token 也是按当时的地址签的。换了就点「关闭」→「在组网地址上开端口」,重新复制地址。
|
|
158
|
+
|
|
159
|
+
**组网里的设备打开地址却超时**
|
|
160
|
+
|
|
161
|
+
先确认那台设备能路由到组网 IP(`ping <组网IP>`),再确认本机防火墙放行该端口。Linux 上 `firewall-cmd --zone=<组网域> --list-ports`,Windows 上查该端口的入站规则。
|
package/lib/client.js
CHANGED
|
@@ -140,7 +140,7 @@ window.__ModuleLoader__.load({
|
|
|
140
140
|
'div',
|
|
141
141
|
{ style: S.wrap },
|
|
142
142
|
h('div', { style: S.h1 }, '组网访问'),
|
|
143
|
-
h('div', { style: S.sub }, '
|
|
143
|
+
h('div', { style: S.sub }, '用手机远程控制:手机浏览器打开就是你在电脑上用的那个 DSH——同一实例、同一份会话,不用第二个实例,不用 SSH。'),
|
|
144
144
|
|
|
145
145
|
h(
|
|
146
146
|
Card, { title: '当前状态' },
|
package/lib/index.js
CHANGED
|
@@ -84,11 +84,17 @@ function readBody(req, limit = 8 * 1024) {
|
|
|
84
84
|
*/
|
|
85
85
|
function createProxy({ listenAddress, listenPort, upstream, upstreamPort }) {
|
|
86
86
|
const target = `${upstream}:${upstreamPort}`
|
|
87
|
+
// DSH 会校验 Origin 与 Host 是否一致(不一致直接 403),所以我们转发时把 Host 改写成
|
|
88
|
+
// 上游地址,就必须把 Origin 一起改写成上游的 origin;否则浏览器的 WebSocket 升级
|
|
89
|
+
// 永远 403,界面上表现成「一直重新连接中」。
|
|
90
|
+
const upstreamOrigin = `http://${target}`
|
|
87
91
|
const rewrite = (headers) => {
|
|
88
92
|
const h = { ...headers }
|
|
93
|
+
const incomingHost = headers.host ?? ''
|
|
89
94
|
h.host = target
|
|
90
|
-
h['x-forwarded-host'] =
|
|
95
|
+
h['x-forwarded-host'] = incomingHost
|
|
91
96
|
h['x-forwarded-proto'] = 'http'
|
|
97
|
+
if (headers.origin) h.origin = upstreamOrigin
|
|
92
98
|
return h
|
|
93
99
|
}
|
|
94
100
|
|
|
@@ -109,7 +115,11 @@ function createProxy({ listenAddress, listenPort, upstream, upstreamPort }) {
|
|
|
109
115
|
|
|
110
116
|
// WebSocket / HTTP upgrade:裸 socket 双向转发(DSH 的实时通道靠它)
|
|
111
117
|
server.on('upgrade', (req, socket, head) => {
|
|
118
|
+
socket.setNoDelay(true)
|
|
119
|
+
socket.setKeepAlive(true, 30_000)
|
|
112
120
|
const up = net.connect(upstreamPort, upstream, () => {
|
|
121
|
+
up.setNoDelay(true)
|
|
122
|
+
up.setKeepAlive(true, 30_000)
|
|
113
123
|
const lines = [`${req.method} ${req.url} HTTP/1.1`]
|
|
114
124
|
for (const [k, v] of Object.entries(rewrite(req.headers))) {
|
|
115
125
|
if (v === undefined) continue
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-mesh-access",
|
|
3
|
-
"version": "1.0.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "1.0.2",
|
|
4
|
+
"description": "Control your DSH from your phone: opens a port on the mesh/VPN interface from inside the running server process, so a phone browser gets the same instance and the same session list — no SSH, no second dsh. Also reachable from another PC, a GUI NAS, or a TV box.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "lib/index.js",
|
|
7
7
|
"exports": {
|