Jelajahi Sumber

改为受管安装默认监听局域网

samien 2 bulan lalu
induk
melakukan
42784ef320
5 mengubah file dengan 48 tambahan dan 26 penghapusan
  1. 2 1
      .env.example
  2. 10 10
      README.md
  3. 5 4
      bin/hermes-yaoyao.mjs
  4. 11 11
      docs/agent-install.md
  5. 20 0
      tests/serviceCli.test.ts

+ 2 - 1
.env.example

@@ -1,9 +1,10 @@
+# Manual npm/Docker runs stay loopback-only unless changed; macOS `service install` defaults to 0.0.0.0.
 HERMES_YAOYAO_HOST=127.0.0.1
 HERMES_YAOYAO_PORT=8800
 HERMES_YAOYAO_UPSTREAM=http://127.0.0.1:9119
 # Comma-separated additional DNS names. Localhost and active private IP literals are allowed automatically.
 HERMES_YAOYAO_ALLOWED_HOSTS=
-# For LAN access set HOST=0.0.0.0 and either configure TLS or explicitly enable trusted-LAN HTTP below.
+# For manual LAN access set HOST=0.0.0.0 and either configure TLS or explicitly enable trusted-LAN HTTP below.
 HERMES_YAOYAO_ALLOW_INSECURE_LAN=0
 # The managed LaunchAgent sets this to 1 and keeps the local Hermes Dashboard on 9119 available.
 HERMES_YAOYAO_SUPERVISE_DASHBOARD=0

+ 10 - 10
README.md

@@ -184,27 +184,27 @@ npm run dev
 
 原生群聊由房主 Hermes 保存权威房间、话题和消息。扫码时,iOS 会把远端节点以加密凭据注册到房主插件;房主通过远端 `nodeWorker` 执行 Session,并转发流式事件、审批、澄清、中断和受限群聊附件。房主工作目录不会作为远端绝对路径使用,远端 Agent 默认采用自己的工作区。
 
-免密配对和跨节点执行应使用 HTTPS/WSS 或 Tailscale。只有显式设置 `HERMES_YAOYAO_ALLOW_INSECURE_LAN=1` 时才应在可信局域网使用 HTTP;不要把二维码或配对凭据发送给不受信任的人。
+免密配对和跨节点执行应使用 HTTPS/WSS 或 Tailscale。受管安装会显式设置 `HERMES_YAOYAO_ALLOW_INSECURE_LAN=1`,因此默认 HTTP 监听只适合可信局域网;不要把二维码或配对凭据发送给不受信任的人。
 
 ## 网络暴露:9119 与 8800 分别控制
 
-默认情况下,两个端口都**不开放局域网**:Hermes Dashboard `9119` 和夭夭 Web `8800` 都只监听 `127.0.0.1`。通过本项目安装的受管服务开启局域网时,两个端口会一起开放。
+通过 `service install` 安装的受管服务默认开放可信局域网:Hermes Dashboard `9119` 和夭夭 Web `8800` 都监听 `0.0.0.0`。手动 `npm start` 与 Docker 部署仍保留各自的绑定默认值。
 
 | 端口 | 服务 | 默认 | 单独开启局域网 |
 | --- | --- | --- | --- |
-| `9119` | Hermes Dashboard | `127.0.0.1` | 由夭夭 Web 监督;首次缺失配置时创建随机服务账号并启动 |
-| `8800` | 夭夭 Web | `127.0.0.1` | 显式设置 `HERMES_YAOYAO_HOST=0.0.0.0` 后与 9119 一起开放 |
+| `9119` | Hermes Dashboard | `0.0.0.0` | 由夭夭 Web 监督;沿用或创建随机服务账号后启动 |
+| `8800` | 夭夭 Web | `0.0.0.0` | LaunchAgent 显式启用可信局域网 HTTP |
 
-夭夭 Web 默认上游仍是 `http://127.0.0.1:9119`。受管服务的局域网开关会同时让它监听局域网地址,并让其启动的 Dashboard `9119` 监听局域网地址。
+夭夭 Web 默认上游仍是 `http://127.0.0.1:9119`,8800 在本机通过回环连接受监督的 9119;两个服务对局域网的监听地址均为 `0.0.0.0`。
 
-仅在可信局域网中以 HTTP 开放受管服务时,必须同时设置:
+若需要把受管安装恢复为仅本机访问,可在安装前显式设置:
 
 ```bash
-HERMES_YAOYAO_HOST=0.0.0.0
-HERMES_YAOYAO_ALLOW_INSECURE_LAN=1
+HERMES_YAOYAO_HOST=127.0.0.1
+HERMES_YAOYAO_ALLOW_INSECURE_LAN=0
 ```
 
-生产局域网使用建议同时配置 `HERMES_YAOYAO_TLS_CERT` 和 `HERMES_YAOYAO_TLS_KEY`。
+默认局域网 HTTP 只适合可信网络。跨不受信网络使用时必须配置 `HERMES_YAOYAO_TLS_CERT` 和 `HERMES_YAOYAO_TLS_KEY`,并限制防火墙或反向代理访问范围。
 
 受管服务会在 `dashboard.basic_auth` 未配置时创建 `yaoyao-service` 和随机密码的
 scrypt 哈希,同时生成会话签名 `secret`;明文服务密码只加密保存在 8800 数据目录。
@@ -322,7 +322,7 @@ curl --fail --silent http://127.0.0.1:9119/api/dashboard/plugins
 
 ## 受管服务操作与验收
 
-`service install` 会写入并启动 `com.samien.hermes-yaoyao` LaunchAgent;它默认监督本机 `9119`。已安装服务的环境变量写入 plist,因此改变监听地址、TLS 或监督开关后需要再次执行 `service install`,仅执行 `service start` 不会刷新这些配置。
+`service install` 会写入并启动 `com.samien.hermes-yaoyao` LaunchAgent;它默认让 8800 与受监督的 9119 监听局域网。已安装服务的环境变量写入 plist,因此改变监听地址、TLS 或监督开关后需要再次执行 `service install`,仅执行 `service start` 不会刷新这些配置。
 
 | 目标 | 命令 | 预期结果 |
 | --- | --- | --- |

+ 5 - 4
bin/hermes-yaoyao.mjs

@@ -32,7 +32,7 @@ function escapeXml(value) {
     .replaceAll("'", ''')
 }
 
-function environment() {
+function environment(env = process.env) {
   const allowed = [
     'HERMES_YAOYAO_HOST',
     'HERMES_YAOYAO_PORT',
@@ -50,7 +50,7 @@ function environment() {
     'HERMES_YAOYAO_ALLOW_REMOTE_UPDATE',
     'HERMES_YAOYAO_SERVICE_ROOT',
   ]
-  return Object.fromEntries(allowed.flatMap(key => process.env[key] ? [[key, process.env[key]]] : []))
+  return Object.fromEntries(allowed.flatMap(key => env[key] ? [[key, env[key]]] : []))
 }
 
 export function launchAgentPlist(options = {}) {
@@ -61,11 +61,12 @@ export function launchAgentPlist(options = {}) {
     PATH: `${dirname(node)}:${join(homedir(), '.local', 'bin')}:/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin`,
     NODE_ENV: 'production',
     HERMES_YAOYAO_HOME: dataHome,
-    HERMES_YAOYAO_HOST: '127.0.0.1',
+    HERMES_YAOYAO_HOST: '0.0.0.0',
     HERMES_YAOYAO_PORT: '8800',
     HERMES_YAOYAO_UPSTREAM: 'http://127.0.0.1:9119',
+    HERMES_YAOYAO_ALLOW_INSECURE_LAN: '1',
     HERMES_YAOYAO_SUPERVISE_DASHBOARD: '1',
-    ...environment(),
+    ...environment(options.environment),
   }
   const envXml = Object.entries(envEntries).map(([key, value]) => (
     `      <key>${escapeXml(key)}</key>\n      <string>${escapeXml(value)}</string>`

+ 11 - 11
docs/agent-install.md

@@ -14,23 +14,23 @@
 
 ## 网络默认值与局域网策略
 
-默认情况下,两个服务都**不开启局域网访问**。受管 8800 服务启用局域网时,会将两个端口一起开放:
+通过 `service install` 安装的受管服务默认监听可信局域网,两个端口一起开放:
 
 | 端口 | 服务 | 默认监听地址 | 开启局域网的责任边界 |
 | --- | --- | --- | --- |
-| `9119` | Hermes Dashboard | `127.0.0.1` | 由 8800 服务持续监督;无配置时创建 `admin/admin` 认证并启动 |
-| `8800` | 夭夭 Web | `127.0.0.1` | 显式设置 `HERMES_YAOYAO_HOST=0.0.0.0` 后与 9119 一起开放 |
+| `9119` | Hermes Dashboard | `0.0.0.0` | 由 8800 服务持续监督;沿用或创建独立服务认证后启动 |
+| `8800` | 夭夭 Web | `0.0.0.0` | LaunchAgent 显式写入可信局域网 HTTP 开关 |
 
-最小暴露策略是保持两个端口仅本机监听。受管服务不支持“仅开放 8800”:用户明确允许局域网后,它会同时以局域网地址启动 8800 和 9119。
+受管服务不支持“仅开放 8800”:安装后会同时以局域网地址启动 8800 和 9119。该默认值只适用于受管 macOS LaunchAgent;手动 `npm start` 和 Docker 部署仍使用各自的绑定配置。
 
-若用户明确要求开放可信局域网 HTTP,Agent 必须在安装或重启夭夭 Web 前设置:
+若部署必须限制为仅本机访问,Agent 应在安装前显式覆盖:
 
 ```bash
-export HERMES_YAOYAO_HOST=0.0.0.0
-export HERMES_YAOYAO_ALLOW_INSECURE_LAN=1
+export HERMES_YAOYAO_HOST=127.0.0.1
+export HERMES_YAOYAO_ALLOW_INSECURE_LAN=0
 ```
 
-生产环境优先设置 `HERMES_YAOYAO_TLS_CERT` 和 `HERMES_YAOYAO_TLS_KEY`。该开关会将受管 9119 一起绑定至 `0.0.0.0`;`hermes dashboard --insecure` 不会关闭认证,不能将它当成局域网开关。
+默认局域网模式会显式设置 `HERMES_YAOYAO_ALLOW_INSECURE_LAN=1`,只适合受信网络。跨不受信网络部署时必须设置 `HERMES_YAOYAO_TLS_CERT` 和 `HERMES_YAOYAO_TLS_KEY`,并使用防火墙或反向代理限制访问;`hermes dashboard --insecure` 不会关闭认证,不能将它当成局域网开关。
 
 ## 受管 9119 的默认认证与持续监督
 
@@ -196,11 +196,11 @@ hermes dashboard --status
 lsof -nP -iTCP:9119 -sTCP:LISTEN
 ```
 
-验收条件:Dashboard 状态正常,且只有一个 `9119` TCP 监听器。插件路由位于 `/api/plugins/yaoyao/`,该 API 需要现有 Hermes 登录会话;不要为了探测路由而关闭认证。除非用户明确授权且已配置对应生命周期所有者,否则保持 `9119` 仅本机监听。
+验收条件:Dashboard 状态正常,且只有一个 `9119` TCP 监听器。插件路由位于 `/api/plugins/yaoyao/`,该 API 需要现有 Hermes 登录会话;不要为了探测路由而关闭认证。独立运行的 Dashboard 默认保持本机监听;通过夭夭受管服务安装时则跟随 8800 默认监听局域网。
 
 ## 6. 可选:部署夭夭 Web
 
-夭夭 Web 默认监听 `8800` 并连接 Dashboard `9119`。通过 LaunchAgent 安装后,它持续监督 Dashboard `9119`,但在自身停止或卸载时不会主动停止正在运行的 Dashboard。
+夭夭 Web 默认使用端口 `8800` 并连接 Dashboard `9119`。通过 LaunchAgent 安装后,8800 与受监督的 9119 都默认监听 `0.0.0.0`;8800 停止或卸载时不会主动停止正在运行的 Dashboard。
 
 ```bash
 npm ci
@@ -209,7 +209,7 @@ node bin/hermes-yaoyao.mjs service install
 node bin/hermes-yaoyao.mjs service status
 ```
 
-若需要显式指定 Dashboard 上游,只在安装服务前设置 `HERMES_YAOYAO_UPSTREAM`。默认值为 `http://127.0.0.1:9119`。只有用户明确要求时才允许局域网:设置 `HERMES_YAOYAO_HOST=0.0.0.0` 和 `HERMES_YAOYAO_ALLOW_INSECURE_LAN=1`;受管服务会同时将 9119 绑定至 `0.0.0.0`。
+若需要显式指定 Dashboard 上游,只在安装服务前设置 `HERMES_YAOYAO_UPSTREAM`。默认值为 `http://127.0.0.1:9119`,因为 8800 仍通过本机回环访问受监督的 9119。若要恢复仅本机监听,请在安装前设置 `HERMES_YAOYAO_HOST=127.0.0.1` 和 `HERMES_YAOYAO_ALLOW_INSECURE_LAN=0`。
 
 受管服务的配置被写入 `~/Library/LaunchAgents/com.samien.hermes-yaoyao.plist`。任何监听、TLS、上游或监督配置变更后,都要再次执行 `service install`,随后确认状态、两个监听器和日志:
 

+ 20 - 0
tests/serviceCli.test.ts

@@ -15,6 +15,26 @@ describe('hermes-yaoyao LaunchAgent plist', () => {
     expect(launchAgentPlist()).toContain('<key>HERMES_YAOYAO_SUPERVISE_DASHBOARD</key>')
   })
 
+  it('binds managed Web and Dashboard services to the trusted LAN by default', () => {
+    const plist = launchAgentPlist({ environment: {} })
+
+    expect(plist).toContain('<key>HERMES_YAOYAO_HOST</key>\n      <string>0.0.0.0</string>')
+    expect(plist).toContain('<key>HERMES_YAOYAO_ALLOW_INSECURE_LAN</key>\n      <string>1</string>')
+    expect(plist).toContain('<key>HERMES_YAOYAO_SUPERVISE_DASHBOARD</key>\n      <string>1</string>')
+  })
+
+  it('allows an explicit loopback-only managed installation', () => {
+    const plist = launchAgentPlist({
+      environment: {
+        HERMES_YAOYAO_HOST: '127.0.0.1',
+        HERMES_YAOYAO_ALLOW_INSECURE_LAN: '0',
+      },
+    })
+
+    expect(plist).toContain('<key>HERMES_YAOYAO_HOST</key>\n      <string>127.0.0.1</string>')
+    expect(plist).toContain('<key>HERMES_YAOYAO_ALLOW_INSECURE_LAN</key>\n      <string>0</string>')
+  })
+
   it('can point the managed service at the stable current release link', () => {
     const root = join(homedir(), '.local', 'share', 'hermes-yaoyao', 'current')
     const plist = launchAgentPlist({ serviceRoot: root })