dsh-zen-remote 2.3.1 → 2.3.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/README.md
CHANGED
|
@@ -94,7 +94,7 @@ dsh plugin --profile web add dsh-zen-remote
|
|
|
94
94
|
// ~/.dsh/profiles/desktop/package.json
|
|
95
95
|
{
|
|
96
96
|
"dependencies": {
|
|
97
|
-
"dsh-zen-remote": "^2.3.
|
|
97
|
+
"dsh-zen-remote": "^2.3.2" // for local development: "link:/path/to/dsh-zen-remote"
|
|
98
98
|
}
|
|
99
99
|
}
|
|
100
100
|
```
|
package/README.zh-CN.md
CHANGED
|
@@ -94,7 +94,7 @@ dsh plugin --profile web add dsh-zen-remote
|
|
|
94
94
|
// ~/.dsh/profiles/desktop/package.json
|
|
95
95
|
{
|
|
96
96
|
"dependencies": {
|
|
97
|
-
"dsh-zen-remote": "^2.3.
|
|
97
|
+
"dsh-zen-remote": "^2.3.2" // 本地开发换成 "link:/path/to/dsh-zen-remote"
|
|
98
98
|
}
|
|
99
99
|
}
|
|
100
100
|
```
|
package/lib/client.js
CHANGED
|
@@ -18886,8 +18886,8 @@ function GatewayWizard(props) {
|
|
|
18886
18886
|
};
|
|
18887
18887
|
if (path === 'lan') {
|
|
18888
18888
|
// LAN / Tailscale direct connections arrive on the machine's LAN or
|
|
18889
|
-
// Tailscale interface, so the gateway child
|
|
18890
|
-
//
|
|
18889
|
+
// Tailscale interface, so the gateway child binds to `0.0.0.0` (with
|
|
18890
|
+
// lan-gate's private-IP wall blocking any unproxied public IP).
|
|
18891
18891
|
await props.saveRowFields({
|
|
18892
18892
|
...baseFields,
|
|
18893
18893
|
host: '0.0.0.0',
|
|
@@ -18903,8 +18903,12 @@ function GatewayWizard(props) {
|
|
|
18903
18903
|
});
|
|
18904
18904
|
}
|
|
18905
18905
|
else {
|
|
18906
|
+
// Managed Caddy and Cloudflare Tunnel both run on the same host and
|
|
18907
|
+
// connect to the gateway over loopback, so reset `host` back to
|
|
18908
|
+
// `127.0.0.1` in case the user previously enabled LAN mode.
|
|
18906
18909
|
await props.saveRowFields({
|
|
18907
18910
|
...baseFields,
|
|
18911
|
+
host: '127.0.0.1',
|
|
18908
18912
|
ingressMode: path,
|
|
18909
18913
|
ingressDomain: domain.trim(),
|
|
18910
18914
|
ingressHttpsPort: readiness.httpsPort,
|
package/lib/lan-gate-server.cjs
CHANGED
|
@@ -239,6 +239,22 @@ var lastWebClaim = null // { id, secure, at } | null
|
|
|
239
239
|
// ---- client identity --------------------------------------------------------
|
|
240
240
|
function normalizeIp(raw) { return String(raw || '').replace(/^::ffff:/, '') }
|
|
241
241
|
function isLoopbackIp(ip) { return ip === '127.0.0.1' || ip === '::1' }
|
|
242
|
+
function isPrivateOrLoopbackIp(ip) {
|
|
243
|
+
if (isLoopbackIp(ip)) return true
|
|
244
|
+
var m4 = /^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/.exec(ip)
|
|
245
|
+
if (m4) {
|
|
246
|
+
var a = Number(m4[1]), b = Number(m4[2]), c = Number(m4[3]), d = Number(m4[4])
|
|
247
|
+
if (a > 255 || b > 255 || c > 255 || d > 255) return false
|
|
248
|
+
if (a === 10 || a === 127) return true
|
|
249
|
+
if (a === 172 && b >= 16 && b <= 31) return true
|
|
250
|
+
if (a === 192 && b === 168) return true
|
|
251
|
+
if (a === 169 && b === 254) return true
|
|
252
|
+
if (a === 100 && b >= 64 && b <= 127) return true // CGNAT / Tailscale
|
|
253
|
+
return false
|
|
254
|
+
}
|
|
255
|
+
var lower = String(ip || '').toLowerCase()
|
|
256
|
+
return /^f[cd][0-9a-f]{2}:/.test(lower) || /^fe[89ab][0-9a-f]:/.test(lower)
|
|
257
|
+
}
|
|
242
258
|
function hasForwardHeaders(req) { return req.headers['x-forwarded-for'] !== undefined || req.headers['x-forwarded-proto'] !== undefined || req.headers['x-forwarded-host'] !== undefined }
|
|
243
259
|
|
|
244
260
|
// Resolve who is really talking to us. Forwarded headers are only trusted
|
|
@@ -1186,6 +1202,15 @@ function localOnlyBlocked(req, res) {
|
|
|
1186
1202
|
|
|
1187
1203
|
var server = http.createServer(function (req, res) {
|
|
1188
1204
|
var client = resolveClient(req)
|
|
1205
|
+
// Direct (non-proxied) connections from a public IP are refused outright:
|
|
1206
|
+
// plain HTTP on 0.0.0.0:3088 is for loopback, LAN (RFC1918), and Tailscale
|
|
1207
|
+
// (100.64.0.0/10) only — public internet traffic must enter through a
|
|
1208
|
+
// TLS-terminating reverse proxy or tunnel (which connects from loopback or
|
|
1209
|
+
// a configured trustedProxy).
|
|
1210
|
+
if (!client.viaProxy && !isPrivateOrLoopbackIp(client.ip)) {
|
|
1211
|
+
json(req, res, 403, { ok: false, reason: 'public-direct-forbidden' })
|
|
1212
|
+
return
|
|
1213
|
+
}
|
|
1189
1214
|
var pathname = String(req.url || '/').split('?')[0]
|
|
1190
1215
|
var local = isLocalDirect(req, client)
|
|
1191
1216
|
var device = local ? undefined : deviceForReq(req)
|
|
@@ -1277,6 +1302,10 @@ var server = http.createServer(function (req, res) {
|
|
|
1277
1302
|
|
|
1278
1303
|
server.on('upgrade', function (req, socket, head) {
|
|
1279
1304
|
var client = resolveClient(req)
|
|
1305
|
+
if (!client.viaProxy && !isPrivateOrLoopbackIp(client.ip)) {
|
|
1306
|
+
try { socket.end('HTTP/1.1 403 Forbidden\r\nConnection: close\r\n\r\n') } catch (e) {}
|
|
1307
|
+
return
|
|
1308
|
+
}
|
|
1280
1309
|
var local = isLocalDirect(req, client)
|
|
1281
1310
|
var device = local ? undefined : deviceForReq(req)
|
|
1282
1311
|
if (!local && !device && overRate(client.ip)) { try { socket.end('HTTP/1.1 429 Too Many Requests\r\nConnection: close\r\n\r\n') } catch (e) {} return }
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GatewayWizard.d.ts","sourceRoot":"","sources":["../../../../src/client/wizard/GatewayWizard.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAGH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AACtC,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,kCAAkC,CAAA;AACjF,OAAO,KAAK,EAMV,qBAAqB,EACtB,MAAM,oCAAoC,CAAA;AAmD3C,OAAO,EAAE,EAAE,EAAE,MAAM,eAAe,CAAA;AAMlC,MAAM,WAAW,kBAAmB,SAAQ,YAAY,CAAC,uBAAuB,CAAC,EAAE,WAAW,CAAC,OAAO,EAAE,CAAC;IACvG,qEAAqE;IACrE,MAAM,EAAE,qBAAqB,CAAA;IAC7B,2EAA2E;IAC3E,aAAa,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;KAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;CAC3G;AAoGD,wBAAgB,aAAa,CAAC,KAAK,EAAE,kBAAkB,GAAG,SAAS,
|
|
1
|
+
{"version":3,"file":"GatewayWizard.d.ts","sourceRoot":"","sources":["../../../../src/client/wizard/GatewayWizard.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAGH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AACtC,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,kCAAkC,CAAA;AACjF,OAAO,KAAK,EAMV,qBAAqB,EACtB,MAAM,oCAAoC,CAAA;AAmD3C,OAAO,EAAE,EAAE,EAAE,MAAM,eAAe,CAAA;AAMlC,MAAM,WAAW,kBAAmB,SAAQ,YAAY,CAAC,uBAAuB,CAAC,EAAE,WAAW,CAAC,OAAO,EAAE,CAAC;IACvG,qEAAqE;IACrE,MAAM,EAAE,qBAAqB,CAAA;IAC7B,2EAA2E;IAC3E,aAAa,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;KAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;CAC3G;AAoGD,wBAAgB,aAAa,CAAC,KAAK,EAAE,kBAAkB,GAAG,SAAS,CAm/DlE"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-zen-remote",
|
|
3
|
-
"version": "2.3.
|
|
3
|
+
"version": "2.3.2",
|
|
4
4
|
"description": "一个插件、两种角色:主服务端把 DeepSeek Harness 变成手机能安全访问的 PWA(移动端界面、配对码网关、Web Push),并把选定会话共享给已配对的桌面端;子客户端在另一台 DSH 桌面端的侧边栏里远程使用这些会话。One DSH plugin, two roles: the host turns DeepSeek Harness into a phone-reachable PWA (mobile UI, pairing-code gateway behind your own reverse proxy, Web Push) and shares chosen sessions to paired desktops; the client uses those sessions remotely from another DSH desktop app's sidebar.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -600,8 +600,8 @@ export function GatewayWizard(props: GatewayWizardProps): ReactNode {
|
|
|
600
600
|
}
|
|
601
601
|
if (path === 'lan') {
|
|
602
602
|
// LAN / Tailscale direct connections arrive on the machine's LAN or
|
|
603
|
-
// Tailscale interface, so the gateway child
|
|
604
|
-
//
|
|
603
|
+
// Tailscale interface, so the gateway child binds to `0.0.0.0` (with
|
|
604
|
+
// lan-gate's private-IP wall blocking any unproxied public IP).
|
|
605
605
|
await props.saveRowFields(
|
|
606
606
|
{
|
|
607
607
|
...baseFields,
|
|
@@ -618,8 +618,12 @@ export function GatewayWizard(props: GatewayWizardProps): ReactNode {
|
|
|
618
618
|
ingressPublicUrl: readiness.publicUrl,
|
|
619
619
|
})
|
|
620
620
|
} else {
|
|
621
|
+
// Managed Caddy and Cloudflare Tunnel both run on the same host and
|
|
622
|
+
// connect to the gateway over loopback, so reset `host` back to
|
|
623
|
+
// `127.0.0.1` in case the user previously enabled LAN mode.
|
|
621
624
|
await props.saveRowFields({
|
|
622
625
|
...baseFields,
|
|
626
|
+
host: '127.0.0.1',
|
|
623
627
|
ingressMode: path,
|
|
624
628
|
ingressDomain: domain.trim(),
|
|
625
629
|
ingressHttpsPort: readiness.httpsPort,
|