dsh-mobile 0.6.17 → 0.7.0
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 +47 -11
- package/CONTRIBUTORS.md +12 -6
- package/README.en.md +22 -14
- package/README.md +21 -14
- package/SECURITY.md +1 -1
- package/THIRD_PARTY_NOTICES.md +33 -0
- package/apps/mobile/README.md +28 -3
- package/apps/mobile/README.zh-CN.md +28 -3
- package/apps/mobile/release.json +3 -3
- package/cordis.patch.yml +5 -9
- package/docs/ATTACH_EXISTING_FRPS.en.md +32 -2
- package/docs/ATTACH_EXISTING_FRPS.md +2 -2
- package/docs/CLIENT_MODULES.en.md +2 -0
- package/docs/CLIENT_MODULES.md +2 -0
- package/docs/CLOUDFLARE_TUNNEL.en.md +2 -0
- package/docs/CLOUDFLARE_TUNNEL.md +2 -0
- package/docs/IROH.en.md +44 -0
- package/docs/IROH.md +44 -0
- package/docs/MOBILE_PLUGIN_ADAPTATION.en.md +196 -0
- package/docs/MOBILE_PLUGIN_ADAPTATION.md +196 -0
- package/docs/README.md +9 -0
- package/docs/SELF_HOSTED_ORIGIN.en.md +26 -1
- package/docs/SELF_HOSTED_ORIGIN.md +27 -2
- package/docs/SKIN_COMPATIBILITY.en.md +2 -0
- package/docs/SKIN_COMPATIBILITY.md +2 -0
- package/docs/SLOW_CONNECTIONS.en.md +10 -2
- package/docs/SLOW_CONNECTIONS.md +10 -2
- package/docs/TRUSTED_NETWORKS.en.md +17 -0
- package/docs/TRUSTED_NETWORKS.md +17 -0
- package/lib/cli.js.map +1 -1
- package/lib/client.js +1081 -70
- package/lib/client.js.map +1 -1
- package/lib/index.d.mts +271 -2
- package/lib/index.mjs +1908 -245
- package/lib/index.mjs.map +1 -1
- package/lib/mobile-layout.js +14 -6
- package/lib/mobile-layout.js.map +1 -1
- package/native/iroh-host/LICENSE.dsh-mobile-iroh +21 -0
- package/native/iroh-host/LICENSE.dsh-tether +21 -0
- package/native/iroh-host/NOTICE.dsh-mobile-iroh +13 -0
- package/native/iroh-host/README.md +66 -0
- package/package.json +18 -5
- package/packages/question-fixes/package.json +1 -1
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
# 移动端插件适配指南
|
|
2
|
+
|
|
3
|
+
[English](MOBILE_PLUGIN_ADAPTATION.en.md) · [返回文档索引](README.md)
|
|
4
|
+
|
|
5
|
+
这份指南面向 DSH 插件作者,目标是**小屏可用,桌面功能不回退**。DSH Mobile 提供连接、页面布局和公共入口,不会逐个重排第三方插件的内部控件。可以先用浏览器完成适配,再补充真机验证;没有 Android 设备并不妨碍开始。
|
|
6
|
+
|
|
7
|
+
## 先确认面板所在位置
|
|
8
|
+
|
|
9
|
+
| 当前移动页面行为 | 插件应如何处理 |
|
|
10
|
+
| --- | --- |
|
|
11
|
+
| 打开 `main` 槽中的面板时,布局在面板上方提供「返回会话」栏 | 使用容器实际可用高度;该栏至少 56px,安全区和内容可能增加高度,不要手动从屏幕高度固定减去 56px |
|
|
12
|
+
| 窄屏侧栏以抽屉显示,展开宽度不超过 `min(88vw, 340px)`;宽屏可以常驻显示 | 不假设侧栏永远是 340px,入口文字和按钮应能收缩 |
|
|
13
|
+
| 移动布局带有 `.dshm-shell` 和 `[data-pane="conversation"]`、`[data-pane="sidebar"]` 标记 | 排障时可用这些标记定位区域;插件内部样式优先作用于自己的根节点,不依赖宿主私有 CSS 类名 |
|
|
14
|
+
| 移动外壳为输入框和可编辑区域设置至少 16px 的字体,同时保留更大的继承字号 | 为输入区域预留高度,不用更小的固定字体抵消用户设置 |
|
|
15
|
+
| 公共入口的适配不会保证任意第三方控件的可点击区域 | 插件作者仍需检查按钮、关闭键、复选框和菜单的实际命中区域 |
|
|
16
|
+
|
|
17
|
+
这些是当前布局行为,不是要求插件复制的固定尺寸。浮层、侧栏和主面板的可用空间不同,需在实际挂载位置验证。
|
|
18
|
+
|
|
19
|
+
## 按可用空间适配
|
|
20
|
+
|
|
21
|
+
先让基础布局能够收缩:给 flex/grid 子项设置 `min-width: 0`,允许工具栏换行,使用内容驱动的高度。面板宽度不一定等于视口宽度:桌面侧栏中的 400px 面板也需要紧凑布局。
|
|
22
|
+
|
|
23
|
+
只改变排列时,可用 CSS 容器查询;全屏页面的视口适配仍可使用媒体查询。下面的 `600px` 是示例断点,应按插件内容选择:
|
|
24
|
+
|
|
25
|
+
```css
|
|
26
|
+
.plugin-panel-host { container-type: inline-size; min-width: 0; }
|
|
27
|
+
.plugin-panel { min-width: 0; }
|
|
28
|
+
.plugin-panel .toolbar { display: flex; flex-wrap: wrap; gap: 8px; }
|
|
29
|
+
|
|
30
|
+
@container (max-width: 600px) {
|
|
31
|
+
.plugin-panel .toolbar { display: grid; grid-template-columns: minmax(0, 1fr); }
|
|
32
|
+
}
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
`.plugin-panel-host` 应包住 `.plugin-panel`。对不支持容器查询的引擎,基础的换行和流式宽度仍应可用,不要把必需操作藏在唯一的查询分支里。
|
|
36
|
+
|
|
37
|
+
确实需要脚本分支时,可以在组件内部观察根节点宽度,而不是判断手机 UA:
|
|
38
|
+
|
|
39
|
+
```js
|
|
40
|
+
const rootRef = useRef(null)
|
|
41
|
+
const [panelWidth, setPanelWidth] = useState(null)
|
|
42
|
+
const isNarrow = panelWidth !== null && panelWidth <= 600
|
|
43
|
+
|
|
44
|
+
useEffect(() => {
|
|
45
|
+
const element = rootRef.current
|
|
46
|
+
if (element === null) return undefined
|
|
47
|
+
const measure = () => setPanelWidth(element.getBoundingClientRect().width)
|
|
48
|
+
measure()
|
|
49
|
+
window.addEventListener('resize', measure)
|
|
50
|
+
const observer = typeof window.ResizeObserver === 'function' ? new window.ResizeObserver(measure) : null
|
|
51
|
+
observer?.observe(element)
|
|
52
|
+
return () => {
|
|
53
|
+
window.removeEventListener('resize', measure)
|
|
54
|
+
observer?.disconnect()
|
|
55
|
+
}
|
|
56
|
+
}, [])
|
|
57
|
+
|
|
58
|
+
// 组件返回值中的根节点;初次测量前也应保留可用的基础布局。
|
|
59
|
+
h('section', { ref: rootRef, className: 'plugin-panel', 'data-narrow': isNarrow ? 'true' : 'false' }, contents)
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
没有 ResizeObserver 的回退只能在窗口变化时重测;如果面板会独立调整宽度,还需接入插件已有的布局通知。观察器和监听器应随组件卸载清理。
|
|
63
|
+
|
|
64
|
+
## 适配清单
|
|
65
|
+
|
|
66
|
+
### 触控目标与间距
|
|
67
|
+
|
|
68
|
+
本项目建议主要 Web 操作提供至少 **44×44 CSS px** 的命中区域,主操作有空间时可用 48px;这不是 Android dp 或 iOS pt 的换算。相邻操作保留间距,不通过覆盖邻居来扩大点击区。
|
|
69
|
+
|
|
70
|
+
```css
|
|
71
|
+
.plugin-panel :is(button, select, input:not([type="checkbox"]):not([type="radio"])) { min-height: 44px; }
|
|
72
|
+
.plugin-panel .icon-button { min-width: 44px; }
|
|
73
|
+
.plugin-panel .actions { display: flex; flex-wrap: wrap; gap: 8px; }
|
|
74
|
+
.plugin-panel .check-label { box-sizing: border-box; display: inline-flex; align-items: center; gap: 8px; min-width: 44px; min-height: 44px; padding-inline: 8px; }
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
小复选框可放在关联的 `label` 中,扩大标签的可点击区域,不必放大图标。用实际点按和 `elementFromPoint()` 检查边缘命中;声明了 `min-height` 仍可能被布局压缩、裁切或遮挡。
|
|
78
|
+
|
|
79
|
+
### 筛选条、标签与行内动作
|
|
80
|
+
|
|
81
|
+
过长的筛选条可以换行,或放入能横向滚动的独立容器;不要让页面整体横向溢出。保留焦点可见性和足够的内边距,使最后一项也能滚入视野:
|
|
82
|
+
|
|
83
|
+
```css
|
|
84
|
+
.plugin-panel .chips { display: flex; gap: 8px; overflow-x: auto; padding: 4px; }
|
|
85
|
+
.plugin-panel .chip { flex: 0 0 auto; min-height: 44px; }
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
有明确含义的行内动作可以在窄屏收成图标,但要保留可访问名称,必要时在菜单中保留文字说明。不能靠悬停提示作为手机上唯一的操作说明。
|
|
89
|
+
|
|
90
|
+
```js
|
|
91
|
+
h('button', { className: 'icon-button', 'aria-label': label }, h(Icon, { 'aria-hidden': true, name: 'play' }))
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
窄屏不代表没有键盘。可以收起装饰性的快捷键角标,但保留实际快捷键、帮助入口、Tab 顺序和可见焦点;不要只按宽度移除键盘可用功能。
|
|
95
|
+
|
|
96
|
+
### 字体、密度与完整信息
|
|
97
|
+
|
|
98
|
+
继承 DSH 的字体和语义颜色;需要跟随移动页面字号时,可在自己的内容根节点使用 `--dsh-content-font-size`,未提供该变量时保留继承值:
|
|
99
|
+
|
|
100
|
+
```css
|
|
101
|
+
.plugin-panel { font-size: var(--dsh-content-font-size, inherit); line-height: 1.5; }
|
|
102
|
+
.plugin-panel .meta { color: var(--dsw-alias-label-secondary, currentColor); }
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
压缩装饰性标题和空白,不压缩触摸目标。长标题允许换行或提供可访问的完整查看入口;错误、待确认内容和关键操作名称不能只剩截断文本。大字号、长路径与中英文内容都要检查。
|
|
106
|
+
|
|
107
|
+
### 弹层、表单与滚动边界
|
|
108
|
+
|
|
109
|
+
浮层应受实际容器和可视区约束,避免固定宽高把按钮推到屏幕外。先使用 DSH 的现有浮层组件;自有弹层需保留可达的关闭入口、焦点管理和 Escape 行为。
|
|
110
|
+
|
|
111
|
+
```css
|
|
112
|
+
.plugin-panel .form-row { display: grid; grid-template-columns: minmax(0, 1fr); gap: 8px; }
|
|
113
|
+
.plugin-panel .scroll-body { min-height: 0; overflow: auto; overscroll-behavior: contain; }
|
|
114
|
+
.plugin-panel textarea { box-sizing: border-box; width: 100%; min-height: 96px; }
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
只有确实延伸到屏幕边缘且未被宿主处理的区域才追加 `env(safe-area-inset-*)`,避免重复留白。键盘打开后,保存、取消和错误提示仍应可见或可滚动到达;独立滚动区域不应拖动背后的页面。
|
|
118
|
+
|
|
119
|
+
### 浮层层级与 portal
|
|
120
|
+
|
|
121
|
+
专用移动布局通过 `isolation:isolate` 将抽屉和面板限制在外壳自身的层叠上下文。直接挂载到 `document.body`、具有定位和正 `z-index` 的菜单可以显示在外壳上方,无需超过抽屉内部的层级值。原生布局适配器保留既有层级值。
|
|
122
|
+
|
|
123
|
+
这不代表任意 body 子元素都能覆盖所有对话框。负值、零值/auto 的绘制顺序、祖先的层叠上下文以及浏览器顶层都会影响结果;外壳内部的菜单仍受祖先约束。优先使用宿主已有的浮层能力,所属面板关闭或模态层获得焦点时收起菜单,不要统一抬高第三方组件或修改 DSH 对话框层级。
|
|
124
|
+
|
|
125
|
+
在窄屏与宽屏下,分别打开抽屉、详情和设置,检查实际可见性、焦点及 `document.elementFromPoint()` 命中。`smoke:plugin-portal-layers` 的受控场景检查正层级 body 菜单和浏览器顶层对话框,不代表所有社区插件均已验收。
|
|
126
|
+
|
|
127
|
+
## 验证:代码检查、浏览器与真机分别证明什么
|
|
128
|
+
|
|
129
|
+
### 结构检查
|
|
130
|
+
|
|
131
|
+
单测可验证窄屏分支、可访问名称、状态保留和卸载清理。服务端渲染不会执行浏览器布局测量;给测试提供宽度或布局桩,只能证明选中了哪个分支,不能证明真实尺寸、可点击性或桌面像素一致。不要把 CSS 中出现 `44px` 当成触摸验收。
|
|
132
|
+
|
|
133
|
+
### 真实浏览器检查
|
|
134
|
+
|
|
135
|
+
将插件挂到实际 DSH 页面后,至少检查 375px、390px 窄屏、横屏、桌面全宽和桌面窄侧栏。若维护静态预览,还要在浏览器中加载它,并明确它与真实宿主的差异。
|
|
136
|
+
|
|
137
|
+
- 覆盖列表、详情、设置、空状态、长内容和出错状态;
|
|
138
|
+
- 检查元素边界、裁切祖先和实际命中,确认首尾操作都能触达;
|
|
139
|
+
- 用键盘验证 Tab、Escape、焦点恢复,以及浮层打开时背景不会误操作;
|
|
140
|
+
- 改变宽度和字号,确认输入草稿、选择与展开状态保留;
|
|
141
|
+
- 检查浅色、深色和桌面基线;截图差异需解释,不要求有意改进也逐像素不变。
|
|
142
|
+
|
|
143
|
+
例如,在 Playwright 中对已有面板入口执行实际操作后,可检查控件几何和命中;以下选择器应替换为插件自己的稳定标记:
|
|
144
|
+
|
|
145
|
+
```js
|
|
146
|
+
const action = page.locator('[data-plugin-action="save"]')
|
|
147
|
+
await action.scrollIntoViewIfNeeded()
|
|
148
|
+
const box = await action.boundingBox()
|
|
149
|
+
if (box === null || box.width < 44 || box.height < 44) throw new Error('Save target is too small')
|
|
150
|
+
const hit = await action.evaluate(element => {
|
|
151
|
+
const box = element.getBoundingClientRect()
|
|
152
|
+
return element.contains(document.elementFromPoint(box.x + box.width / 2, box.y + box.height / 2))
|
|
153
|
+
})
|
|
154
|
+
if (!hit) throw new Error('Save target is obscured')
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
中心点命中只是起点,不能替代边缘点按、滚动、焦点与状态检查。具体启动和验证流程见[贡献指南](../CONTRIBUTING.md#select-behavior-checks)。
|
|
158
|
+
|
|
159
|
+
### 真机补充
|
|
160
|
+
|
|
161
|
+
浏览器模拟不能代替真实 WebView、输入法、安全区、惯性滚动或外接键盘验收。记录设备、App/WebView 版本、连接方式和实际步骤;没有验证的部分直接说明,不宣称已全平台通过。
|
|
162
|
+
|
|
163
|
+
## 给插件作者的模板
|
|
164
|
+
|
|
165
|
+
### Issue
|
|
166
|
+
|
|
167
|
+
```markdown
|
|
168
|
+
## 插件与小屏
|
|
169
|
+
- 插件名和版本:
|
|
170
|
+
- DSH、DSH Mobile 与 App/浏览器版本:
|
|
171
|
+
- 面板位置与可用宽度(主面板 / 侧栏 / 浮层):
|
|
172
|
+
- 复现步骤、期望与实际表现:
|
|
173
|
+
- 截图及可定位的控件(隐藏凭据和私人内容):
|
|
174
|
+
- 关闭其他可选前端模块后的对照结果(如已测试):
|
|
175
|
+
|
|
176
|
+
## 验收目标
|
|
177
|
+
- [ ] 必需操作可见、可点,长内容不被截断
|
|
178
|
+
- [ ] 触控区域、相邻间距和首尾项经过实际检查
|
|
179
|
+
- [ ] 键盘焦点、返回/关闭和草稿状态无回退
|
|
180
|
+
- [ ] 弹层与表单在窄屏和大字号下可用
|
|
181
|
+
- [ ] 桌面主要流程无回退;注明尚未验证的设备行为
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
### PR
|
|
185
|
+
|
|
186
|
+
- [ ] 说明受影响入口和内容,不按 UA 硬分手机与桌面;
|
|
187
|
+
- [ ] 优先复用组件与状态;确需不同排列时避免复制业务逻辑;
|
|
188
|
+
- [ ] 给出真实浏览器的窄屏和桌面对照、操作步骤及相关测试;
|
|
189
|
+
- [ ] 检查焦点、命中、长内容、错误和清理,不仅检查 CSS 文本;
|
|
190
|
+
- [ ] 说明真机已验证与未验证的范围,不复制其他版本的结果。
|
|
191
|
+
|
|
192
|
+
## 范围
|
|
193
|
+
|
|
194
|
+
本指南来自社区插件适配实践与 [#279 讨论](https://github.com/saya-ch/dsh-mobile/discussions/279),提供可复用的实现与验收思路,不代表这里已独立验证任何第三方插件的新版本。主题细节还可参考[皮肤与移动布局](SKIN_COMPATIBILITY.md)。
|
|
195
|
+
|
|
196
|
+
DSH Mobile 不按第三方私有类名维护通用覆盖表,也不保证依赖原生窗口的插件能在远程页面直接使用。适配应由拥有该组件的插件维护,并使用 DSH 的公开扩展接口;发现宿主缺失的能力时应单独报告,不修改已安装的 DSH 产物来绕过问题。
|
package/docs/README.md
CHANGED
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
| 复用已经运行的 frps,不自动修改服务器 | [接入既有 frps](ATTACH_EXISTING_FRPS.md) | [Existing frps](ATTACH_EXISTING_FRPS.en.md) |
|
|
14
14
|
| 复用 Lucky、Nginx 或 Caddy 的公开 HTTPS 入口 | [自有反向代理](SELF_HOSTED_ORIGIN.md) | [Own reverse proxy](SELF_HOSTED_ORIGIN.en.md) |
|
|
15
15
|
| 由插件安装 Caddy 并管理 HTTPS 证书(0.6.9 起) | [托管 Caddy](CADDY_MANAGED.md) | [Managed Caddy](CADDY_MANAGED.en.md) |
|
|
16
|
+
| iroh 加密直连实验通道 | [iroh 实验通道](IROH.md) | [iroh experimental channel](IROH.en.md) |
|
|
16
17
|
| 页面加载慢、实时连接反复重连或长操作超时 | [慢链路与重连](SLOW_CONNECTIONS.md) | [Slow links and reconnection](SLOW_CONNECTIONS.en.md) |
|
|
17
18
|
| 了解输入栏换行、附加控件与触摸目标 | [移动输入栏](MOBILE_COMPOSER_TOOLBAR.md) | [Mobile composer](MOBILE_COMPOSER_TOOLBAR.en.md) |
|
|
18
19
|
| 保留电脑皮肤,排查移动页面的背景与可读性 | [皮肤与移动布局](SKIN_COMPATIBILITY.md) | [Skins and mobile layout](SKIN_COMPATIBILITY.en.md) |
|
|
@@ -29,6 +30,14 @@
|
|
|
29
30
|
| 为移动页面选择加载模块 | [模块设置](CLIENT_MODULES.md) | [Module settings](CLIENT_MODULES.en.md) | 电脑默认与设备覆盖分别保存,不自动刷新会话 |
|
|
30
31
|
| 允许受控路由网络访问 LAN Gateway | [额外可信网段](TRUSTED_NETWORKS.md) | [Trusted networks](TRUSTED_NETWORKS.en.md) | 不建立 VPN,不自动扩大防火墙规则 |
|
|
31
32
|
|
|
33
|
+
## 插件移动适配 / Plugin mobile adaptation
|
|
34
|
+
|
|
35
|
+
给插件作者的响应式布局、触控与验收建议:优先复用现有组件,兼顾小屏与桌面,并区分结构检查、真实浏览器和真机证据。
|
|
36
|
+
|
|
37
|
+
| 主题 | 中文 | English |
|
|
38
|
+
| --- | --- | --- |
|
|
39
|
+
| 让第三方插件面板在手机上可用 | [移动端插件适配指南](MOBILE_PLUGIN_ADAPTATION.md) | [Mobile plugin adaptation](MOBILE_PLUGIN_ADAPTATION.en.md) |
|
|
40
|
+
|
|
32
41
|
## 开发与安全 / Development and security
|
|
33
42
|
|
|
34
43
|
0.6.3 的 [扩展 Worker 指南](EXTENSION_WORKERS.md)/[Worker guide](EXTENSION_WORKERS.en.md) 介绍按扩展启用、预算与显式恢复;此功能不迁移普通 Cordis 插件,也不是权限沙箱。
|
|
@@ -47,12 +47,37 @@ Select **Save and start backend**. An active backend reloads its settings. The p
|
|
|
47
47
|
2. Point the proxy at the displayed private HTTP backend, not the phone's public HTTPS address.
|
|
48
48
|
3. Preserve the external **Host including non-default port**: the example requires `phone.example.com:8815`, not the private target or a hostname without its port.
|
|
49
49
|
4. Preserve Origin, Cookie, Set-Cookie and authentication/CSRF headers. Do not rewrite Cookie domain/security attributes or cache authentication responses.
|
|
50
|
-
5. Forward HTTP/1.1 WebSocket upgrades and bidirectional data.
|
|
50
|
+
5. Forward HTTP/1.1 WebSocket upgrades and bidirectional data. The existing WebSocket path allowlist keeps applying; when a third-party plugin needs its own path, approve it separately in diagnostics.
|
|
51
51
|
|
|
52
52
|
[Lucky's official Web documentation](https://www.lucky666.cn/docs/modules/web/) describes WebSocket support. UI labels vary by version, but this backend requires the incoming external Host. Do not enable target-address Host; if a version offers custom Host, provide the full public hostname and port. Certificates belong on Lucky, not this HTTP backend.
|
|
53
53
|
|
|
54
54
|
For a separate proxy host, configure routing and a firewall rule limited to its actual private source yourself. This provider does not change the firewall.
|
|
55
55
|
|
|
56
|
+
### When you already run cloudflared yourself
|
|
57
|
+
|
|
58
|
+
If you already configured a named tunnel the official way (`cloudflared tunnel`, possibly as a systemd unit, a launchd job or a Windows service), **you do not need the plugin to install a second copy, and you do not need to store a tunnel Token in it**. Use the own-reverse-proxy provider above and point your existing tunnel at the plugin's HTTP backend:
|
|
59
|
+
|
|
60
|
+
1. In **Mobile access → Remote → Self-hosted → Own reverse proxy**, fill in: the public HTTPS address as your tunnel's public hostname (for example `https://dsh.example.com`), the private listen IP as `127.0.0.1`, an unused backend port (default `3444`), and the allowed source as `127.0.0.0/8`.
|
|
61
|
+
2. Select **Save and start backend** and copy the HTTP backend address the panel shows.
|
|
62
|
+
3. For a locally managed tunnel, update the matching `ingress` entry's `service` while keeping your existing tunnel identity, credentials and other routes. This is an excerpt, not a replacement configuration:
|
|
63
|
+
|
|
64
|
+
```yaml
|
|
65
|
+
tunnel: <your tunnel ID>
|
|
66
|
+
ingress:
|
|
67
|
+
- hostname: dsh.example.com
|
|
68
|
+
service: http://127.0.0.1:3444
|
|
69
|
+
- service: http_status:404
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
4. Apply the change using your existing deployment procedure, restarting the service if required. For a dashboard-managed tunnel, edit the public hostname's service in Cloudflare instead of creating a local configuration file. **The plugin never starts, stops, reloads or removes that service, and never reads its configuration or Token.**
|
|
73
|
+
|
|
74
|
+
The split is deliberate: **you own the tunnel, DNS and public certificate; the plugin owns device pairing and DSH authentication.** The backend still enforces device pairing, exact Host/Origin checks and CSRF, so pointing a tunnel at it does not expose a bare DSH to the internet.
|
|
75
|
+
|
|
76
|
+
Two things to watch:
|
|
77
|
+
|
|
78
|
+
- **Avoid the port clash.** The plugin's own cloudflared component also defaults to `3444`. Only one remote provider should run at a time; stop the plugin-managed one before switching, or pick a different port here.
|
|
79
|
+
- **Use the HTTP backend address shown by the panel.** The original DSH Web port (which may differ from `3080`) is not this protected backend. The LAN HTTPS entry (commonly `3443`) has separate trust and pairing and is not the HTTP backend for this mode; do not assume that the panel rejects every incorrect external tunnel target.
|
|
80
|
+
|
|
56
81
|
### Nginx and IPv6
|
|
57
82
|
|
|
58
83
|
The phone's public IPv6 connection to Nginx and Nginx's HTTP connection to DSH Mobile are separate connections. **An IPv6 public entry does not require an IPv6 backend.** On the same computer, Nginx can accept public IPv6 and forward to `http://127.0.0.1:3444`; the source CIDR remains IPv4 loopback. For an explicit `::1` backend, use `http://[::1]:3444` and `::1/128` instead.
|
|
@@ -48,12 +48,37 @@ CIDR 限制针对 TCP 连接的**直接来源地址**,不是手机 IP,也不
|
|
|
48
48
|
2. 代理目标使用面板给出的 **HTTP 后端地址**,而不是手机使用的 HTTPS 地址。
|
|
49
49
|
3. **保留请求的外部 Host,包含非默认端口。** 上例后端必须收到 `Host: phone.example.com:8815`,不能改成 `192.168.50.10:3444`,也不能漏掉 `:8815`。
|
|
50
50
|
4. 透传浏览器的 Origin、Cookie、Set-Cookie,以及认证/CSRF 相关头,不要改写 Cookie 的域或安全属性;不要缓存配对或认证响应。
|
|
51
|
-
5. 透传 WebSocket 升级(HTTP/1.1、Upgrade、Connection)以及双向数据。已有的 WebSocket
|
|
51
|
+
5. 透传 WebSocket 升级(HTTP/1.1、Upgrade、Connection)以及双向数据。已有的 WebSocket 路径白名单继续生效;第三方插件需要时仍在**连接诊断**面板中单独允许其路径。
|
|
52
52
|
|
|
53
53
|
[Lucky 官方 Web 文档](https://www.lucky666.cn/docs/modules/web/)说明其支持 WebSocket。配置界面随版本变化,但本插件要求不变:保留外部请求 Host,不要启用“使用目标地址Host”;若版本提供自定义 Host,请填写完整公网主机名及端口。TLS/证书配置在 Lucky,不在这个 HTTP 后端上配置。
|
|
54
54
|
|
|
55
55
|
若代理在另一台机器上,还需由管理员保证网络可达,并将主机防火墙入站范围限制到代理的实际私网来源;此功能不自动改防火墙。
|
|
56
56
|
|
|
57
|
+
### 已经自己运行 cloudflared 时
|
|
58
|
+
|
|
59
|
+
如果你已经在用官方方式配置了命名隧道(`cloudflared tunnel`,可能是 systemd、launchd 或 Windows 服务),**不需要让插件再装一份 cloudflared,也不需要在插件里保存隧道 Token**。用上面的自备代理模式,把你已有的隧道指向插件的 HTTP 后端即可:
|
|
60
|
+
|
|
61
|
+
1. 在电脑端 **移动访问 → 远程 → 自建连接 → 自有反向代理** 里填写:公网 HTTPS 地址填你隧道的公开主机名(例如 `https://dsh.example.com`),私有监听 IP 填 `127.0.0.1`,后端端口填一个未占用的值(默认 `3444`),允许来源填 `127.0.0.0/8`。
|
|
62
|
+
2. 点击 **保存并启动后端**,复制面板给出的 HTTP 后端地址。
|
|
63
|
+
3. 本地管理的隧道只需修改对应 `ingress` 的 `service`,保留已有隧道身份、凭据及其他路由。以下仅为片段,不要覆盖整份配置:
|
|
64
|
+
|
|
65
|
+
```yaml
|
|
66
|
+
tunnel: <你的隧道 ID>
|
|
67
|
+
ingress:
|
|
68
|
+
- hostname: dsh.example.com
|
|
69
|
+
service: http://127.0.0.1:3444
|
|
70
|
+
- service: http_status:404
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
4. 按现有部署方式应用变更,必要时重启服务。通过 Cloudflare 控制台管理的隧道,应在那里修改公开主机名对应的服务地址,不必新建本地配置文件。**插件不会启动、停止、重载或删除这个服务**,也不会读取它的配置或 Token。
|
|
74
|
+
|
|
75
|
+
这样分工是清楚的:**隧道、DNS 和公网证书由你管理,设备配对与 DSH 认证由插件管理**。插件的后端仍然执行完整的设备配对、Host/Origin 校验和 CSRF 检查,所以隧道指向它并不会把裸 DSH 暴露到公网。
|
|
76
|
+
|
|
77
|
+
需要注意的两点:
|
|
78
|
+
|
|
79
|
+
- **端口别冲突。** 插件自己的 cloudflared 组件也默认用 `3444`。同一时刻只应有一个远程提供方在运行;改用自备代理前先停掉插件托管的那份,或者在这里换一个端口。
|
|
80
|
+
- **以面板实际展示的 HTTP 后端地址为准。** DSH 原始网页端口可能不是 `3080`,它也不是这里受保护的后端;局域网 HTTPS 入口(常见为 `3443`)有独立的信任和配对,也不是本模式的 HTTP 后端。不要假定面板会拒绝所有错误的外部隧道目标。
|
|
81
|
+
|
|
57
82
|
### Nginx 与 IPv6
|
|
58
83
|
|
|
59
84
|
手机到 Nginx 的公网 IPv6 连接,与 Nginx 到 DSH Mobile 的 HTTP 后端连接是两段独立连接。**公网入口使用 IPv6,不要求后端也使用 IPv6**。同机 Nginx 可以通过 IPv6 接收手机请求,再代理到 `http://127.0.0.1:3444`;这时来源 CIDR 仍是 IPv4 回环。若后端明确监听 `::1`,Nginx 目标改为 `http://[::1]:3444`,来源改为 `::1/128`。
|
|
@@ -86,7 +111,7 @@ location / {
|
|
|
86
111
|
|
|
87
112
|
**“后端已监听”只证明本地 HTTP 监听成功,不代表公网 HTTPS、证书或 WebSocket 已成功。** 自备代理模式的连接诊断也只报告本地状态,不自动向公网地址探测。
|
|
88
113
|
|
|
89
|
-
在电脑端点击 **生成远程配对二维码**,再在 Android App **0.4.0 或更高版本**的 **远程访问** 流程扫码(不要使用 LAN
|
|
114
|
+
在电脑端点击 **生成远程配对二维码**,再在 Android App **0.4.0 或更高版本**的 **远程访问** 流程扫码(不要使用 LAN 扫码流程)。使用受信任证书的自有域名也可在手机浏览器中完成配对;现有自有域名逻辑保留 HTTPS 自定义端口,无需为此功能修改 APK。
|
|
90
115
|
|
|
91
116
|
上线前,必须用手机从目标外网实际检查:
|
|
92
117
|
|
|
@@ -18,6 +18,8 @@ If saving reports a dependency conflict, retain the required module or also dese
|
|
|
18
18
|
- First compare the normal computer layout. Developers can also open `/?frontend=stock` on the authenticated mobile Origin to diagnose boot and layout behavior. Gateway authentication and HTTPS checks remain; this entry skips dedicated mobile boot rewriting and module selection, but installed client adaptation and authenticated customizations may still apply. It is not a plugin-free control; some API operations may be rejected, so it does not replace normal mobile access.
|
|
19
19
|
- When stock has a background but mobile does not, inspect the skin's mounting container and fallback for other layouts. WebSocket approval, APK reinstallation or making every container transparent cannot guarantee a fix.
|
|
20
20
|
- A see-through sidebar, unreadable text shadows and an empty trace need separate diagnosis, not a single missing-background explanation. For an empty trace, inspect the first client exception, actual layout dimensions and whether its module loaded. A static screenshot does not distinguish rendering failure, occlusion and connection failure.
|
|
21
|
+
- **The mobile chrome does not depend on the skin**: the drawer, the right detail panel and the panel return bar composite `--dsw-alias-bg-layer-1` (the return bar uses `--dsw-alias-bg-base`) over the opaque CSS `Canvas` system color. A skin that makes those tokens translucent, or leaves them unresolvable, no longer shows conversation text behind the sidebar labels; a still see-through surface then comes from the skin's own decoration layer, not the chrome base.
|
|
22
|
+
- **Page-level styles injected by a skin travel with the page**: wallpapers and whole-page palettes are injected into the HTML by the plugin on the host, so deselecting that skin's client module does not remove them (module selection covers client modules only). Disable the whole plugin to stop loading them.
|
|
21
23
|
|
|
22
24
|
For example, the published `maid-atelier` 0.1.7 package mounts its background in the stock `centerCol` container. Its repository's fallback for other layouts does not establish that an installed package contains the same correction. DSH Mobile does not imitate that class or move the skin's nodes. A skin supporting mobile can locate its decoration with the existing `[data-pane="conversation"]` and `[data-pane="sidebar"]` markers, or use DSH public theme variables. The skin must still own sizing, stacking, cleanup and light/dark behavior without obscuring text or hit targets. This guide does not establish full skin acceptance. See [#202](https://github.com/saya-ch/dsh-mobile/issues/202).
|
|
23
25
|
|
|
@@ -18,6 +18,8 @@ DSH Mobile 在已认证的移动页面中使用专用根布局,继续渲染 DS
|
|
|
18
18
|
- 先与电脑上的原生布局对照。开发者还可在已认证移动 Origin 打开 `/?frontend=stock` 作启动与布局诊断;它保留 Gateway 认证与 HTTPS 检查,跳过专用移动启动改写和模块选择,但仍可能加载客户端移动适配及已认证定制,并非不含插件的对照页。部分 API 操作可能被拒绝,不能代替正常移动入口。
|
|
19
19
|
- 若原生布局有背景而移动布局没有,检查皮肤背景的挂载容器及其对非原生布局的回退逻辑;单纯放行 WebSocket、重装 APK 或把全部容器设为透明不能保证修复。
|
|
20
20
|
- 侧栏透底、文字阴影难读和轨迹空白应分别排查,不能都归为“少了一张背景图”。轨迹空白时还需检查首个客户端异常、实际布局尺寸和是否加载了相应模块;仅从静态截图不能判断是渲染异常、遮挡还是连接问题。
|
|
21
|
+
- **移动外壳的底板不依赖皮肤**:抽屉、右侧详情和面板返回栏把 `--dsw-alias-bg-layer-1`(返回栏用 `--dsw-alias-bg-base`)叠在不透明的 CSS `Canvas` 系统色上。皮肤把这些 token 设成半透明,或让它们解析不到,会话内容都不会再透到侧栏文字后面;若此时仍透底,来源是皮肤自己的装饰层,而不是外壳底板。
|
|
22
|
+
- **皮肤注入的整页样式会跟着页面走**:壁纸与整页配色由插件在服务端注入 HTML,取消该皮肤的客户端模块不会移除它们(模块选择只覆盖客户端模块)。要彻底不加载,请在插件层禁用。
|
|
21
23
|
|
|
22
24
|
例如 `maid-atelier` 0.1.7 发布包的背景依赖原生 `centerCol` 容器;皮肤仓库源码中的非原生布局回退不代表已安装包包含相同修正。DSH Mobile 不伪造这个类名或移动皮肤节点。支持移动布局的皮肤可以利用现有 `[data-pane="conversation"]`、`[data-pane="sidebar"]` 标记定位自己的装饰,或使用 DSH 公共主题变量;皮肤仍需自行处理尺寸、层叠、关闭清理和明暗主题,装饰不得遮挡文字或点击区域。本指南不表示整套皮肤已完成兼容验收。参见 [#202](https://github.com/saya-ch/dsh-mobile/issues/202)。
|
|
23
25
|
|
|
@@ -8,7 +8,7 @@ Start with the actual channel rather than treating every delay as a DSH heartbea
|
|
|
8
8
|
|
|
9
9
|
## Identify the stage that fails
|
|
10
10
|
|
|
11
|
-
First record the DSH, DSH Mobile plugin and Android app versions. On the computer, check the current channel under **Mobile Access →
|
|
11
|
+
First record the DSH, DSH Mobile plugin and Android app versions. On the computer, check the current channel under **Mobile Access → Diagnostics**, then inspect DSH startup logs and the browser's developer tools under Network → WS and update the component involved. The plugin and app release independently; their version numbers do not need to match. Remove Tokens, Cookies, and complete pairing URLs before sharing logs.
|
|
12
12
|
|
|
13
13
|
- **WebSocket never connects**: check for `101 Switching Protocols` and errors such as `401`, `403`, `404`, or `502`. Authentication, Host/Origin checks, proxy upgrade support, paths, and version differences can all cause this. Heartbeat adjustments do not resolve these failures. Allow blocked third-party plugin paths individually in Connection diagnostics; DSH's built-in paths do not need to be added again.
|
|
14
14
|
- **The request gets 101 but connections keep closing**: record the interval and compare the same page and Session through LAN and remote access. If a long Session repeatedly disconnects only through the remote channel while downloads saturate the link, investigate the heartbeat and initialization deadlines below. Browser close code `1006` means an abnormal end and does not identify which layer disconnected.
|
|
@@ -18,7 +18,7 @@ Both [#126](https://github.com/saya-ch/dsh-mobile/issues/126) and [#146](https:/
|
|
|
18
18
|
|
|
19
19
|
### HTTP rejection diagnostics (plugin 0.6.11+)
|
|
20
20
|
|
|
21
|
-
Plugin 0.6.11 and later write limited `auth failure` HTTP diagnostics to the plugin log (`$DSH_HOME/mobile-access/logs/dsh-mobile.log`): authorization versus CSRF rejection, status, method, a safe route or route category, related Cookie/header presence and counts, normalized Origin
|
|
21
|
+
Plugin 0.6.11 and later write limited `auth failure` HTTP diagnostics to the plugin log (`$DSH_HOME/mobile-access/logs/dsh-mobile.log`): authorization versus CSRF rejection, status, method, a safe route or route category, related Cookie/header presence and counts, normalized Origin, recognized fetch-site values and, when authorization is present, the first 8 characters of the device id. It omits tokens, Cookie values, query strings and arbitrary original paths. Each Gateway rate-limits its two categories separately: the first event is immediate and same-category rejections aggregate within a 30-second window; `suppressed` counts previously suppressed records of that category, not all requests or only the current path. This helps investigate missing credentials and CSRF failures; it does not automatically repair a 401/403. The absence of a record does not establish successful authentication: earlier Host/Origin rejections, WebSocket upgrades and native pairing/renewal are outside these two recording points. Review logs before sharing them.
|
|
22
22
|
|
|
23
23
|
### Internal authentication exchange diagnostics (plugin 0.6.15+)
|
|
24
24
|
|
|
@@ -108,6 +108,14 @@ These optional fields sit alongside `paths`; their defaults normally suffice:
|
|
|
108
108
|
|
|
109
109
|
Restart DSH and reopen the phone page after a change. Developer tools can show whether the WebSocket handshake negotiated `permessage-deflate`; a client that does not negotiate it can still connect without compression. Compare actual channel transfer volume and CPU use for the same Session, rather than judging savings from the decompressed message lengths shown in developer tools. Set `paths` back to `[]` to disable it. Compression does not raise provider quotas or replace connection troubleshooting.
|
|
110
110
|
|
|
111
|
+
### When it is worth enabling
|
|
112
|
+
|
|
113
|
+
Compression is most useful when large, compressible live messages cross a bandwidth-limited link. In an isolated Gateway/`ws` test with synthetic repetitive text, an 8 KiB message used 8,196 bytes without compression and 249 bytes with it; a 64 KiB sample used 65,546 and 692 bytes. These are WebSocket frame bytes, not TLS/TCP overhead or measurements of a real Session. Savings depend strongly on the content.
|
|
114
|
+
|
|
115
|
+
With the default 1 KiB threshold and no-context-takeover negotiation, the tested 1,023-byte message stayed uncompressed. Incompressible 64 KiB data grew by 22 bytes and added about 1.1 ms to the local round trip. A local bandwidth-shaped test showed lower delivery latency for repetitive messages, but does not predict any particular cellular, relay or LAN result; sustained-load memory and physical-device behavior were not measured.
|
|
116
|
+
|
|
117
|
+
Compare the same workload with and without compression before drawing a conclusion. HTTP history responses and `/api/remote.mux` frames are separate paths: a faster Session switch after several simultaneous upgrades cannot be attributed to WebSocket compression alone. Compression remains opt-in.
|
|
118
|
+
|
|
111
119
|
## Static-resource caching and repeated downloads
|
|
112
120
|
|
|
113
121
|
Owned static resources (`/mobile-access/compat.js`, `mobile-layout.js` and custom CSS/JS) use quoted content ETags and `Cache-Control: private, no-cache`. A browser may store the body but must revalidate before reuse. The gateway checks device authorization and the current resource before processing conditional GET/HEAD requests: unchanged content receives `304`, while a file edit returns the new body. Actual cache reuse still depends on browser behavior.
|
package/docs/SLOW_CONNECTIONS.md
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
|
|
9
9
|
## 先判断重连发生在哪一步
|
|
10
10
|
|
|
11
|
-
先记录 DSH、DSH Mobile 插件和 Android App 的版本,再在电脑端 **移动访问 →
|
|
11
|
+
先记录 DSH、DSH Mobile 插件和 Android App 的版本,再在电脑端 **移动访问 → 诊断** 检查当前通道;查看 DSH 启动日志和浏览器开发者工具的 Network → WS,按问题涉及的组件更新。插件与 App 独立发版,版本号不必相同。分享日志时去掉 Token、Cookie 和完整配对地址。
|
|
12
12
|
|
|
13
13
|
- **WebSocket 没有连接成功**:检查请求是否获得 `101 Switching Protocols`,并留意 `401`、`403`、`404`、`502` 等错误。认证、Host/Origin、反向代理升级支持、连接路径或版本差异都可能造成这种情况。调整心跳不能解决这些问题;第三方插件被拦截的路径可在连接诊断中按需允许,不必把 DSH 内置路径全部重新添加。
|
|
14
14
|
- **已获得 101,但连接反复关闭**:记录关闭间隔,并对比同一页面、同一会话的局域网与远程访问。如果只在远程打开长会话时频繁断开,同时下载长时间占满链路,才进一步检查下面的心跳和初始化等待时间。浏览器显示 `1006` 表示连接异常结束,本身不能确定是哪一层断开。
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
|
|
19
19
|
### HTTP 拒绝诊断(插件 0.6.11 起)
|
|
20
20
|
|
|
21
|
-
插件 0.6.11 起会在插件日志(`$DSH_HOME/mobile-access/logs/dsh-mobile.log`)记录有限的 `auth failure` HTTP 诊断:区分授权与 CSRF 拒绝,包含状态、方法、安全路径或路径类别、相关 Cookie/请求头是否存在及计数、规范化 Origin
|
|
21
|
+
插件 0.6.11 起会在插件日志(`$DSH_HOME/mobile-access/logs/dsh-mobile.log`)记录有限的 `auth failure` HTTP 诊断:区分授权与 CSRF 拒绝,包含状态、方法、安全路径或路径类别、相关 Cookie/请求头是否存在及计数、规范化 Origin、受支持的 fetch-site 值,以及有授权时设备标识的前 8 位,不记录令牌、Cookie 值、查询参数或任意原始路径。每个网关的两类诊断分别限频,首条立即记录,30 秒窗口内同类拒绝聚合;`suppressed` 表示此前被抑制的同类记录数量,不是全部请求数,也不限定于当前路径。它帮助排查凭据未携带或 CSRF 校验失败,不会自动修复 401/403。没有日志也不代表认证成功:更早的 Host/Origin 拒绝、WebSocket 升级和原生配对/续期不在这两处记录范围内。分享前仍应检查日志。
|
|
22
22
|
|
|
23
23
|
### 内部认证交换诊断(插件 0.6.15 起)
|
|
24
24
|
|
|
@@ -108,6 +108,14 @@ websocketCompression:
|
|
|
108
108
|
|
|
109
109
|
修改后重启 DSH 并重新打开手机页面。可在开发者工具中查看 WebSocket 握手是否协商了 `permessage-deflate`;客户端没有协商时仍可无压缩连接。对比同一会话的实际通道传输量与 CPU 使用,不能仅以开发者工具显示的解压后消息长度判断节省比例。需要关闭时把 `paths` 改回 `[]`;压缩不能提高服务商限额,也不能替代连接故障排查。
|
|
110
110
|
|
|
111
|
+
### 什么时候值得开启
|
|
112
|
+
|
|
113
|
+
可压缩的大消息经过受限带宽时,压缩通常更有价值。在隔离 Gateway/`ws` 测试中,合成的重复文本样本从 8 KiB 对应的 8,196 字节降到 249 字节,从 64 KiB 对应的 65,546 字节降到 692 字节。这是 WebSocket 帧字节,不含 TLS/TCP 开销,也不是实际会话的测量;压缩率取决于具体内容。
|
|
114
|
+
|
|
115
|
+
使用默认 1 KiB 阈值并协商禁用上下文复用时,测试中的 1,023 字节消息没有压缩。不可压缩的 64 KiB 数据反而增加 22 字节,本地往返增加约 1.1 ms。局部限速测试中,重复文本的传递延迟有所下降,但不能据此预测具体蜂窝、转发或局域网体验;本轮未测量持续负载内存和真机行为。
|
|
116
|
+
|
|
117
|
+
请对相同工作负载分别开关压缩再比较。HTTP 历史响应与 `/api/remote.mux` 消息是不同路径,不能将同时升级多个组件后的会话切换改善全部归因于 WebSocket 压缩。该功能仍默认关闭、按需开启。
|
|
118
|
+
|
|
111
119
|
## 静态资源缓存与重复下载
|
|
112
120
|
|
|
113
121
|
网关自有静态资源(`/mobile-access/compat.js`、`mobile-layout.js`、自定义 CSS/JS)使用带引号的内容 ETag 和 `Cache-Control: private, no-cache`。浏览器可保存正文,但每次复用前必须重新校验;网关先检查设备授权和当前资源,再处理 GET/HEAD 条件请求,内容未变时返回 `304`,文件改动后返回新正文。实际缓存复用仍取决于浏览器行为。
|
|
@@ -24,3 +24,20 @@ DSH Mobile's default Windows HTTPS / Discovery inbound rules allow only `LocalSu
|
|
|
24
24
|
A routed network may not support LAN broadcast discovery. If the computer is not discovered, use its displayed pairing link or QR code; routing, firewall access, and the HTTPS entry must still work. Adding an IPv6 CIDR does not create an IPv6 listener.
|
|
25
25
|
|
|
26
26
|
This setting controls source access to the LAN Gateway, not source CIDRs for an external reverse proxy. Configure that separately with the [own HTTPS reverse proxy guide](SELF_HOSTED_ORIGIN.en.md). Do not expose the LAN Gateway or private HTTP backend directly to the public internet.
|
|
27
|
+
|
|
28
|
+
## Accessing the NAS administration page
|
|
29
|
+
|
|
30
|
+
The administration page's `/api/mobile-access` and the phone Gateway are separate entries. The additional trusted networks above do not open the management API. By default, the management API still accepts only direct loopback peers.
|
|
31
|
+
|
|
32
|
+
Plugin 0.6.18 adds `adminAllowedCidrs` for NAS deployments already accessed through a controlled LAN. Add this field to the existing `mobile-access` entry's complete `config`, replacing the example with the administration computer's actual address:
|
|
33
|
+
|
|
34
|
+
```yaml
|
|
35
|
+
adminAllowedCidrs:
|
|
36
|
+
- 192.168.50.23/32
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
This is only the additional field, **not a complete replacement `config`**. DSH entry overrides replace the whole configuration; retain the existing `setupFile`, `stateFile`, `controlFile`, TLS and other custom settings. Restart DSH after editing.
|
|
40
|
+
|
|
41
|
+
This option does not change DSH's listener, routing or firewall, or open a public management entry. It accepts only the listed direct TCP peers, never `X-Forwarded-For`, and also requires the current request to pass DSH session authentication. Sign in to DSH normally first. A version without usable authentication, a deployment with authentication disabled or a request without credentials cannot gain management access merely through a CIDR. Prefer a single administration computer's `/32`; the limit is 32 entries, with no all-address `/0` or duplicate networks.
|
|
42
|
+
|
|
43
|
+
Existing private-IP/loopback Host restrictions, exact Origin checks, cross-site rejection and denied CORS preflights remain. The management API does not accept arbitrary DNS names or public Hosts. A proxy's direct address may represent several visitors: the proxy must restrict access, retain DSH authentication and never add CORS permission for this path. Plain HTTP on a LAN does not prevent interception; use HTTPS or SSH forwarding on uncontrolled networks, and never publish `/api/mobile-access`. Remove the field or set an empty list to restore the default without deleting pairings.
|
package/docs/TRUSTED_NETWORKS.md
CHANGED
|
@@ -24,3 +24,20 @@ DSH Mobile 的默认 Windows HTTPS / Discovery 入站规则只允许 `LocalSubne
|
|
|
24
24
|
路由网络不一定支持局域网广播发现。发现列表没有电脑时,可使用电脑显示的配对链接或二维码,但路由、防火墙和 HTTPS 入口仍须可达。填写 IPv6 CIDR 也不会自动增加 IPv6 监听。
|
|
25
25
|
|
|
26
26
|
此设置用于局域网 Gateway 的来源访问范围,不改变外部反向代理的来源 CIDR。自有代理请按[自有 HTTPS 反向代理指南](SELF_HOSTED_ORIGIN.md)配置;不要把局域网 Gateway 或私有 HTTP 后端映射到公网。
|
|
27
|
+
|
|
28
|
+
## NAS 的管理网页访问
|
|
29
|
+
|
|
30
|
+
管理网页的 `/api/mobile-access` 与手机连接的 Gateway 是两个入口。上面的额外可信网段设置不会开放管理 API。默认情况下,管理 API 仍只允许直连来源为回环地址。
|
|
31
|
+
|
|
32
|
+
插件 0.6.18 起提供 `adminAllowedCidrs`,供已经通过受控局域网访问 DSH 的 NAS 部署使用。在现有 `mobile-access` 条目的完整 `config` 中追加以下字段,并将示例改成管理电脑的实际地址:
|
|
33
|
+
|
|
34
|
+
```yaml
|
|
35
|
+
adminAllowedCidrs:
|
|
36
|
+
- 192.168.50.23/32
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
这只是新增字段,**不是可直接替换的完整 `config`**。DSH 的条目覆盖会替换整个配置;请保留原有 `setupFile`、`stateFile`、`controlFile`、TLS 和其他自定义设置。修改后重启 DSH。
|
|
40
|
+
|
|
41
|
+
此选项不改变 DSH 的监听地址、路由或防火墙,也不会打开公网管理入口。仅允许列出的直接 TCP 来源,不读取 `X-Forwarded-For`;同时要求当前请求通过 DSH 的会话认证。浏览器须先正常登录 DSH;没有可用认证能力的版本、关闭认证的部署或无凭据请求不能靠填写 CIDR获得管理权限。尽量使用单台管理电脑的 `/32`,最多 32 项,不接受全地址 `/0` 或重复网段。
|
|
42
|
+
|
|
43
|
+
现有私有 IP/回环 Host 限制、精确 Origin、跨站检查和拒绝 CORS 预检的行为保持不变。管理 API 不接受任意域名或公网 Host。反向代理的直接地址可能代表多名访问者:代理必须限制访问、保留 DSH 认证、不能给此路径添加跨域许可。HTTP 局域网也不能防止链路窃听;不受控网络请使用 HTTPS 或 SSH 转发,不要公开 `/api/mobile-access`。恢复默认时移除该字段或设为空列表,不会删除配对数据。
|