自托管 Agent 安全要靠外部实测验证
文章提出六项行为测试,验证 VPS 上的 AI Agent 是否真正受到访问限制。节选展示从外部扫描端口、检查监听地址、通过 SSH 隧道访问面板,并提醒 SSH 配置还可能受附加文件影响。
AI 深度解读
VPS 上的个人 AI Agent 配好了防火墙、SSH 和自动重启,就算安全了吗?作者给出的判断是:配置只能说明你想让机器怎么运行,真正的验收要看它实际怎么做。他为 OpenClaw、Hermes 这类自托管 Agent 列了六项行为测试,覆盖端口、登录、封禁、恢复、告警和费用。
这份清单的用处,在于把「应该没问题」变成可以复查的结果。不过,测试通过只能证明当时检查的项目符合预期,撑不起「整台服务器已经安全」这样的保证。
端口和 SSH,要从外面验证
第一项检查是从另一台机器扫描已经启动 Agent 的服务器,确认互联网实际能访问哪些端口:
nmap -Pn -p- -sS YOUR_IP
nmap -Pn -sU --top-ports 100 YOUR_IP
注意两行检查范围不同:第一行扫描全部 TCP 端口,第二行只扫描最常见的 100 个 UDP 端口。作者预期只有 22/tcp 开放;如果能看到 Agent 网关或管理面板,要先处理暴露问题。
服务器内部再运行 sudo ss -tulnp,检查监听地址。作者要求 Agent 绑定 127.0.0.1 或 ::1,OpenClaw 网关端口是 18789。原文还列出 Ubuntu 上的 DNS 地址 127.0.0.53/127.0.0.54 和 DHCP 的 udp/68,提醒读者别把系统条目直接当成 Agent 暴露。
访问面板可以走隧道:ssh -N -L PORT:127.0.0.1:PORT USER@YOUR_IP。这样浏览器通过本地转发访问服务器上的面板。
SSH 同样不能只读 /etc/ssh/sshd_config。云镜像可能通过 sshd_config.d/ 中的附加配置重新开启密码登录。用 sudo sshd -T | grep -Ei 'passwordauthentication|kbdinteractiveauthentication|permitrootlogin' 查看最终生效结果,作者预期三项都是 no。
然后从外部执行 ssh -o PreferredAuthentications=password -o PubkeyAuthentication=no USER@YOUR_IP。验收结果是直接出现 Permission denied,没有密码提示。
配置文件描述意图,外部连接测试验证结果。
自动封禁和自动恢复,都得真的触发一次
systemctl is-active fail2ban 只能证明进程正在运行。作者建议用第二台主机故意制造几次 SSH 登录失败,再执行 sudo fail2ban-client status sshd,检查测试 IP 是否进入封禁列表。
作者在测试虚拟机上测到的封禁时间分别为 7 秒和 127 秒,差异与重试时机有关。这是两次观察结果,不能当作统一时限。完成后可用 sudo fail2ban-client set sshd unbanip IP 解封。
Agent 的恢复测试则需要杀掉真实进程。原文针对用户级 systemd 服务这样操作:
sudo systemctl --user -M USER@ show AGENT_UNIT -p MainPID -p Restart
sudo kill -9 <PID>
注意第一行的 --user -M USER@。查询系统级 systemd 可能只得到 MainPID=0,找错了管理服务的地方。
作者要求 Restart=always 或 on-failure,杀进程后既要看到服务重启,也要确认 Agent 能重新回复 Telegram。他测到进程恢复需要 6–7 秒,首次 Telegram 回复需要 22–42 秒。
这两个时间应分开记录。进程启动了,业务链路未必已经恢复。
原文还用 loginctl show-user USER -p Linger 检查 lingering,即用户没有登录时,用户服务是否仍可持续运行。它是作者开机恢复检查中的一环;刚才的杀进程测试并没有实际验证重启服务器后的完整表现。
告警、预算和回滚,也要留下结果
第五项是主动停止 Agent,检查手机能否在几分钟内收到告警。通知必须通过自己控制的 bot 发送;脚本可以检查 Bot API 的 sendMessage 响应是否包含 "ok": true 和 message_id。
但 VPS 整机宕机时,机内告警也可能一起失效,所以作者同时要求外部存活探测。
费用检查则落在供应商侧。原文称 OpenClaw 和 Hermes 没有内置的硬性支出上限,并以 OpenRouter 为例,用 curl -s https://openrouter.ai/api/v1/key -H "Authorization: Bearer $KEY" 查询密钥信息。检查 limit 不是 null;需要月度上限时,再检查 limit_reset 是否为 monthly。密钥应从仅 root 可读的文件读取,避免进入日志或 shell 历史。
额外一项是回滚演练。OpenClaw 使用 openclaw backup create --verify,Hermes 使用 hermes backup;更新前备份状态、固定版本、关闭自更新,再验证坏版本能否退回。作者测得包含检查的回滚耗时为 1–3.5 分钟。
我的判断
我认同这套验收方式,尤其是把「服务在运行」和「Agent 能回复」分开检查。它能揭穿不少配置正确、实际行为不符的情况。
但标题里的「证明锁定安全」说得偏满。作者没有提供不同部署方案的对照数据,恢复和回滚耗时也只是个人实测,不能拿来承诺一般团队的恢复指标。
清单还有明确前提:只开放 22/tcp 对应作者的个人 VPS 部署方式;同机承载公开网站时,需要按实际用途制定端口清单。同网段扫描也弱于互联网扫描,作者因此建议使用临时 VPS。
另外,Hermes 允许 Agent 自行写入 skill 文件,skill 白名单能发现额外文件,却无法完全阻止写入。端口检查通过,也没有解决这个权限问题。每次更新后,旧的通过记录同样不能替代重新验收。
能拿来做什么
- 给自己的 Agent VPS 建一份验收记录,写下外部端口、SSH 拒绝结果、实际封禁 IP 和恢复耗时,避免只保存配置截图。
- 如果用 Telegram 操作日常编程 Agent,把「首次成功回复」作为恢复终点,并分别测试进程崩溃和服务停止后的表现。
- 更新前核对供应商侧的额度设置,保存可恢复的状态备份,并在可丢弃的环境中演练坏版本回退;更新后重新执行关键检查。