按 security-reports/ 的隐私审查台账逐项收口。纯脱敏与表述泛化, 不含任何业务逻辑变更;实测结论与排查步骤一字未动。 P1(可定位到具体设备/个人) - scripts/verify-b2.mjs:NA_URL 去掉硬编码缺省值(原指向一台真实机器),改为必填。 这是全仓库唯一「拿着就能连到某台真机」的常量。 - 测试账户名 pdverify → na-test(docs/VM-VERIFICATION.md 7 处、docs/console-plan.md 1 处) - 虚拟机与宿主的真实网段 → RFC 5737 文档保留段 192.0.2.x(含 CLOSE_WAIT 记录) - 跨项目名与私人称呼 → 中性表述(docs/PRD.md、docs/DEVELOPMENT.md、docs/console-plan.md 等) P2(低风险设备指纹) - 虚拟化产品及其 CLI / 访客工具名 → 中性表述(12 个文件 + 1 个工作流注释) - 测试目录 C:\nodeagent-test → C:\na-test - NAS 设备型号与系统名 → NAS 设备 / NAS 系统(docs/DEPLOY-LINUX.md、scripts/install-linux.sh、README.md) - 真机 CPU 型号、真机物理分辨率、代理软件品牌与监听端口、杀软品牌 → 泛化 - 单元测试示例段去掉真机 IP 尾八位:acl-v11 / net-scripts 的 fixture 与断言同步更新 - .gitignore 补 config.json / agent.json(含真实密钥与节点地址,绝不入库) - 顺带移除混入技术文档的「不构成投资建议」字样(与文档主题无关) 验证:pnpm test:unit 340/340 通过;独立扫描器对 235 个跟踪文件做 17 类模式 全量扫描,命中 0。
138 lines
7.1 KiB
Markdown
138 lines
7.1 KiB
Markdown
# Linux 被控端部署(Debian 12 / Ubuntu / NAS 系统等 systemd 系统)
|
||
|
||
> 适用:把一台 Linux 机器作为**被控端**,让 Mac/Linux 控制端接管。
|
||
> 本文的能力清单是 **2026-10-13 在 Debian 12 容器里实测**得出的,不是推测。
|
||
|
||
---
|
||
|
||
## 0. 一句话
|
||
|
||
Linux 被控端 = **命令 / 状态 / 文件 / 审计**(服务器型用途);
|
||
**没有 GUI 能力**(截图、键鼠、窗口、剪贴板、音量均为 Windows/macOS 实现,
|
||
Linux 端未实现 —— 调用会明确返回 `E_UNSUPPORTED_PLATFORM`,不假装可用)。
|
||
|
||
---
|
||
|
||
## 1. 快速开始(以 NAS 设备为例)
|
||
|
||
```bash
|
||
# ① 把仓库放到 NAS 上(任选其一)
|
||
# - git clone https://github.com/jkooe/nodeagent.git
|
||
# - 或从控制端 scp 整个目录过去
|
||
|
||
# ② 生成被控端载荷(在**控制端**或任意有 Node 22+ 的机器上执行一次)
|
||
node scripts/pack.mjs # → release/agent.mjs
|
||
|
||
# ③ 在 NAS 上执行安装(需要 sudo;会自动注册 systemd 服务并开机自启)
|
||
cd nodeagent
|
||
sudo bash scripts/install-linux.sh --node-id nas-01
|
||
|
||
# ④ 抄下屏幕上打印的「密钥」与「连接命令」,回控制端执行:
|
||
# nodeagent connect <NAS的IP> --port 8765 --key <密钥> --insecure
|
||
```
|
||
|
||
**装完即自启**:`systemctl status nodeagent` 应为 `active (running)`;
|
||
重启 NAS 后也会自动拉起(`systemctl is-enabled nodeagent` → `enabled`)。
|
||
|
||
### 三种安装模式
|
||
|
||
| 模式 | 命令 | 程序目录 | 自启方式 | 适用 |
|
||
|---|---|---|---|---|
|
||
| **系统级**(默认) | `sudo bash scripts/install-linux.sh` | `/opt/nodeagent` | 系统 systemd(`multi-user.target`) | NAS / 服务器,需 sudo |
|
||
| **用户级** | `bash scripts/install-linux.sh --user` | `~/.local/share/nodeagent` | 用户 systemd + `linger` | 无 sudo 的场景 |
|
||
| **不注册服务** | `sudo bash scripts/install-linux.sh --no-service` | 同上(按模式定) | 自行安排(supervisor / cron `@reboot` / nohup) | systemd 受限的系统 |
|
||
|
||
其他参数:`--port 8765`、`--allow-input`(**Linux 上无实际输入能力**,仅留存配置)、
|
||
`--uninstall [--purge]`。
|
||
|
||
---
|
||
|
||
## 2. 运行依赖(脚本会自动处理能处理的)
|
||
|
||
| 依赖 | 是否必需 | 说明 |
|
||
|---|---|---|
|
||
| **Node ≥ 22** | 必需 | 脚本优先用系统 Node;**没有就自动下载** `node-v22.x-linux-<arch>` 到 `<安装目录>/runtime/`(用 npmmirror,国内快)。NAS 上通常没有 Node → 走自动下载 ✓ |
|
||
| **systemd** | 默认必需 | 用于开机自启。没有就加 `--no-service`(脚本会给出替代启动命令) |
|
||
| **bash** | 必需 | 安装脚本与部分能力用它。**Alpine 等只有 busybox 的系统需先装 bash**(`apk add bash`) |
|
||
| **procps(`ps`)** | **`system.process.list` 需要** | Debian/Ubuntu 自带 ✓;**精简容器镜像(如 `node:*-slim`)默认没有** → 表现为「进程列表为空」。装:`apt-get install -y procps` |
|
||
| **iproute2(`ip`)** | 可选 | 仅用于安装时显示本机 IP;缺失时脚本回退 `hostname -I` / `ifconfig`,再不行显示占位符 ✓ |
|
||
| **curl 或 wget** | 下载运行时时需要 | 若已装 Node 22+ 则不需要 |
|
||
|
||
> ⚠️ 实测踩到的坑:在 **Alpine** 容器里测会看到 `spawn /bin/bash ENOENT`,
|
||
> 极易误判成「Linux 不支持」——**实际是镜像没有 bash**。
|
||
> 同理 `node:22-slim` 里 `process.list` 返回空是**没有 procps**,不是代码问题。
|
||
|
||
---
|
||
|
||
## 3. Linux 上真实可用的能力(实测)
|
||
|
||
在同一台(Debian 12)机器上跑 `node scripts/verify.mjs` 的结果:
|
||
|
||
| 能力 | Linux | 说明 |
|
||
|---|---|---|
|
||
| `system.info` | ✅ | 返回 OS 名 "Linux"、CPU 核数、主机名 |
|
||
| `system.status` | ✅ | CPU / 内存 / 磁盘(多磁盘正常识别) |
|
||
| `system.process.list` | ✅** | 需 `procps`;缺则返回空列表 |
|
||
| `system.shell.exec` | ✅ | 含非零退出码回传、**超时强制终止**(实测 exit=124) |
|
||
| `system.service.list` | ⚠️ | Windows 服务概念,Linux 上退化为 systemd 单元(部分可用) |
|
||
| `system.audit.list` / 审计链 | ✅ | 与平台无关 |
|
||
| `system.task.*` | ✅ | 异步长任务框架 |
|
||
| `fs.*`(list/read/write/stat) | ✅ | 路径按 POSIX 语义(区分大小写) |
|
||
| `log.query` / `monitor.*` | ⚠️ 部分 | `monitor` 有 Windows 专属实现,部分子能力不可用 |
|
||
| `event.watch`(file/process/net) | ✅ | 与平台无关 |
|
||
| `system.agent.update`(自更新) | ✅ | 与平台无关 |
|
||
| `screen.*` / `input.*` / `window.*` / `clipboard.*` / `audio.*` / `record.*` | ❌ | **未实现** → 明确返回 `E_UNSUPPORTED_PLATFORM` |
|
||
| `app.list` / `app.install` | ❌ | winget 专属 → 同样明确拒绝 |
|
||
|
||
**汇总对比**:本机 macOS 15 通过/0 失败;Linux(Debian 12)**9 通过 / 1 失败(缺 procps)/ 6 跳过**(跳过的都是 GUI 类)。
|
||
|
||
---
|
||
|
||
## 4. 管理命令
|
||
|
||
```bash
|
||
# 系统级
|
||
systemctl status nodeagent
|
||
journalctl -u nodeagent -f # 实时日志
|
||
systemctl restart nodeagent
|
||
sudo bash scripts/install-linux.sh --uninstall # 卸载(保留配置与审计日志)
|
||
sudo bash scripts/install-linux.sh --uninstall --purge # 连数据目录一起删
|
||
|
||
# 用户级:把上面命令里的 systemctl / journalctl 加 --user
|
||
```
|
||
|
||
**配置与数据**(`~/.nodeagent`,与 agent 侧 `agentDir()` 一致):
|
||
|
||
| 文件 | 内容 |
|
||
|---|---|
|
||
| `agent.json` | 节点 ID / 端口 / **密钥**(权限 600)/ 认证模式 |
|
||
| `audit.log` | 审计日志(JSONL,10MB 轮转留 5 份) |
|
||
| `audit-anchors.jsonl` | 审计链锚点(启用锚定后产生) |
|
||
|
||
---
|
||
|
||
## 5. 故障排查(按实测顺序)
|
||
|
||
| 现象 | 原因 | 处理 |
|
||
|---|---|---|
|
||
| `未检测到 systemd` | 容器/非 systemd 系统 | 加 `--no-service`,或改用 supervisor |
|
||
| `spawn /bin/bash ENOENT` | **系统没有 bash**(Alpine 等) | `apk add bash` / `apt-get install -y bash` |
|
||
| `进程列表为空` | **没有 `ps`**(slim 镜像) | `apt-get install -y procps` |
|
||
| 脚本"跑到一半就没了" | `set -e` 下某个命令替换失败(如缺 `ip`) | 已在 v2.0.3+ 加固为多级回退;旧版请升级脚本 |
|
||
| 控制端连不上,被控端却显示已监听 | 防火墙 | Debian: `ufw allow 8765/tcp`;firewalld: `firewall-cmd --add-port=8765/tcp --permanent && firewall-cmd --reload` |
|
||
| `E_AUTH_FAILED` | 密钥不一致 | 以被控端 `~/.nodeagent/agent.json` 的 `key` 为准 |
|
||
| GUI 能力报 `E_UNSUPPORTED_PLATFORM` | **正常**(Linux 无 GUI 实现) | 无需处理;这是「诚实拒绝」而非故障 |
|
||
|
||
---
|
||
|
||
## 6. 建议(服务器型被控端)
|
||
|
||
1. **尽快启用审计链外部锚定** —— 把链头存到 NAS 之外(云盘/另一台机器)。
|
||
本机锚点等于没锚:被控端被 root 后锚点也会一起被改。
|
||
```bash
|
||
node scripts/anchor-audit.mjs collect --out /tmp/anchor-$(date +%Y%m%d).jsonl
|
||
# 再把该文件上传到云盘,之后用 verify 子命令比对
|
||
```
|
||
2. **不要开 `--allow-input`** —— Linux 上无实际输入能力,开着只是加大配置面。
|
||
3. 若机器只有公网无内网互通,考虑用 **Hub 中转**(被控端主动外连,穿 NAT)。
|