服务器上线 100 秒,就有人来敲门:一次登录日志排查与 AI 时代的自保清单
那个周日晚上,我本来只想让 AI 助手扫一眼 7 台服务器的登录日志:几台云主机,加上机房里三台跑 Kubernetes 的节点。我原以为几分钟就能看完。
AI 交回的第一份汇总里有一行,我看了三遍:其中一台节点开机后大约 100 秒,就有人开始试它的 root 密码。
接下来的一周,两个荷兰 IP 在这台机器上试了一万三千多次密码,换着用了四千多个用户名。
更让我在意的是它的节奏。99.8% 的相邻两次尝试间隔在 30 到 59 秒之间,一天 24 小时,每小时 85 到 90 次,从不加速,也从不停,像一台节拍器。
一次都没成功。可这台节拍器为什么要走得这么慢?
慢,是冲着你的防御来的
我在另一台云主机上装了 fail2ban,用的是网上教程里最常见的配置:10 分钟内失败 5 次,封 1 小时。
我去翻了它的战绩:日志里记了 7430 次失败,fail2ban 总共只封了 3 个 IP。
道理很简单:对方每 3 分钟才试一次,10 分钟里最多 3 次,永远碰不到阈值。这叫低速爆破,节奏就是照着默认配置的尺寸裁出来的。我那套防护,在对手眼里跟没装一样。
再看它们的字典:zyj、zjq、xushiyuan 这类拼音缩写,加上 dell、inspur、sugon、nvidia-smi 这类服务器和 GPU 厂商的名字。目标很明确,是国内高校和科研单位的 GPU 机器。它们不认识我,只是在把整片网段扫一遍,我正好在里面。
那一晚最吓人的三次,都和攻击者无关
第一次,我以为密码泄露了。 日志显示,某台机器刚改完 root 密码,34 秒后,一个杭州 IP 用新密码一次就登录成功,会话只持续了 2 秒。我顺着时间线查了半天,最后确认是服务商面板在改密后自动测试了一次连接。虚惊一场,但我也因此发现,自己平时根本分不清哪些登录是自己人。
第二次,泄露的是我自己。 初始化机器时,我在 VNC 控制台上把密码敲进了用户名栏,系统把它当作用户名,明文写进了日志。后来又在三台节点的 /root/.bash_history 里翻到了这样一行:
echo 'root:明文密码' | chpasswd这是做系统模板时留下的,用这个模板克隆出来的每一台机器都带着它。同一份 history 里,还有一个配了 NOPASSWD: ALL 的跳板账号的密码,这个账号的权限等同 root。
第三次,我以为有人在擦痕迹。 我准备去清理那几行 history,发现它们已经不见了:三台机器,每台正好少了两行,修改时间依次间隔几秒。我脊背一凉。再查登录记录,那三次会话用的是我的 key,来源是我家的 IP。原来我同时开着另一个 AI 会话,给了它同样的指令,它先动手删掉了。
这一晚教会我的一件事是:以后有人问「谁动了我的服务器」,答案很可能是你自己的另一个 agent。如果人、各个 agent 和攻击者在日志里都长得差不多,出了事你根本说不清楚。
AI 时代,攻守两边的成本都变了
以前我总觉得,真正厉害的攻击需要一个团队。
Anthropic 在 2025 年 8 月的威胁情报报告里写过一个案例:一名攻击者让 Claude Code 自动完成侦察、窃取凭据和渗透内网,一个月里至少打进了 17 家机构,涉及医疗、应急服务、政府和宗教组织;AI 甚至被用来分析偷到的财务数据,决定开多少赎金,有的赎金要价超过 50 万美元。同一份报告里还有一个只有基础编程能力的人,靠 AI 开发出勒索软件,在论坛上以 400 到 1200 美元一份出售(Anthropic, 2025-08)。到 2026 年 9 月的报告,已经能看到犯罪团伙用 AI 加速「扫描、利用、接管目标系统」的全过程(Anthropic, 2026-09)。
所以,门外那台节拍器的成本只会越来越低。
防守这一侧也在变,而且变化就发生在我们自己手里。我们开始让 AI 拿着 root key 批量操作服务器:它会顺手开一个端口,会按你的要求把密码打印到终端(这串密码从此留在了会话记录里),也会和另一个 agent 同时改同一份配置。每一步都是你授权的,每一步都比人工快,也都更难被察觉。
你的机器不值钱?它本身就是资源
很多人觉得:我就一个小博客,谁会盯上我?
问题在于,攻击者要的往往不是你的数据,而是你的机器本身。
Palo Alto 的 Unit 42 在 2023 年追踪 P2PInfect 蠕虫时统计过:两周内能从公网连上的 Redis 超过 30.7 万个。被感染的 Redis 还会反过来去扫描别人的 SSH 22 端口(Unit 42)。后来的变种会往 authorized_keys 里塞自己的公钥,再装上挖矿程序(Darktrace)。
读到这里,我想起了门外那台节拍器。那两个 IP 背后,说不定也是某个人被攻陷、自己还不知道的服务器。我没办法证明这一点,但这个可能性让我很不舒服:一台机器一旦沦陷,它就成了下一个去敲别人门的节拍器。
然后我做了一个随手的测试:用 Docker 跑的缓存和数据库,端口在公网上可以直接连通。Docker 发布端口时,流量会在进入 ufw 的规则之前就被转走,官方文档写得很清楚(Docker Docs),云厂商的安全组也没挡住。SSH 被爆破至少还会留下一万多行失败日志;暴露在公网的数据库被人利用时,可能一行记录都没有。
那一晚真正让我后怕的,是这扇我自己打开、却一直没注意到的门。
真正会让你「喝茶」的
对国内有网站的人来说,最坏的结局往往不是数据丢了,而是网站和机器被人拿去干违法的事:
- 首页被整个换掉。 换成博彩、色情或诈骗页面。
- 被挂暗链。 这类黑帽 SEO 手法只对搜索引擎爬虫显示赌博链接,你自己用浏览器打开一切正常,搜索结果里却全是你的域名。
- 服务器成了作恶的工具。 被当作诈骗网站的中转,或者攻击他人的跳板。
备案和云账号都是实名的,查过来首先找的是你。
2025 年 10 月修正的《网络安全法》写得很直白(全文):
- 第二十三条: 网络运营者要采取防范网络攻击、网络侵入的技术措施,并留存相关网络日志不少于六个月。
- 第六十一条: 不履行这些义务的,可以警告,处一万元以上五万元以下罚款;拒不改正或者导致危害后果的,处五万元以上五十万元以下罚款。
- 第四十九条和第六十九条: 发现违法信息不及时停止传输、消除并报告的,可处五万元以上五十万元以下罚款;情节严重的,罚款最高二百万元,并可以关闭网站、吊销许可证。
个人站长在具体案件里怎么被认定、怎么处罚,要看实际情况,这里不构成法律意见。但有一点是确定的:出了事,你得拿出日志来说明发生了什么,说明你自己不知情。日志只留了一周,这些话就很难讲清楚。
暗链可以这样自查:把自己伪装成百度爬虫请求一次首页,和正常请求的结果对比。
diff <(curl -s https://你的域名/) <(curl -s -A "Baiduspider" https://你的域名/)两次返回的内容不一样,就要仔细查了。
我现在的做法
下面这些做法,按投入由少到多排列。
今晚就能做,十分钟左右
1. SSH 只允许 key 登录。 这一条做到了,门外那一万多次尝试就全部作废。
cat > /etc/ssh/sshd_config.d/00-hardening.conf <<'EOF'PasswordAuthentication noKbdInteractiveAuthentication noPermitRootLogin prohibit-passwordEOFsshd -t && systemctl reload sshsshd -T | grep -E 'passwordauthentication|permitrootlogin' # 确认实际生效的值sshd 对同一个配置项只采用第一次出现的值,Ubuntu 在主配置的开头引入 sshd_config.d/,所以文件名以 00- 开头最稳妥。改之前一定要先另开一个窗口,确认 key 能登录。我吃过这个亏,经过写在《改个 SSH 端口,我把自己锁在了服务器外面》里。
顺便说一个可能有人不同意的观点:改 SSH 端口没什么用。我那台节点是通过 NAT 映射到一个高位端口对外的,照样开机 100 秒就被找到。改端口只能让日志清净一点。
2. 看一眼谁登录过你的机器。
grep -a "Accepted" /var/log/auth.log* | grep -oE "Accepted \S+ for \S+ from \S+" | sort | uniq -cssh-keygen -lf ~/.ssh/authorized_keys # 这里的每一把 key 你都认识吗CentOS 等发行版把这类日志写在 /var/log/secure。每一条 Accepted 你都要能说出是谁;authorized_keys 里多出一把你不认识的 key,就可以按失陷处理了。
这周抽空做
3. 把 fail2ban 调成针对低速爆破。 我现在用的是 3 次失败永久封禁,统计窗口拉长到 7 天:
[DEFAULT]ignoreip = 127.0.0.1/8 ::1 <你自己的出口网段> <其他服务器的IP>maxretry = 3findtime = 7dbantime = -1banaction = nftables[type=allports]
[sshd]enabled = truemode = aggressive# /etc/fail2ban/fail2ban.local(让永久封禁记录在重启后不被清掉)[DEFINITION]dbpurgeage = 3650d有两处坑:
- 白名单一定要配。 你自己手滑输错 3 次,被永久封掉的就是你。机器之间有互访的话,比如证书同步脚本会用 key 登录另一台,对方的 IP 也要加进去。
- 装完先验证过滤规则。 新版 OpenSSH 的日志进程名变成了
sshd-session,先跑一次fail2ban-regex /var/log/auth.log sshd,确认能匹配到日志行。装上不等于生效,这一点我前面已经吃过亏了。
4. 从外面看自己的暴露面。 ss -tlnp 只能告诉你本机在监听什么;能不能从公网连上,要在另一台机器上执行 nc -z 你的IP 端口 去试。数据库和缓存一律只绑定内网地址,Docker 里写成 "127.0.0.1:6379:6379";安全组默认拒绝,需要什么再单独放行。
5. 凭据别进 history。 改密码时这样写,密码不会进 history,也不会出现在进程列表里:
read -rs PW && echo "root:$PW" | chpasswd && unset PW另外有两件事:模板镜像在制作完成前清空 history;用不到的高权限账号直接用 passwd -l 锁掉。
6. 日志至少留六个月,并接上告警。 把「非白名单来源登录成功」推送到手机上,不要等哪天想起来才去翻。推送我用的是自建 ntfy,搭法见《自建 ntfy:Docker 服务端部署与手机、桌面客户端接入》。
给 AI agent 立规矩
这一条是我这次才补上的,也是我最想让你带走的:
- 每个 agent 一把单独的 key。 在
authorized_keys里用from=限制来源,这样日志里能分清是你本人、是哪个 agent,还是外人。 - 生产环境的写操作只交给一个执行者。 两个 agent 同时改 sshd 配置,只会互相覆盖。
- 在指令里写明:不要把密码或 token 打印到终端。 AI 的会话记录存在哪里、同步到了哪里,你未必说得清。
关于 WAF,泼一点冷水
有人建议直接上雷池这类 WAF。它确实能挡 SQL 注入、XSS 和 CC 攻击,也能给后台加一道人机验证。
但它只管 HTTP:SSH 爆破它看不见,公网上的数据库它也管不到。它还要占一台机器的资源:官方要求 CPU 支持 SSSE3(雷池文档),会拉起一整组容器,还要自己终止 TLS,和你现有的反向代理抢证书。
我的顺序是:先关掉不该开的端口,SSH 改成只认 key,fail2ban 调对,日志留够六个月并接上告警,最后才考虑 WAF。如果你的网站有登录、评论、上传这类交互功能,WAF 值得排进计划;只是一个静态博客的话,把源站锁死、前面挂 CDN,定期跑一遍上面那条暗链检查命令,投入产出比更高。这个博客就是这么做的:前面挂 EdgeOne,源站 Nginx 对不是从 EdgeOne 过来的请求直接返回 403,再加一层轻量的 Nginx WAF。
写完这篇的时候,那台节拍器还在门外,每 40 秒敲一下。区别是门已经锁上了,它们的 IP 也进了永久黑名单。
你的服务器门口,大概也有这么一台。今晚花十分钟,跑一遍那条 grep Accepted。