@eduwork/dsh-remote-access 0.0.0-stage → 0.1.1
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 +27 -0
- package/LICENSE +21 -0
- package/README.md +94 -2
- package/README_EN.md +95 -0
- package/THIRD_PARTY_NOTICES.md +9 -0
- package/cordis.patch.yml +5 -0
- package/docs/DEPLOYMENT.md +168 -0
- package/docs/DEPLOYMENT_EN.md +168 -0
- package/docs/PROTOCOL.md +129 -0
- package/lib/THIRD_PARTY_LICENSES.txt +728 -0
- package/lib/client.js +105 -0
- package/lib/index.js +22275 -0
- package/lib/relay.js +4247 -0
- package/lib/typert.js +38 -0
- package/lib/web/icon.png +0 -0
- package/lib/web/icon.svg +1 -0
- package/lib/web/index.html +18 -0
- package/lib/web/loader.css +24 -0
- package/lib/web/loader.js +1 -0
- package/lib/web/manifest.webmanifest +21 -0
- package/lib/web/preamble.js +1 -0
- package/lib/web/sw.js +1 -0
- package/package.json +150 -4
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# 变更记录 / Changelog
|
|
2
|
+
|
|
3
|
+
## 0.1.1 — 2026-10-24
|
|
4
|
+
|
|
5
|
+
- 随 npm 包提供中英文自托管中继部署指南:固定版本启动、Key、HTTPS/Nginx、路径前缀、systemd、OIDC、iframe 与排错。
|
|
6
|
+
- 澄清同源集成的信任范围,以及直接终端接口与 Agent 权限的区别;运行代码与协议不变。
|
|
7
|
+
|
|
8
|
+
- Include bilingual relay deployment guides covering pinned npm startup, access keys, HTTPS/Nginx, path prefixes, systemd, OIDC, iframe integration and troubleshooting.
|
|
9
|
+
- Clarify same-origin trust boundaries and direct terminal APIs versus Agent permissions; runtime code and protocol are unchanged.
|
|
10
|
+
|
|
11
|
+
## 0.1.0 — 2026-10-23
|
|
12
|
+
|
|
13
|
+
- 首个版本:在手机或其他电脑的浏览器中使用本机的 DSH,包含 DSH 插件与设置页、可自托管的中继和网页客户端。
|
|
14
|
+
- 连接端到端加密;新设备须在电脑上核对配对码并允许,可逐台移除。
|
|
15
|
+
- 远程设备可查看与新建会话、继续或停止任务、审批与回答提问、预览与下载成果;设置只能查看,账号、凭据、插件管理等仅限本机。
|
|
16
|
+
- 手机上沿用 DSH 自己的界面,按窄屏调整侧栏与设置弹窗。
|
|
17
|
+
- 中继可凭机构登录的 ID Token 或接入密钥接纳电脑,并限制每个账号的电脑数和连接频率;发行版可预置机构的中继,用户登录后即可使用。
|
|
18
|
+
- 支持带路径前缀的中继地址;通过 `RELAY_FRAME_ANCESTORS` 配置允许嵌入的门户来源,默认禁止嵌入。
|
|
19
|
+
- 随包提供协议文档;Node.js 最低版本为 24.22.1,与部署说明中的安全更新基线一致。
|
|
20
|
+
|
|
21
|
+
- First version: use DSH on this computer from a browser on a phone or another computer, with the DSH plugin and its settings page, a self-hostable relay and the web client.
|
|
22
|
+
- Connections are end-to-end encrypted; a new device must be allowed on the computer after checking its pairing code, and devices can be removed one by one.
|
|
23
|
+
- Remote devices can view and start sessions, continue or stop tasks, approve and answer questions, and preview and download results; settings are view only, and accounts, credentials and plugin management stay on the computer.
|
|
24
|
+
- Phones get DSH's own interface, with the sidebar and the settings dialog fitted to narrow screens.
|
|
25
|
+
- The relay admits computers by an organization's ID Token or by an access key, and limits computers per account and connection rates; a distribution can preset its organization's relay, ready once the user signs in.
|
|
26
|
+
- Relay URLs support path prefixes; `RELAY_FRAME_ANCESTORS` configures which portals may embed the page, with embedding denied by default.
|
|
27
|
+
- Includes the protocol documentation; requires Node.js 24.22.1 or newer, matching the security update baseline in the deployment guide.
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 East China Normal University
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,95 @@
|
|
|
1
|
-
#
|
|
1
|
+
# 远程访问
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[English](README_EN.md)
|
|
4
|
+
|
|
5
|
+
`@eduwork/dsh-remote-access` 让你在手机或其他电脑的浏览器里使用另一台电脑上的 DeepSeek Harness(DSH):查看和新建会话、继续或取消任务、审批、回答提问、查看和下载结果。连接经自托管的中继服务器转发,端到端加密,中继看不到内容。每台设备都要在电脑上核对配对码、确认后才能连接,也可以随时移除。
|
|
6
|
+
|
|
7
|
+
包里有两部分:
|
|
8
|
+
|
|
9
|
+
- **DSH 插件**:运行在被访问的电脑上,在设置页开关远程访问、添加和移除设备,并让 DSH 的界面适合手机屏幕。
|
|
10
|
+
- **中继服务**:部署在有公网地址的服务器上,转发密文,并提供手机上打开的网页。
|
|
11
|
+
|
|
12
|
+
## 使用
|
|
13
|
+
|
|
14
|
+
### 部署中继
|
|
15
|
+
|
|
16
|
+
需要 Node.js 24.22.1 或更新版本,以及为中继域名提供 HTTPS 并转发 WebSocket 的反向代理。
|
|
17
|
+
|
|
18
|
+
```sh
|
|
19
|
+
RELAY_URL=https://remote.example.edu/ RELAY_ACCESS_KEYS=替换成随机Key \
|
|
20
|
+
npx --yes --package=@eduwork/dsh-remote-access@0.1.1 eduwork-remote-relay
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
`RELAY_URL` 是用户访问中继的公开地址;`RELAY_ACCESS_KEYS` 是发给电脑主人的接入密钥,多个用逗号分隔。中继默认监听 `127.0.0.1:8787`,可用 `HOST`、`PORT` 修改;`<RELAY_URL>healthz` 返回 `ok`,可用于监控。
|
|
24
|
+
|
|
25
|
+
完整的 [中继部署指南](docs/DEPLOYMENT.md) 包含 Key 生成、Windows PowerShell 命令、HTTPS/Nginx、路径前缀、systemd 常驻运行、机构登录和 iframe 集成,以及启动后的验证与排错步骤。
|
|
26
|
+
|
|
27
|
+
中继也可以部署在同域的单独路径,例如 `RELAY_URL=https://example.edu/eduwork-remote/`。反向代理须保留此前缀,电脑上填写同一个完整地址。同域路径不隔离浏览器权限,部署者须确认站点与被配对电脑处于可接受的共同信任范围(见[安全](#安全));作用于整个站点的 Service Worker 还须放过这段路径。
|
|
28
|
+
|
|
29
|
+
学校或企业也可以让成员凭自己的登录使用中继,不必逐个发接入密钥:`RELAY_OIDC_ISSUER` 填机构 OpenID Connect 登录的 issuer(例如 `https://sso.example.edu`),`RELAY_OIDC_CLIENT_IDS` 填桌面应用在该登录中的 client ID,多个用逗号分隔。电脑以登录得到的 ID Token 注册,中继用 issuer 公布的公钥验证,只记录用户标识,不记录 Token。Token 到期前电脑会自动换新的;到期仍未换新时,中继断开这台电脑现有的远程连接。机构登录失效、需要重新登录时,电脑停止连接中继,设置页提示重新登录。两种方式可以同时启用。
|
|
30
|
+
|
|
31
|
+
中继限制每个账号最多同时注册 5 台电脑,每台电脑每分钟最多接受 60 个设备连接,同一地址一分钟内注册被拒 10 次后要等待。中继在反向代理后面时,用 `RELAY_CLIENT_IP_HEADER` 指定代理传递客户端地址的请求头(例如 `x-real-ip`),否则所有用户共用代理的地址。
|
|
32
|
+
|
|
33
|
+
中继的网页默认不允许被其他页面嵌入。机构网站需要用 iframe 嵌入它时,用 `RELAY_FRAME_ANCESTORS` 列出允许嵌入的页面来源,多个用空格分隔:与中继同源的页面写 `self`,其他页面写它的来源,例如 `https://portal.example.edu`。命令行和 env 文件都会去掉引号,所以 `self` 与 `'self'` 等效;写多个来源时整个值加双引号,例如 `RELAY_FRAME_ANCESTORS="self https://portal.example.edu"`。iframe 不要加 `sandbox` 属性,中继网页需要运行脚本、注册 Service Worker 和下载文件。嵌入的页面应与中继属于同一站点(主域名相同,例如 `portal.example.edu` 与 `remote.example.edu`):跨站嵌入时,Safari 等 WebKit 浏览器无法在其中加载电脑的界面。
|
|
34
|
+
|
|
35
|
+
### 在电脑上开启
|
|
36
|
+
|
|
37
|
+
在 DSH 中安装插件后重启:
|
|
38
|
+
|
|
39
|
+
```sh
|
|
40
|
+
dsh plugin --profile web add @eduwork/dsh-remote-access
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
打开“设置 → 远程访问”,填写中继服务器和接入密钥,勾选“允许远程访问”。显示“已连接”后即可添加设备。远程访问默认关闭。
|
|
44
|
+
|
|
45
|
+
机构的发行版可以预置自己的中继和登录(插件设置 `organization: { relay, oidcProfileId }`,`oidcProfileId` 是 [dsh-oidc](../dsh-oidc/README.md) 中的机构配置)。这时设置页不显示中继和接入密钥:登录机构账号并勾选“允许远程访问”即可,退出登录后远程访问随之停止。
|
|
46
|
+
|
|
47
|
+
机构登录模式还要求宿主安装提供 `identityToken(profileID)` 接口的 `@eduwork/dsh-oidc@0.3.1` 或后续兼容版本;旧版 `0.3.0` 不包含该接口。使用接入密钥的独立部署不依赖 OIDC 插件。
|
|
48
|
+
|
|
49
|
+
### 添加和移除设备
|
|
50
|
+
|
|
51
|
+
1. 在电脑上点“添加设备”,出现二维码和链接。链接 10 分钟内有效,只能用一次。
|
|
52
|
+
2. 在手机上扫码或打开链接,填写设备名称,点“开始配对”。
|
|
53
|
+
3. 确认手机和电脑上显示的 6 位配对码一致后,在电脑上点“允许”。
|
|
54
|
+
|
|
55
|
+
之后在这台设备上打开中继地址就会连接到电脑;断线后自动重连。iPhone 和 iPad 上请先把页面添加到主屏幕,从主屏幕打开后再粘贴配对链接:只在 Safari 里配对的设备,7 天不用会丢失配对。
|
|
56
|
+
|
|
57
|
+
在电脑的“已配对设备”里点“移除”,该设备立即断开,之后不能再连接。
|
|
58
|
+
|
|
59
|
+
## 远程设备能做什么
|
|
60
|
+
|
|
61
|
+
可以选择已有工作区,查看或新建会话,继续和取消任务,审批或回答提问,查看和下载结果;宿主已安装相应插件时,还可以使用 Studio 成果和日历。
|
|
62
|
+
|
|
63
|
+
手机上看到的就是 DSH 自己的界面,只按窄屏做了调整:会话列表(工作区目录、搜索、新会话等)从左上角打开并铺满屏幕,选中会话或面板后自动收起;设置同样铺满屏幕,各分区排成一行标签,在远程设备上只能查看;对话中的耗时、重试、审批和提问与电脑上一致。
|
|
64
|
+
|
|
65
|
+
远端不能直接调用打开本机窗口、程序或发出通知的接口,不能注册或删除工作区、修改设置、管理账号、插件、凭据、技能、记忆或远程访问本身,也不能直接使用终端与代码执行接口。**通过 Agent 发起的任务仍可能执行命令,沿用该会话的权限与审批规则**;禁止直接调用终端接口不等于禁止 Agent 使用工具。完整清单见 [src/gate/gate.ts](src/gate/gate.ts),未列出的接口一律拒绝。
|
|
66
|
+
|
|
67
|
+
## 安全
|
|
68
|
+
|
|
69
|
+
- 电脑和设备之间端到端加密,中继只转发密文。配对链接固定了电脑的公钥,中继无法冒充电脑。
|
|
70
|
+
- 设备密钥由浏览器生成且不可导出,电脑只保存设备公钥。每次连接都要用设备密钥签名。
|
|
71
|
+
- 接入密钥和机构登录只决定谁能使用这台中继,不能用来连接别人的电脑。接入密钥保存在 DSH 的凭据里(`EDUWORK_REMOTE_ACCESS_KEY`),不写进插件设置;机构登录的 ID Token 只发给发行版预置的中继,设置页不能更改这个地址。
|
|
72
|
+
- 手机上打开的网页由中继提供,部署中继的人可以修改它。请只使用你信任的中继。
|
|
73
|
+
- 手机上显示的 DSH 界面由所连的电脑提供,与中继网页同源。浏览器按来源(协议、主机、端口)而非路径隔离数据,因此一台电脑提供的界面能使用此浏览器与其他电脑的配对去连接它们。请只与自己的电脑配对。
|
|
74
|
+
- 同理,中继与其他网站同源时,那些网站的脚本能使用这里的配对连接电脑;任何一台被配对的电脑提供的界面,也能以用户的身份访问那些网站及脚本可访问的浏览器数据。独立域名能缩小信任范围;若选择同域路径集成,需要接受这项共同信任边界,路径前缀和普通 iframe 均不提供隔离。
|
|
75
|
+
- 允许其他页面嵌入中继的网页后,那些页面能把它显示在自己的页面里并加以遮挡,诱导用户点击(例如批准命令)。只允许你信任的页面嵌入。
|
|
76
|
+
|
|
77
|
+
协议细节见[协议文档](docs/PROTOCOL.md)。
|
|
78
|
+
|
|
79
|
+
## 贡献来源
|
|
80
|
+
|
|
81
|
+
本插件由 [@JunieXD](https://github.com/JunieXD) 在 [#192](https://github.com/ECNU/EduWork/pull/192) 中实现,承接了 [@Paraso42](https://github.com/Paraso42) 在 [#180](https://github.com/ECNU/EduWork/pull/180) 中的远程访问原型贡献:DSH 宿主接入点梳理、接口白名单与拒绝原因、设备信任与撤销模型,以及断线重连、避免重复执行和跨网络部署的验收场景。@Paraso42 是远程访问功能的合作贡献者;当前协议与实现以 #192 为准。
|
|
82
|
+
|
|
83
|
+
## 开发
|
|
84
|
+
|
|
85
|
+
在本包目录运行:
|
|
86
|
+
|
|
87
|
+
```sh
|
|
88
|
+
npm ci
|
|
89
|
+
npm run check
|
|
90
|
+
node scripts/check-web.ts
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
`check-web.ts` 在 Chromium 和 WebKit 中走完配对、加载、请求、断线重连和移除设备,需要本机已安装 Playwright 的浏览器,不在 CI 中运行。
|
|
94
|
+
|
|
95
|
+
[包维护与发布](https://github.com/ecnu/EduWork/blob/main/docs/PACKAGES.md) · [变更记录](CHANGELOG.md) · [代码许可](LICENSE) · [第三方声明](THIRD_PARTY_NOTICES.md)
|
package/README_EN.md
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
# Remote access
|
|
2
|
+
|
|
3
|
+
[简体中文](README.md)
|
|
4
|
+
|
|
5
|
+
`@eduwork/dsh-remote-access` lets you use DeepSeek Harness (DSH) on another computer from a browser on your phone or a second computer: view and start conversations, continue or cancel tasks, approve, answer questions, and view and download results. The connection passes through a self-hosted relay server and is end-to-end encrypted, so the relay cannot read it. Each device connects only after you compare a pairing code and confirm it on the computer, and you can remove it at any time.
|
|
6
|
+
|
|
7
|
+
The package has two parts:
|
|
8
|
+
|
|
9
|
+
- **DSH plugin**: runs on the computer being accessed. Its settings page switches remote access on and off and adds and removes devices, and it fits DSH's interface to phone screens.
|
|
10
|
+
- **Relay service**: runs on a server with a public address. It forwards ciphertext and serves the page you open on your phone.
|
|
11
|
+
|
|
12
|
+
## Use
|
|
13
|
+
|
|
14
|
+
### Deploy the relay
|
|
15
|
+
|
|
16
|
+
You need Node.js 24.22.1 or later and a reverse proxy that serves HTTPS for the relay's domain and forwards WebSockets.
|
|
17
|
+
|
|
18
|
+
```sh
|
|
19
|
+
RELAY_URL=https://remote.example.edu/ RELAY_ACCESS_KEYS=replace-with-a-random-key \
|
|
20
|
+
npx --yes --package=@eduwork/dsh-remote-access@0.1.1 eduwork-remote-relay
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
`RELAY_URL` is the public address users reach the relay at; `RELAY_ACCESS_KEYS` are the comma-separated access keys you give to computer owners. The relay listens on `127.0.0.1:8787` by default; change it with `HOST` and `PORT`. `<RELAY_URL>healthz` answers `ok` for monitoring.
|
|
24
|
+
|
|
25
|
+
The [relay deployment guide](docs/DEPLOYMENT_EN.md) covers key generation, Windows PowerShell commands, HTTPS/Nginx, path prefixes, persistent systemd operation, organization sign-in, iframe integration, verification and troubleshooting.
|
|
26
|
+
|
|
27
|
+
The relay can also share a domain under its own path, such as `RELAY_URL=https://example.edu/eduwork-remote/`. Preserve the prefix in proxy requests and enter the same complete URL on the computer. Paths do not isolate browser privileges: the operator must accept the shared trust boundary between the site's applications and paired computers (see [Security](#security)). A site-wide Service Worker must also leave this path alone.
|
|
28
|
+
|
|
29
|
+
A school or company can instead let its members use the relay with their own sign-in, without handing out access keys: set `RELAY_OIDC_ISSUER` to the issuer of the organization's OpenID Connect sign-in (for example `https://sso.example.edu`) and `RELAY_OIDC_CLIENT_IDS` to the desktop application's client IDs in it, separated by commas. Computers register with the ID Token their sign-in issued; the relay checks it against the keys the issuer publishes and keeps only the user's identifier, never the token. Computers switch to a new token before theirs expires; if one expires without being renewed, the relay ends that computer's remote connections. When the organization sign-in has lapsed and needs signing in again, the computer stops connecting to the relay and the settings page asks the user to sign in again. Both ways can be enabled together.
|
|
30
|
+
|
|
31
|
+
The relay lets each account register at most 5 computers at a time and each computer accept at most 60 device connections a minute; an address with 10 refused registrations in a minute has to wait. Behind a reverse proxy, set `RELAY_CLIENT_IP_HEADER` to the header in which the proxy passes the client's address (for example `x-real-ip`); otherwise all users share the proxy's address.
|
|
32
|
+
|
|
33
|
+
By default no other page may embed the relay's page. When an organization's site needs to embed it in an iframe, list the origins of the pages allowed to in `RELAY_FRAME_ANCESTORS`, separated by spaces: `self` for pages of the relay's own origin, or an origin such as `https://portal.example.edu` for others. Shells and env files strip quotes, so `self` and `'self'` are the same; quote the whole value when it lists several, for example `RELAY_FRAME_ANCESTORS="self https://portal.example.edu"`. Do not give the iframe a `sandbox` attribute: the relay's page runs scripts, registers a Service Worker and downloads files. The embedding page should be on the same site as the relay (the same registrable domain, such as `portal.example.edu` and `remote.example.edu`): embedded across sites, Safari and other WebKit browsers cannot load the computer's interface in it.
|
|
34
|
+
|
|
35
|
+
### Turn it on on the computer
|
|
36
|
+
|
|
37
|
+
Install the plugin in DSH and restart it:
|
|
38
|
+
|
|
39
|
+
```sh
|
|
40
|
+
dsh plugin --profile web add @eduwork/dsh-remote-access
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
Open Settings → Remote access, enter the relay server and the access key, and select "Allow remote access". Once it shows "Connected", you can add devices. Remote access is off by default.
|
|
44
|
+
|
|
45
|
+
An organization's distribution can preset its relay and sign-in (plugin setting `organization: { relay, oidcProfileId }`, where `oidcProfileId` names the organization's [dsh-oidc](../dsh-oidc/README_EN.md) profile). The settings page then shows no relay or access key: sign in with the organization's account and select "Allow remote access". Signing out stops remote access.
|
|
46
|
+
|
|
47
|
+
Organization sign-in also requires `@eduwork/dsh-oidc@0.3.1` or a later compatible version on the host, providing `identityToken(profileID)`; the older `0.3.0` does not include this API. Standalone deployments using an access key do not depend on the OIDC plugin.
|
|
48
|
+
|
|
49
|
+
### Add and remove devices
|
|
50
|
+
|
|
51
|
+
1. On the computer, choose "Add a device". A QR code and a link appear; the link works once, for 10 minutes.
|
|
52
|
+
2. On the phone, scan the code or open the link, enter a device name and choose "Pair".
|
|
53
|
+
3. Check that the phone and the computer show the same 6-digit pairing code, then choose "Allow" on the computer.
|
|
54
|
+
|
|
55
|
+
From then on, opening the relay address on that device connects to the computer, and it reconnects by itself after a drop. On iPhone and iPad, add the page to the Home Screen first, open it from there and paste the pairing link: a pairing made only in Safari is lost after 7 days without use.
|
|
56
|
+
|
|
57
|
+
Choose "Remove" under "Paired devices" on the computer to disconnect a device at once and keep it from connecting again.
|
|
58
|
+
|
|
59
|
+
## What remote devices can do
|
|
60
|
+
|
|
61
|
+
They can choose an existing workspace, view and start conversations, continue and cancel tasks, approve or answer questions, and view and download results. Studio results and the calendar are also available when those plugins are installed on the host.
|
|
62
|
+
|
|
63
|
+
A phone shows DSH's own interface, only fitted to the narrow screen: the session list (workspace folders, search, new session and so on) opens full screen from the top-left corner and closes once you pick a session or a panel; settings also fill the screen, with the sections as a row of tabs, and are view only on remote devices; conversations show durations, retries, approvals and questions as on the computer.
|
|
64
|
+
|
|
65
|
+
Remote devices cannot directly call APIs that open local windows or programs or show notifications, register or remove workspaces, change settings, manage accounts, plugins, credentials, skills, memories or remote access, or access terminal and code-execution APIs. **Tasks submitted through the Agent can still execute commands under the session's permission and approval rules**; blocking direct terminal APIs does not disable Agent tools. The full list is in [src/gate/gate.ts](src/gate/gate.ts); anything not listed is refused.
|
|
66
|
+
|
|
67
|
+
## Security
|
|
68
|
+
|
|
69
|
+
- Traffic between the computer and the device is end-to-end encrypted; the relay only forwards ciphertext. The pairing link pins the computer's public key, so the relay cannot impersonate the computer.
|
|
70
|
+
- The browser generates the device key as non-extractable; the computer stores only its public key. Every connection is signed with the device key.
|
|
71
|
+
- An access key or an organization sign-in only decides who may use the relay; neither can be used to connect to someone else's computer. The access key is kept in DSH's credentials (`EDUWORK_REMOTE_ACCESS_KEY`), not in the plugin's settings; the ID Token of an organization sign-in goes only to the relay the distribution preset, which the settings page cannot change.
|
|
72
|
+
- The relay serves the page you open on your phone, so whoever runs the relay can change it. Use only relays you trust.
|
|
73
|
+
- The DSH interface on your phone comes from the paired computer and shares the relay's origin. Browsers isolate data by origin (scheme, host and port), not path, so one computer's interface can use this browser's pairings with other computers to connect to them. Pair only with your own computers.
|
|
74
|
+
- Likewise, sites sharing the relay's origin can use its pairings, and the interface of any paired computer can access those sites as the user and read browser data available to scripts. A separate domain narrows this trust boundary. Same-origin path integration accepts the shared boundary; neither path prefixes nor ordinary iframes provide isolation.
|
|
75
|
+
- Pages allowed to embed the relay's page can show it within their own and cover parts of it to trick users into clicking (approving a command, say). Allow only pages you trust.
|
|
76
|
+
|
|
77
|
+
See the [protocol document](docs/PROTOCOL.md) (Chinese) for details.
|
|
78
|
+
|
|
79
|
+
## Contribution origins
|
|
80
|
+
|
|
81
|
+
[@JunieXD](https://github.com/JunieXD) implemented this plugin in [#192](https://github.com/ECNU/EduWork/pull/192), building on [@Paraso42](https://github.com/Paraso42)'s remote-access prototype in [#180](https://github.com/ECNU/EduWork/pull/180): mapping DSH host integration points, endpoint allowlists and refusal reasons, the device trust and revocation model, and validation scenarios for reconnection, avoiding duplicate execution, and deployment across networks. @Paraso42 is a co-contributor to remote access; #192 defines the current protocol and implementation.
|
|
82
|
+
|
|
83
|
+
## Development
|
|
84
|
+
|
|
85
|
+
From this package directory:
|
|
86
|
+
|
|
87
|
+
```sh
|
|
88
|
+
npm ci
|
|
89
|
+
npm run check
|
|
90
|
+
node scripts/check-web.ts
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
`check-web.ts` goes through pairing, loading, requests, reconnection and device removal in Chromium and WebKit. It needs Playwright's browsers installed locally and does not run in CI.
|
|
94
|
+
|
|
95
|
+
[Package maintenance and publishing](https://github.com/ecnu/EduWork/blob/main/docs/PACKAGES_EN.md) · [Changelog](CHANGELOG.md) · [License](LICENSE) · [Third-party notices](THIRD_PARTY_NOTICES.md)
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# 第三方声明
|
|
2
|
+
|
|
3
|
+
`@eduwork/dsh-remote-access` 使用 MIT 许可证。发布产物打包了下列软件包的代码;构建脚本从实际打包的依赖收集各包的许可证全文,随包放在 `lib/THIRD_PARTY_LICENSES.txt`。精确版本见 `package-lock.json`。
|
|
4
|
+
|
|
5
|
+
- 宿主插件与网页客户端的加密:`noise-handshake`、`b4a`(Apache-2.0),`sodium-javascript`、`sodium-universal`、`blake2b-wasm`、`siphash24`、`xsalsa20`(MIT),`blake2b`、`chacha20-universal`、`nanoassert`、`sha256-universal`、`sha256-wasm`、`sha512-universal`、`sha512-wasm`(ISC)。
|
|
6
|
+
- 中继服务:`ws`(MIT)。
|
|
7
|
+
- 设置页:`zod`、`uqr`(MIT)。
|
|
8
|
+
|
|
9
|
+
DeepSeek Harness 软件包、`@deepseek-ai/cordis`、`@deepseek-ai/schemastery` 和 React 由宿主提供,作为 peer dependency 出现,不打包进本包,也不表示其作者认可本项目。网页图标取自 EduWork 自有 Logo,随本项目 MIT 许可提供。
|
package/cordis.patch.yml
ADDED
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
# 自托管中继部署
|
|
2
|
+
|
|
3
|
+
[English](DEPLOYMENT_EN.md) · [插件使用与配对](../README.md)
|
|
4
|
+
|
|
5
|
+
中继和桌面插件由同一个 npm 包 `@eduwork/dsh-remote-access` 交付。服务器只需运行包里的 `eduwork-remote-relay`,无需安装 EduWork 桌面客户端、模型服务或数据库。被访问的电脑运行 DSH/EduWork 和远控插件,其他终端通过浏览器访问中继的 HTTPS 地址。
|
|
6
|
+
|
|
7
|
+
## 1. 启动服务
|
|
8
|
+
|
|
9
|
+
准备 Node.js **24.22.1 或更新的受支持版本**、npm,以及可以转发 WebSocket 的 HTTPS 反向代理。以下命令固定使用 `0.1.1`,升级时明确修改版本号。
|
|
10
|
+
|
|
11
|
+
先生成接入 Key,保存好并交给需要注册电脑的用户:
|
|
12
|
+
|
|
13
|
+
```sh
|
|
14
|
+
node -e "console.log(require('node:crypto').randomBytes(32).toString('base64url'))"
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Linux/macOS 前台试运行:
|
|
18
|
+
|
|
19
|
+
```sh
|
|
20
|
+
export RELAY_URL='https://remote.example.edu/'
|
|
21
|
+
export RELAY_ACCESS_KEYS='替换成刚才生成的Key'
|
|
22
|
+
npx --yes --package=@eduwork/dsh-remote-access@0.1.1 eduwork-remote-relay
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Windows PowerShell:
|
|
26
|
+
|
|
27
|
+
```powershell
|
|
28
|
+
$env:RELAY_URL = 'https://remote.example.edu/'
|
|
29
|
+
$env:RELAY_ACCESS_KEYS = '替换成刚才生成的Key'
|
|
30
|
+
npx --yes --package=@eduwork/dsh-remote-access@0.1.1 eduwork-remote-relay
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
默认监听 `127.0.0.1:8787`。`RELAY_URL` 是**用户访问的外部地址**,不是监听地址;TLS 在反向代理终止。前台命令退出就会停止服务,长期运行见第 3 节。只在本机调试时可使用 `http://localhost:8787/`;手机访问应使用具有有效证书的 HTTPS 地址,以便浏览器使用 Service Worker 和加密 API。
|
|
34
|
+
|
|
35
|
+
## 2. HTTPS 与路径前缀
|
|
36
|
+
|
|
37
|
+
独立域名可用 `RELAY_URL=https://remote.example.edu/`。同域路径可用:
|
|
38
|
+
|
|
39
|
+
```dotenv
|
|
40
|
+
RELAY_URL=https://example.edu/eduwork-remote/
|
|
41
|
+
RELAY_ACCESS_KEYS=替换成随机Key
|
|
42
|
+
RELAY_CLIENT_IP_HEADER=x-real-ip
|
|
43
|
+
HOST=127.0.0.1
|
|
44
|
+
PORT=8787
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
路径前缀由 `RELAY_URL` 决定,**没有另一个 PREFIX 环境变量**。客户端填写同一个完整地址。反向代理必须保留 `/eduwork-remote/`,网页、Service Worker、健康检查和 WebSocket 共用此前缀。
|
|
48
|
+
|
|
49
|
+
Nginx 示例:把 `map` 放在 `http` 块中;把 `location` 放进已有证书配置的 HTTPS `server` 块中。根路径部署时把两个 `location` 替换为一个 `location /`,其余代理设置相同。
|
|
50
|
+
|
|
51
|
+
```nginx
|
|
52
|
+
# http 块内
|
|
53
|
+
map $http_upgrade $eduwork_connection_upgrade {
|
|
54
|
+
default upgrade;
|
|
55
|
+
'' close;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
# 已有 HTTPS server 块内
|
|
59
|
+
location = /eduwork-remote {
|
|
60
|
+
return 301 /eduwork-remote/;
|
|
61
|
+
}
|
|
62
|
+
location /eduwork-remote/ {
|
|
63
|
+
# 不在 8787 后加 /,否则 Nginx 会去掉路径前缀。
|
|
64
|
+
proxy_pass http://127.0.0.1:8787;
|
|
65
|
+
proxy_http_version 1.1;
|
|
66
|
+
proxy_set_header Host $host;
|
|
67
|
+
proxy_set_header Upgrade $http_upgrade;
|
|
68
|
+
proxy_set_header Connection $eduwork_connection_upgrade;
|
|
69
|
+
proxy_set_header X-Real-IP $remote_addr;
|
|
70
|
+
proxy_read_timeout 3600s;
|
|
71
|
+
proxy_send_timeout 3600s;
|
|
72
|
+
proxy_buffering off;
|
|
73
|
+
}
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
设置 `RELAY_CLIENT_IP_HEADER` 时,由可信代理覆盖该请求头,并让中继端口仅对该代理可达。同域已有 Service Worker 若控制整个站点,需要让它放过这段路径。
|
|
77
|
+
|
|
78
|
+
路径划分不会隔离浏览器的同源存储和权限。远端 DSH 界面来自所配对的电脑,与中继页面同源;同域业务和被配对电脑必须处于部署者接受的共同信任范围。独立域名可以缩小这个范围。同域集成前请阅读 [安全说明](../README.md#安全)。
|
|
79
|
+
|
|
80
|
+
## 3. 长期运行(Linux / systemd)
|
|
81
|
+
|
|
82
|
+
由维护者安装固定版本;服务本身使用普通系统账号运行:
|
|
83
|
+
|
|
84
|
+
```sh
|
|
85
|
+
sudo useradd --system --no-create-home --shell /usr/sbin/nologin eduwork-remote
|
|
86
|
+
sudo install -d /opt/eduwork-remote /etc/eduwork-remote
|
|
87
|
+
sudo npm install --prefix /opt/eduwork-remote --omit=dev --ignore-scripts --save-exact @eduwork/dsh-remote-access@0.1.1
|
|
88
|
+
sudo install -m 600 /dev/null /etc/eduwork-remote/relay.env
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
账号已存在时跳过 `useradd`。将第 2 节的配置写入 `/etc/eduwork-remote/relay.env`,填写实际 URL 和随机 Key。环境文件不要提交到仓库。将以下内容保存为 `/etc/systemd/system/eduwork-remote.service`:
|
|
92
|
+
|
|
93
|
+
```ini
|
|
94
|
+
[Unit]
|
|
95
|
+
Description=EduWork remote relay
|
|
96
|
+
After=network-online.target
|
|
97
|
+
Wants=network-online.target
|
|
98
|
+
|
|
99
|
+
[Service]
|
|
100
|
+
Type=simple
|
|
101
|
+
User=eduwork-remote
|
|
102
|
+
Group=eduwork-remote
|
|
103
|
+
WorkingDirectory=/opt/eduwork-remote
|
|
104
|
+
EnvironmentFile=/etc/eduwork-remote/relay.env
|
|
105
|
+
ExecStart=/usr/bin/node /opt/eduwork-remote/node_modules/@eduwork/dsh-remote-access/lib/relay.js
|
|
106
|
+
Restart=on-failure
|
|
107
|
+
RestartSec=3
|
|
108
|
+
|
|
109
|
+
[Install]
|
|
110
|
+
WantedBy=multi-user.target
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
先用 `command -v node` 核对 `ExecStart` 中的路径,确认该 Node 版本满足要求;不要依赖交互式 shell 才会加载的版本管理器。
|
|
114
|
+
|
|
115
|
+
```sh
|
|
116
|
+
sudo systemctl daemon-reload
|
|
117
|
+
sudo systemctl enable --now eduwork-remote
|
|
118
|
+
sudo systemctl status eduwork-remote
|
|
119
|
+
sudo journalctl -u eduwork-remote -n 100 --no-pager
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
更改环境文件后执行 `sudo systemctl restart eduwork-remote`。更新 npm 包时在相同目录安装指定新版本后重启;保留 `package.json`、`package-lock.json` 和环境文件以便回退。中继重启会断开现有连接,在线电脑和设备会尝试重连。配对身份分别保存在电脑和远端浏览器中,中继不保存会话或配对数据库。
|
|
123
|
+
|
|
124
|
+
## 4. 验证与配对
|
|
125
|
+
|
|
126
|
+
路径部署示例:
|
|
127
|
+
|
|
128
|
+
```sh
|
|
129
|
+
curl -fsS http://127.0.0.1:8787/eduwork-remote/healthz
|
|
130
|
+
curl -fsS https://example.edu/eduwork-remote/healthz
|
|
131
|
+
curl -I https://example.edu/eduwork-remote/sw.js
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
前两项应返回 `ok`,第三项应返回 200 和 JavaScript 内容类型。健康检查只说明 HTTP 服务可达;还须在桌面“设置 → 远程访问”填写同一外部地址和 Key,启用后确认“已连接”。随后按[配对步骤](../README.md#添加和移除设备)从另一终端接入,并在本机核对配对码、确认授权。接入 Key 允许电脑使用中继,不能替代这次设备配对。
|
|
135
|
+
|
|
136
|
+
## 5. 机构登录与 iframe(可选)
|
|
137
|
+
|
|
138
|
+
机构登录可替代 Key,也可与 Key 并存:
|
|
139
|
+
|
|
140
|
+
```dotenv
|
|
141
|
+
RELAY_OIDC_ISSUER=https://sso.example.edu
|
|
142
|
+
RELAY_OIDC_CLIENT_IDS=desktop-client-id
|
|
143
|
+
RELAY_FRAME_ANCESTORS=self https://portal.example.edu
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
单用机构登录时不设 `RELAY_ACCESS_KEYS`。`issuer` 必须与 Token 的 `iss` 完全一致,client ID 是桌面应用的 OIDC 客户端标识;多个 ID 用逗号分隔。中继从 discovery/JWKS 获取公钥,当前支持 **RS256 ID Token**,校验签名、issuer、audience/authorized party 和有效期;这里不是模型 API Key,也不是拿 access token 充当 ID Token。
|
|
147
|
+
|
|
148
|
+
电脑需安装 `@eduwork/dsh-oidc@0.3.1` 或后续兼容版本,并由发行版配置远控插件的 `organization: { relay, oidcProfileId }`。单纯设置服务端的 issuer 不会自动配置桌面登录。中继验证已有身份,不保存 refresh token,也不替用户登录;续期由电脑的 OIDC 插件处理。
|
|
149
|
+
|
|
150
|
+
`RELAY_FRAME_ANCESTORS` 默认 `none`,禁止 iframe 嵌入。允许同源父页面时填 `self`,其他父页面填完整来源(协议、主机和可选端口,不含路径)。在 shell 中给多个来源加引号:`RELAY_FRAME_ANCESTORS="self https://portal.example.edu"`。父站自己的 CSP 也要允许加载中继,代理不能再给此路径附加冲突的 `X-Frame-Options: DENY` 或 `frame-ancestors 'none'`。
|
|
151
|
+
|
|
152
|
+
```html
|
|
153
|
+
<iframe src="https://example.edu/eduwork-remote/" title="远程访问"></iframe>
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
当前方案需要脚本、Service Worker 和同源身份,不能套一个移除同源身份的 sandbox;上述普通 iframe 示例不会提供安全隔离。跨站 iframe 在 Safari/WebKit 中可能无法加载电脑界面,优先使用同站集成或顶层打开中继。开放嵌入不改变本机配对与设备撤销要求。
|
|
157
|
+
|
|
158
|
+
## 常见问题
|
|
159
|
+
|
|
160
|
+
| 现象 | 优先检查 |
|
|
161
|
+
| --- | --- |
|
|
162
|
+
| 启动即退出,提示配置不完整 | `RELAY_URL`、Key 或完整 OIDC 配置是否实际进入进程环境。 |
|
|
163
|
+
| healthz 正常,电脑仍无法连接 | HTTPS 证书、WebSocket Upgrade、外部 URL/前缀一致性、接入 Key;OIDC 模式还要检查 issuer/JWKS 可达性和 ID Token。 |
|
|
164
|
+
| 子路径页面或 sw.js 返回 404 | `proxy_pass` 是否去掉了前缀,站点是否把此路径误转到另一个 SPA。 |
|
|
165
|
+
| 手机卡在加载页面 | 有效 HTTPS、Service Worker 未被父站拦截、电脑在线且未休眠、浏览器站点数据未被清理。 |
|
|
166
|
+
| 顶层能打开,iframe 打不开 | 中继 `RELAY_FRAME_ANCESTORS`、父页面 CSP、代理额外响应头,以及 WebKit 跨站限制。 |
|
|
167
|
+
|
|
168
|
+
使用接入 Key 时不需要机构登录插件。API、帧格式和加密机制见[协议文档](PROTOCOL.md)。
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
# Self-hosted relay deployment
|
|
2
|
+
|
|
3
|
+
[简体中文](DEPLOYMENT.md) · [Plugin usage and pairing](../README_EN.md)
|
|
4
|
+
|
|
5
|
+
The desktop plugin and relay ship in the same npm package, `@eduwork/dsh-remote-access`. The server runs `eduwork-remote-relay`; it does not need the EduWork desktop app, model services or a database. The accessed computer runs DSH/EduWork and the plugin, while other devices open the relay's HTTPS URL in a browser.
|
|
6
|
+
|
|
7
|
+
## 1. Start the service
|
|
8
|
+
|
|
9
|
+
Use Node.js **24.22.1 or a later supported version**, npm, and an HTTPS reverse proxy supporting WebSockets. These examples pin `0.1.1`; change the version explicitly when upgrading.
|
|
10
|
+
|
|
11
|
+
Generate an access key, retain it and give it to the users registering computers:
|
|
12
|
+
|
|
13
|
+
```sh
|
|
14
|
+
node -e "console.log(require('node:crypto').randomBytes(32).toString('base64url'))"
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Linux/macOS foreground run:
|
|
18
|
+
|
|
19
|
+
```sh
|
|
20
|
+
export RELAY_URL='https://remote.example.edu/'
|
|
21
|
+
export RELAY_ACCESS_KEYS='replace-with-the-generated-key'
|
|
22
|
+
npx --yes --package=@eduwork/dsh-remote-access@0.1.1 eduwork-remote-relay
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Windows PowerShell:
|
|
26
|
+
|
|
27
|
+
```powershell
|
|
28
|
+
$env:RELAY_URL = 'https://remote.example.edu/'
|
|
29
|
+
$env:RELAY_ACCESS_KEYS = 'replace-with-the-generated-key'
|
|
30
|
+
npx --yes --package=@eduwork/dsh-remote-access@0.1.1 eduwork-remote-relay
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
The default listener is `127.0.0.1:8787`. `RELAY_URL` is the **external address users visit**, not the listening address. The proxy terminates TLS. Exiting the foreground command stops the service; see section 3 for persistent operation. Local-only debugging can use `http://localhost:8787/`; phones should use HTTPS with a valid certificate for Service Worker and cryptographic APIs.
|
|
34
|
+
|
|
35
|
+
## 2. HTTPS and a path prefix
|
|
36
|
+
|
|
37
|
+
A dedicated domain uses `RELAY_URL=https://remote.example.edu/`. To share a domain under a path:
|
|
38
|
+
|
|
39
|
+
```dotenv
|
|
40
|
+
RELAY_URL=https://example.edu/eduwork-remote/
|
|
41
|
+
RELAY_ACCESS_KEYS=replace-with-a-random-key
|
|
42
|
+
RELAY_CLIENT_IP_HEADER=x-real-ip
|
|
43
|
+
HOST=127.0.0.1
|
|
44
|
+
PORT=8787
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
`RELAY_URL` determines the prefix; **there is no separate PREFIX environment variable**. Enter the same complete URL on the computer. Preserve `/eduwork-remote/` in proxy requests: pages, Service Worker, health checks and WebSockets share that prefix.
|
|
48
|
+
|
|
49
|
+
For Nginx, put `map` in the `http` block and the locations in an existing HTTPS `server` block with certificates configured. For a root-path deployment, replace the two locations with one `location /`, keeping the same proxy settings.
|
|
50
|
+
|
|
51
|
+
```nginx
|
|
52
|
+
# Inside http
|
|
53
|
+
map $http_upgrade $eduwork_connection_upgrade {
|
|
54
|
+
default upgrade;
|
|
55
|
+
'' close;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
# Inside the existing HTTPS server
|
|
59
|
+
location = /eduwork-remote {
|
|
60
|
+
return 301 /eduwork-remote/;
|
|
61
|
+
}
|
|
62
|
+
location /eduwork-remote/ {
|
|
63
|
+
# No trailing / after 8787: preserve the path prefix.
|
|
64
|
+
proxy_pass http://127.0.0.1:8787;
|
|
65
|
+
proxy_http_version 1.1;
|
|
66
|
+
proxy_set_header Host $host;
|
|
67
|
+
proxy_set_header Upgrade $http_upgrade;
|
|
68
|
+
proxy_set_header Connection $eduwork_connection_upgrade;
|
|
69
|
+
proxy_set_header X-Real-IP $remote_addr;
|
|
70
|
+
proxy_read_timeout 3600s;
|
|
71
|
+
proxy_send_timeout 3600s;
|
|
72
|
+
proxy_buffering off;
|
|
73
|
+
}
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
When using `RELAY_CLIENT_IP_HEADER`, let the trusted proxy overwrite that header and keep the relay port reachable only by that proxy. An existing site-wide Service Worker must leave this path alone.
|
|
77
|
+
|
|
78
|
+
Paths do not isolate same-origin browser storage or privileges. The remote DSH interface comes from the paired computer and shares the relay's origin. The site's applications and paired computers must therefore belong to a trust boundary the operator accepts. A dedicated domain narrows that boundary. Read [Security](../README_EN.md#security) before sharing an origin.
|
|
79
|
+
|
|
80
|
+
## 3. Persistent service (Linux / systemd)
|
|
81
|
+
|
|
82
|
+
Have a maintainer install the pinned package; run the service as an ordinary system account:
|
|
83
|
+
|
|
84
|
+
```sh
|
|
85
|
+
sudo useradd --system --no-create-home --shell /usr/sbin/nologin eduwork-remote
|
|
86
|
+
sudo install -d /opt/eduwork-remote /etc/eduwork-remote
|
|
87
|
+
sudo npm install --prefix /opt/eduwork-remote --omit=dev --ignore-scripts --save-exact @eduwork/dsh-remote-access@0.1.1
|
|
88
|
+
sudo install -m 600 /dev/null /etc/eduwork-remote/relay.env
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
Skip `useradd` if the account exists. Write the section 2 configuration to `/etc/eduwork-remote/relay.env`, using your URL and generated key. Do not commit the environment file. Save the following as `/etc/systemd/system/eduwork-remote.service`:
|
|
92
|
+
|
|
93
|
+
```ini
|
|
94
|
+
[Unit]
|
|
95
|
+
Description=EduWork remote relay
|
|
96
|
+
After=network-online.target
|
|
97
|
+
Wants=network-online.target
|
|
98
|
+
|
|
99
|
+
[Service]
|
|
100
|
+
Type=simple
|
|
101
|
+
User=eduwork-remote
|
|
102
|
+
Group=eduwork-remote
|
|
103
|
+
WorkingDirectory=/opt/eduwork-remote
|
|
104
|
+
EnvironmentFile=/etc/eduwork-remote/relay.env
|
|
105
|
+
ExecStart=/usr/bin/node /opt/eduwork-remote/node_modules/@eduwork/dsh-remote-access/lib/relay.js
|
|
106
|
+
Restart=on-failure
|
|
107
|
+
RestartSec=3
|
|
108
|
+
|
|
109
|
+
[Install]
|
|
110
|
+
WantedBy=multi-user.target
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
Check the Node path using `command -v node` and adjust `ExecStart` as needed. Verify that binary meets the version requirement; do not rely on a version manager loaded only by interactive shells.
|
|
114
|
+
|
|
115
|
+
```sh
|
|
116
|
+
sudo systemctl daemon-reload
|
|
117
|
+
sudo systemctl enable --now eduwork-remote
|
|
118
|
+
sudo systemctl status eduwork-remote
|
|
119
|
+
sudo journalctl -u eduwork-remote -n 100 --no-pager
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
After environment changes, run `sudo systemctl restart eduwork-remote`. To upgrade, install a specific new npm version in the same directory and restart. Retain `package.json`, `package-lock.json` and the environment file for rollback. A relay restart disconnects current connections; online computers and devices attempt to reconnect. Pairing identities live on the computer and remote browser; the relay stores no session or pairing database.
|
|
123
|
+
|
|
124
|
+
## 4. Verify and pair
|
|
125
|
+
|
|
126
|
+
For a path deployment:
|
|
127
|
+
|
|
128
|
+
```sh
|
|
129
|
+
curl -fsS http://127.0.0.1:8787/eduwork-remote/healthz
|
|
130
|
+
curl -fsS https://example.edu/eduwork-remote/healthz
|
|
131
|
+
curl -I https://example.edu/eduwork-remote/sw.js
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
The first two return `ok`; the last returns 200 with a JavaScript content type. Health checks establish HTTP reachability only. Enter the same external URL and key under desktop Settings → Remote access, enable it, and check for “Connected”. Follow the [pairing steps](../README_EN.md#add-and-remove-devices) on another device, compare codes and approve on the computer. An access key admits a computer to the relay; it does not replace device pairing.
|
|
135
|
+
|
|
136
|
+
## 5. Organization sign-in and iframe (optional)
|
|
137
|
+
|
|
138
|
+
Organization sign-in can replace access keys or coexist with them:
|
|
139
|
+
|
|
140
|
+
```dotenv
|
|
141
|
+
RELAY_OIDC_ISSUER=https://sso.example.edu
|
|
142
|
+
RELAY_OIDC_CLIENT_IDS=desktop-client-id
|
|
143
|
+
RELAY_FRAME_ANCESTORS=self https://portal.example.edu
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
Omit `RELAY_ACCESS_KEYS` when using organization sign-in alone. The issuer must exactly match the token's `iss`. Client IDs identify desktop applications registered with the issuer; separate multiple IDs with commas. Discovery/JWKS supplies public keys. The relay currently accepts **RS256 ID Tokens** and checks signatures, issuer, audience/authorized party and validity. This is neither a model API key nor an access token used as an ID Token.
|
|
147
|
+
|
|
148
|
+
The computer needs `@eduwork/dsh-oidc@0.3.1` or a later compatible version, and distribution configuration for `organization: { relay, oidcProfileId }`. Setting an issuer on the server does not configure desktop login. The relay verifies existing identity, stores no refresh token and does not sign users in; the computer's OIDC plugin handles renewal.
|
|
149
|
+
|
|
150
|
+
`RELAY_FRAME_ANCESTORS` defaults to `none`, blocking iframe embedding. Use `self` for same-origin parents, or complete origins (scheme, host and optional port, without paths). Quote multiple sources in shell commands: `RELAY_FRAME_ANCESTORS="self https://portal.example.edu"`. The parent's CSP must also permit the relay, and the proxy must not add a conflicting `X-Frame-Options: DENY` or `frame-ancestors 'none'` to this path.
|
|
151
|
+
|
|
152
|
+
```html
|
|
153
|
+
<iframe src="https://example.edu/eduwork-remote/" title="Remote access"></iframe>
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
The current design needs scripts, Service Worker and same-origin identity; an opaque-origin sandbox is incompatible. The ordinary iframe above provides no security isolation. Cross-site iframes may fail to load the computer's interface in Safari/WebKit; use same-site integration or open the relay at the top level. Allowing embedding does not replace local pairing or device revocation.
|
|
157
|
+
|
|
158
|
+
## Troubleshooting
|
|
159
|
+
|
|
160
|
+
| Symptom | Check first |
|
|
161
|
+
| --- | --- |
|
|
162
|
+
| Immediate exit with incomplete-configuration error | Ensure the process receives `RELAY_URL` and either access keys or complete OIDC settings. |
|
|
163
|
+
| healthz works but the computer cannot connect | HTTPS certificate, WebSocket Upgrade, matching external URL/prefix and key; for OIDC, issuer/JWKS reachability and ID Token. |
|
|
164
|
+
| Path page or sw.js returns 404 | Check for prefix removal by `proxy_pass` or routing to another site's SPA. |
|
|
165
|
+
| Phone stays on the loading page | Valid HTTPS, no parent Service Worker interference, computer online and awake, browser site data retained. |
|
|
166
|
+
| Top-level page works but iframe does not | Relay frame ancestors, parent CSP, proxy response headers and WebKit cross-site restrictions. |
|
|
167
|
+
|
|
168
|
+
Access-key deployments do not need an organization login plugin. See the [protocol](PROTOCOL.md) for APIs, frames and encryption.
|