乐于分享
好东西不私藏

AI运维实战:让AI扫描日志找到异常IP,写入黑名单封禁

AI运维实战:让AI扫描日志找到异常IP,写入黑名单封禁

AI 能在一堆琐碎、重复、容易看漏的运维材料里,帮你完成第一轮整理、归类和判断,然后把结果变成一个可以执行、可以审计、可以回滚的操作。

最近我做了一次很小的实战:扫描服务器访问日志,找出异常 IP,再写入 Nginx 黑名单。

这个过程不复杂,但很能说明 AI 运维应该怎么落地。

让 AI 先读日志、归类、解释理由、生成候选名单;最后由人确认,再让它执行明确的变更和验证。

以下用脱敏后的日志和配置举例。真实目录、时间和 IP 都做了处理。


第一步:先别把所有非 200 都当异常

日志是 JSON 行格式,每条请求大概长这样:

{"time":"D1 T+00:01","type":"request","ip":"2a0b:8bc0:2:c358::***","method":"GET","url":"/.env.production","statusCode":404,"durationMs":0.302}
{
"time":"D2 T+04:12","type":"request","ip":"23.165.184.**","method":"GET","url":"/assets?path=media%2F...jpg","statusCode":304,"durationMs":0.867}
{
"time":"D2 T+07:35","type":"request","ip":"149.154.161.***","method":"GET","url":"/openapi/x/upload","statusCode":401,"durationMs":1.424}

第一反应很容易是:非 200 都有问题。

这是错的。

在这次日志里,非 200 请求有几百条,但里面混着几类完全不同的东西:

  • 304:浏览器缓存协商,通常是正常请求
  • 303:登录后跳转,通常是正常业务行为
  • 401:鉴权失败,需要看入口和调用来源
  • 404:可能是正常缺失,也可能是扫描器探测
  • 405:方法不允许,常见于乱打 POST、OPTIONS、xmlrpc 之类的探测

所以第一步不是“找非 200 IP”,而是先把非 200 拆开。

AI 在这里很好用。它不会累,不会嫌烦,可以把每条日志按 statusCodeipurl 聚合,再给出每个 IP 的样例路径。

但它也不能替你做最后判断。因为 404 /favicon.ico404 /.env 都是 404,含义完全不一样。


第二步:异常不是状态码,是行为模式

这次日志里,排除 304 缓存命中和 303 登录跳转后,真正值得看的主要是这些行为。

第一类是敏感文件探测:

GET /.env
GET /.env.production
GET /.aws/credentials
GET /credentials.json
GET /serviceAccountKey.json
GET /.git/HEAD
GET /.git/config

这类请求基本没有误伤空间。正常用户不会访问这些路径,正常前端也不会请求它们。

比如某个脱敏 IP 45.148.10.***,在十几秒里连续扫了 .env.env.bak.env.savebackend/.env。这不是用户手滑,这是自动化扫描。

第二类是 WordPress 探测:

GET /wp-login.php
GET /wp-admin/
GET /wp-admin/install.php?step=1
GET //wp-includes/wlwmanifest.xml
GET /xmlrpc.php

服务器根本不是 WordPress,但公网服务器经常会被这种通用脚本扫一遍。这里的信号也很明确:如果一个 IP 在短时间里连续请求十几个 WordPress 路径,可以直接判定为低价值流量。

第三类是管理后台和通用漏洞探测:

GET /phpmyadmin/index.php
GET /administrator/
GET /boaform/admin/formLogin
GET /SDK/webLanguage
POST /
OPTIONS /

这类请求不一定每个都危险,但组合起来就很清楚:对方不知道你跑的是什么系统,只是在碰运气。

第四类是伪装成 API 调用的异常请求:

GET /v1/models
GET /v1/embeddings
GET /v1/completions
GET /openapi/x/upload

这类要更谨慎一点。比如 GET /openapi/x/upload 返回 401,可能是错误调用,也可能是没有带 key 的探测。只有一次的话,不一定马上封;如果同一个 IP 反复打,就要升级处理。


第三步:让 AI 给出“候选名单”,不是“最终名单”

我更喜欢让 AI 输出三层结果。

第一层是统计:

非 200 总数:约数百条
唯一 IP:约数十个
状态分布:303 / 304 / 401 / 404 / 405

第二层是按 IP 汇总:

23.165.184.**    104 次    全部 304    静态资源缓存
88.151.32.**      37 次    全部 404    robots / manifest / .aws 探测
45.148.10.***     21 次    全部 404    .env 系列探测
158.94.211.***    21 次    404/405    凭据文件和异常 POST

第三层是建议动作:

忽略:304 缓存命中
观察:少量 robots.txt / favicon.ico / sitemap.xml
谨慎观察:单次 401
建议封禁:扫 .env、.git、wp-admin、xmlrpc、phpmyadmin 的 IP

这一步很关键。

AI 如果只给你一串 IP,没有解释为什么,这个结果不值得直接用。你需要它把证据带出来:这个 IP 请求了哪些路径、状态码是什么、次数多少、是否集中发生。

对运维来说,黑名单不是“越多越安全”。封错一个真实用户,比漏掉一个低频扫描器更麻烦。

所以我最后只把高置信的异常 IP 放进 Nginx 黑名单。

例如文章里脱敏展示如下:

158.94.211.***
45.148.10.***
185.213.174.***
2a0b:8bc0:2:c358::***
2a02:4780:5e:74a5::***
34.44.123.***
149.88.20.**
192.42.116.***

真实配置里当然要写完整 IP。文章里做掩码,是为了避免泄露生产环境里的具体访问痕迹。


第四步:黑名单不要手改生成文件

很多 Nginx 配置会把黑名单拆成两个文件。

一个是维护文件,给人编辑:

/etc/nginx/ip-blacklists/

内容类似:

# One IP or CIDR per line.
158.94.211.xxx
45
.148.10.xxx
185
.213.174.xxx
2a0b:8bc0:2:c358::/64

另一个是生成文件,给 Nginx include:

/etc/nginx/ip-blacklists/

生成后类似:

deny 158.94.211.xxx;
deny
 45.148.10.xxx;
deny
 185.213.174.xxx;
deny
 2a0b:8bc0:2:c358::/64;
allow
 all;

重点是:不要直接改生成文件。

正确流程应该是:

sudo cp /etc/nginx/ip-blacklists/<global-list> /tmp/<backup>
sudo
 vim /etc/nginx/ip-blacklists/<global-list>
sudo
 update-nginx-global-blacklist
sudo
 nginx -t
sudo
 systemctl reload nginx
curl -I http://example.com/

我让 AI 执行时,也按这个顺序来:

  1. 1. 先备份维护文件
  2. 2. 写入去重后的 IP 列表
  3. 3. 重新生成 Nginx deny 配置
  4. 4. 执行 nginx -t
  5. 5. reload Nginx
  6. 6. 从公网入口验证首页仍然返回 200

这就是 AI 运维和“让 AI 直接改服务器”的区别。

AI 可以执行,但每一步都应该有边界、有回执、有验证。


第五步:别让 AI 只会封 IP

封 IP 是最直接的动作,但不是唯一动作。

这次我更在意的是建立一个可重复的运维习惯:

  • • 日志必须结构化,至少要有 time / ip / method / url / statusCode / duration
  • • 分析必须先排除正常状态,比如 304 和登录跳转
  • • 异常判断不能只看状态码,要看路径、次数、时间窗口和行为组合
  • • 变更要写入维护文件,不改生成文件
  • • 每次变更要有备份、配置测试和公网验证
  • • 候选黑名单要分级,避免把正常用户一刀切

AI 在这里像一个非常耐心的初级 SRE。

它能快速扫日志,能把几十个 IP 聚类,能给出“这个像扫描器、那个像正常缓存”的解释,能把命令组织成可执行步骤。

但它不应该独立决定所有封禁。

真正可靠的流程是:AI 负责把信息整理到足够清楚,人负责把最后的风险边界定下来。


一个小结论

AI 运维不是一个宏大的概念。

它可以从非常小的事情开始:扫日志、找模式、排除正常噪音、生成候选 IP、写入 Nginx 黑名单、验证服务还活着。

这类任务以前也能做,只是人懒得每次都做细。

现在 AI 把“细”这件事变便宜了。

它能不厌其烦地把日志读完,把异常路径摘出来,把 IP 聚合好,把命令按顺序跑完,再把结果汇总给你。

但最后最重要的不是自动化,而是可控性。

可解释、可确认、可回滚、可验证,这四个词,比“全自动”重要得多。

如果一套 AI 运维流程能做到这四点,它就不只是一个聊天助手,而是可以进入生产日常的小工具。