🔒保护访问安全
一台随处可达、还会执行 AI 生成代码的机器:安全不是可选项。SSH 密钥、防火墙、密钥、代理权限。如何不胡来。
回顾一下您搭起来的东西:一台 7×24 运行、能从手机访问、把服务暴露到互联网上、而且会执行 AI 提议的命令的机器。这很棒。但它同时也是一片需要认真对待的攻击面, 不是出于偏执,而是出于卫生习惯。
好消息是:90% 的安全只需几个简单的动作,做一次就行。这篇就是这些动作。没有一个是复杂的。可一旦跳过,反而可能把您的工坊变成垃圾邮件中转站,甚至更糟。
1. SSH:用密钥,永远别用密码
远程访问走的是 SSH。一个暴露在外的 SSH 密码,是互联网上头号攻击目标, 机器人每天测试上百万种组合。对策一劳永逸:关掉密码认证,改用密钥。
一把 SSH 密钥是一对:私钥留在您的笔记本上(绝不放别处),公钥放到机器上。没有私钥,谁也进不来, 哪怕知道您的用户名也没用。
在您的电脑上生成密钥(不是在 mini-PC 上)
# 在您的笔记本上。Ed25519 = 现代、短小、可靠。
ssh-keygen -t ed25519 -C "laptop-vers-minipc"
路径保持默认,设一个口令(passphrase)(万一笔记本被偷,这是最后一道屏障)。
把公钥放到机器上
ssh-copy-id ulrich@adresse-de-la-machine
测试连接:ssh ulrich@adresse-de-la-machine 应该不问密码就进去。
关掉密码
在 mini-PC 上,编辑 /etc/ssh/sshd_config(您的代理可以做,告诉它您要什么):
PasswordAuthentication no
PermitRootLogin no
然后重载:sudo systemctl restart ssh。在确认新的密钥连接能用之前,留一个已打开的会话,以防万一。
2. 防火墙:全部关闭,只留必需的
默认情况下,我们拦下所有进来的流量,再一点一点地放行。ufw 让这件事变得轻而易举。
sudo ufw default deny incoming # 默认拒绝一切
sudo ufw default allow outgoing # 机器可以往外连
sudo ufw allow 22/tcp # SSH(如果走 Tailscale 就什么都不开)
sudo ufw enable
sudo ufw status verbose # 检查一下
3. 密钥:永远不明文,永远不进代码
API 密钥、令牌、服务密码:这些都是密钥(secrets)。规则是绝对的:密钥绝不以明文形式存在于代码中,也绝不进入被 git 版本管理的文件。
把密钥放进一个 git 之外的 .env 文件
# 项目根目录下的一个 .env 文件
echo "ANTHROPIC_API_KEY=sk-..." >> .env
# 而且最重要的是,把它排除在 git 之外
echo ".env" >> .gitignore
代码读取环境变量,它从不包含具体的值。
锁死敏感文件的权限
chmod 600 .env ~/.ssh/id_ed25519 # 只有您能读
对泄露过的东西做轮换
如果某个密钥曾经留在某处(一次提交、一次复制粘贴、一张截图),就把它当成已泄露,并重新生成它。一个 API 密钥点两下就能吊销并重建。白白轮换一次,也好过对泄露视而不见。
您的密钥到底该存哪里
.env 文件足够起步,但一旦您攒下越来越多密钥(AI 的 API、GitHub 令牌、各种服务的访问权),就该问问自己什么才是合适的保险箱。这里有个从简到强的小层级:
- 每个项目一个
.env文件, 起点。放在 git 之外,chmod 600。对个人项目来说很完美。它的局限:密钥明文躺在磁盘上,而且会从一个项目复制到另一个项目。 - 钥匙串 / 密码管理器, 给您个人的密钥储备(也就是真相之源),一个真正的管理器(Bitwarden、1Password、KeePassXC……)加密保存,胜过一千个散落各处的文本文件。需要时您从里面取出来填进
.env。 - 静态加密的保险箱, 为了把密钥存进仓库而不暴露它们,像
sops+age或pass这样的工具会加密这些值:文件可以版本化,只有持有解密密钥的人才能读。当项目变大或要共享时,这是专业的一步。 - 专门的密钥管理服务, 面向认真的多机场景(Vault、Infisical、Doppler……),由一个服务集中管理、审计并轮换密钥。一开始大概超出您的需要,但路最终是通向这里的。
4. 给代理划界限:它执行,您决定
这是我们这套配置特有、也最重要的部分。一个编码代理之所以强大,正因为它能运行命令。这也正是它在无人看管时变危险的原因。几条常识规则:
- 绝不让代理跑在
root下,绝不自动sudo。 它在您的普通用户下运行。当一条命令需要sudo时,您要亲眼看到并手动批准它。一条在 root 下运行的破坏性命令是不留情面的。 - 「自动批准」模式得靠争取。 代理常常提供一种不问您就执行的模式。用来迭代测试很棒;但凡涉及网络、密钥、删文件(
rm)或生产环境的,一律禁止。 - 在项目文件夹里干活,别在
~或/里。 把代理的作用半径限制在项目文件夹内。万一它跑偏,损害也被困在里面。 - 生成的代码在上生产前要重读一遍。 一个代理可能无意间引入漏洞(一条转义不当的 SQL 查询、一个过宽的权限)。重读一遍, 由您,或由第二个充当「评审」的代理, 不是奢侈。
- git 是您的安全网。 频繁提交。如果代理干了蠢事,您总能回退。一个没有 git 历史的项目,就是没有安全网的杂技演员。
5. 让机器保持更新(不用操心)
一个被修复的漏洞就不再是漏洞了, 前提是装上补丁。我们把安全更新自动化:
sudo apt install unattended-upgrades
sudo dpkg-reconfigure --priority=low unattended-upgrades # 回答「是」
机器从此自己安装安全补丁。至于其余的(版本升级),时不时来一次 sudo apt update && sudo apt upgrade 就够了, 您的代理可以提醒您。
6. 安全网:备份
安全不只是拦住入侵者。也是要扛过您自己的失误、一块罢工的硬盘、一个太热心的代理。把重要的东西(您的项目、您的配置、您那些 .env, 加密后)备份到机器之外:另一块硬盘、一个 NAS、一处远程存储。一个您从没试着恢复过的备份,不算备份。