
最近不少运维和安全群在讨论一种现象服务器访问日志里突然出现大量 User-Agent 写为 ClaudeBot、GPTBot 之类的请求但实际访问路径并不是页面采集而是/.env、/.git/config、wp-login.php这类敏感文件探测。这不是官方 AI 爬虫的正常行为而是有人故意伪造 AI Bot 的 User-Agent进行大规模漏洞扫描。伪造者利用 AI 爬虫名称看起来合法、近两年又频繁出现在日志里的特点把扫描流量混在正常 Bot 流量中。对运维和开发来说真正重要的是学会从 User-Agent 之外的信息确认请求身份并在日志、WAF、封禁策略三层完成识别、验证和处置。如果你也在自己的 Nginx 或云安全产品里看到类似日志不要急着把所有 ClaudeBot 请求封掉也不要简单放行。这篇文章会从攻击者为什么这样做开始再给出一套从日志到封禁的最小落地流程。1. 为什么有人要伪造 ClaudeBot 这类 AI Bot 的 User-Agent1.1 伪装扫描日志到底长什么样先看一段常见但很可疑的访问日志203.0.113.7 - - [06/Feb/2025:03:11:22 0800] GET /.env HTTP/1.1 404 153 - ClaudeBot/1.0 198.51.100.23 - - [06/Feb/2025:03:11:24 0800] GET /.git/config HTTP/1.1 404 153 - ClaudeBot/1.0 198.51.100.24 - - [06/Feb/2025:03:11:27 0800] GET /wp-login.php HTTP/1.1 404 153 - Mozilla/5.0 (compatible; ClaudeBot/1.0)如果只看 User-Agent前几行确实像某个 AI 爬虫在正常抓取。但请求路径暴露了问题/.env环境变量文件、/.git/config源码仓库配置、wp-login.phpWordPress 登录入口这些都是漏洞扫描器最常探测的敏感路径。攻击者不在意返回 200 还是 404他们关心的是哪些路径存在、哪些服务会响应以及能否从响应内容中提取到价值信息。这类日志的特点是一条请求一个路径来源 IP 可能分散UA 只在字面上“看起来像官方”但访问规律和正常 AI 爬虫完全不同。1.2 伪造 AI Bot 身份能带来哪些好处攻击者伪造 ClaudeBot 这类 AI 爬虫名称不是随手写的主要有几个现实原因。第一个原因是绕过依赖 UA 的访问控制。有些站点为了配合 AI 搜索收录会在 Nginx 或 CDN 上专门放行ClaudeBot、GPTBot这类 UA有些团队还会把它们加入白名单认为它们不会带来威胁。攻击者伪造这个 UA相当于直接借用了白名单身份。第二个原因是规避基于恶意 UA 的基础封禁。像 sqlmap、Nikto、wpscan 这些扫描工具的 UA 特征非常明显很多 IPS、WAF 有现成规则可以直接拦截。把 UA 改成 ClaudeBot 之后传统规则失效流量更容易到达业务服务器。第三个原因是降低人工分析时的警惕性。安全告警每天会产生大量日志看到 ClaudeBot、GPTBot 这类名称很多分析师第一反应是“正常 AI 爬虫”不会第一时间深入排查。攻击者利用的正是这种思维惯性。1.3 User-Agent 是自述身份不能作为唯一依据需要注意HTTP 协议中的 User-Agent 是请求方自己声明的“身份”客户端可以随意修改。用一行命令就能演示curl -A ClaudeBot/1.0 https://example.com/robots.txt服务器端收到这个请求后只能看到User-Agent: ClaudeBot/1.0无法判断发请求的到底是 ClaudeBot 官方爬虫还是某个扫描器。基于同样的原理攻击者完全可以在扫描脚本里伪造任意 UA。所以对 User-Agent 的正确态度是它只能作为第一层分流标识不能作为信任依据。真正要判断一个流量是否可信必须组合来源 IP、请求行为、访问频率和路径特征来判断。2. 三层识别法从身份、来源、行为判断真假2.1 第一层身份核对 UA 字符串本身虽然 UA 可以伪造但它仍然是第一道过滤条件。这里要做的是“精确匹配”而不是“模糊包含”。以 ClaudeBot 为例官方爬虫的 UA 命名通常有固定格式一般形如ClaudeBot/1.0或Mozilla/5.0 (compatible; ClaudeBot/1.0; 官方说明页)。如果日志里出现ClaudeBot/1.0后面还拼接了.net、.php、scanner、test等字符或者大小写、空格明显异常就需要怀疑是伪造样本。更严谨的做法是维护一个“已知 AI Bot UA 样本库”。这个样本库包括三部分官方公开文档中声明的 UA 格式。线上访问日志中确认为官方爬虫的 UA。社区报告确认过存在伪造的 UA 变体。判断原则很简单字符串完全匹配可能有风险需要继续看下一层字符串不匹配但行为像抓取器可能是普通爬虫也可能是扫描器同样要继续看来源和行为。2.2 第二层来源IP 段、ASN 与反向 DNS来源验证是识别伪造 AI Bot 最重要的手段。User-Agent 可以随便改但正常情况下一个 TCP 连接必须有真实的源 IP攻击者可以使用大量 IP 发起扫描但很难让自己的一台扫描机同时出现在正确的云厂商网段里。先看 IP 归属whois 203.0.113.7查询结果会显示 IP 所在网段、运营商和组织名称。比如查询到Organization: Example Cloud、CIDR: 203.0.113.0/24这时再看这个组织是否与官方 AI 爬虫公开的网段一致。再看反向 DNSdig -x 203.0.113.7官方爬虫的 IP 通常会配置反解反解域名会包含明显标识比如某个爬虫名称或官方域名后缀。如果源 IP 反解结果为空或者反解域名是一串随机数字甚至指向一个与 AI 爬虫完全无关的 IDC 机房那么即使 UA 写得再像官方也要提高警惕。这里的难点是官方 AI 爬虫不一定会公开完整的 IP 清单部分云厂商 IP 还会动态变化。所以来源信息不能作为绝对判断要结合行为一起看。2.3 第三层行为请求路径、频率和抓取顺序正常 AI 爬虫的工作方式通常有清晰的抓取顺序先请求robots.txt再根据 sitemap 或页面里的链接去抓取页面内容请求的路径大多是可访问的业务 URL频率相对可控。漏洞扫描器不是这样工作的。扫描器通常携带一份路径字典按字典顺序挨个发起请求比如/.env /.git/HEAD /.git/config /wp-login.php /wp-admin/ /api/v1/ /actuator/env /backup.sql它们不会先看 robots.txt也不会在意页面结构和链接关系只关心路径是否存在、响应状态码是什么、返回内容里有没有敏感信息。如果一个“ClaudeBot”在同一个 IP 下十秒内连续请求这些路径那基本可以确定不是官方 AI Bot而是伪造 UA 的扫描行为。还可以观察请求频率是否规律。正常抓取会有一定间隔扫描器为了赶时间常常高并发。如果同一个 UA 在凌晨两三点对同一台服务器发起几百个不同路径的请求而且大部分是 404攻击的可能性很高。2.4 三层组合判断不要只看单一条件维度正常 AI Bot 常见表现伪造 AI Bot 常见表现UA 匹配UA 与官方公开字符串一致格式稳定UA 相似但夹杂异常字符或版本不一致来源 IP来自官方或合作云厂商网段可能有固定 ASN来源分散在多个 IDCASN 与官方声明不一致反查 DNS反解域名包含可识别标识无反解或反解指向无关域名访问路径先请求 robots.txt再抓取业务链接直接路径枚举/.env、/.git/config等抓取频率有间隔并发受控短时间高频请求规律不明显参考链接一般带正常 Referer请求头完整缺少 RefererHeader 不自然单条请求命中某一项不能说明什么比如正常业务方也可能偶尔访问/.env路径。但如果“UA 匹配 来源可疑 敏感路径 高频”这四件事同时出现基本可以进入拦截流程。3. 落地检测从 Nginx 访问日志找出可疑 Bot 流量3.1 先统一日志格式保证能取到关键字段在排查之前要确保 Nginx 访问日志记录了足够信息。推荐使用包含客户端 IP、时间、请求、状态码和 UA 的格式log_format main $remote_addr - $remote_user [$time_local] $request $status $body_bytes_sent $http_referer $http_user_agent; access_log /var/log/nginx/access.log main;如果业务部署在 CDN 或七层负载均衡后面$remote_addr可能是 CDN 节点 IP而不是真实客户端 IP。这种情况要使用X-Forwarded-For或 CDN 平台提供的真实客户端 IP 变量但同时要注意这些 Header 可以被伪造。生产环境必须先验证源站是否只信任来自 CDN 的请求避免攻击者直接伪造 Header 绕过记录。3.2 用 Python 脚本按特征聚合可疑请求先统计 UA 里出现 ClaudeBot、GPTBot、Bytespider 等关键词的 IP找出最活跃的来源from collections import Counter from pathlib import Path log_file Path(/var/log/nginx/access.log) fake_ua_keywords (ClaudeBot, GPTBot, Bytespider) sensitive_path (/.env, .git/config, wp-login.php, actuator, .bak, .sql) ip_counter Counter() sensitive_counter Counter() lines log_file.read_text(encodingutf-8, errorsignore).splitlines() for line in lines: if not any(keyword in line for keyword in fake_ua_keywords): continue fields line.split() if not fields: continue ip fields[0] ip_counter[ip] 1 if any(path in line for path in sensitive_path): sensitive_counter[ip] 1 print(出现伪造 AI UA 关键词的 Top 20 IP) for ip, count in ip_counter.most_common(20): print(f{count:8d} {ip}) print(命中敏感路径的 Top 20 IP) for ip, count in sensitive_counter.most_common(20): print(f{count:8d} {ip})这个脚本的思路是先筛选 UA再筛选路径最后按 IP 聚合。实际生产环境不需要硬编码在脚本里可以把日志接入 ELK、ClickHouse 或云原生日志服务用同样的逻辑做可视化统计。这里要注意一个坑不要直接在整个日志文件上一次性过滤。生产环境日志量很大建议先tail -100000或按时间窗口切分日志再进行分析。3.3 时间维度瞬时突增是更可靠的信号IP 数量和路径命中只是其中一个维度。伪造 UA 的扫描器往往会在短时间内集中爆发所以把时间维度加进来判断更准确。统计指定时间内每分钟请求量tail -100000 /var/log/nginx/access.log \ | grep ClaudeBot \ | cut -d[ -f2 | cut -d] -f1 | cut -d: -f1-3 \ | sort | uniq -c | sort -rn | head -20输出结果类似147 06/Feb/2025:03:11 98 06/Feb/2025:03:12 12 06/Feb/2025:03:13如果同一个来源 IP 在某一分钟内连续产生几十条到上百条请求而且请求路径全是/.env、/.git/config、wp-login.php这类路径说明这不是正常 AI Bot 的抓取节奏而是扫描器正在跑字典。时间窗口聚合的价值在于它能把“少量误报”和“批量扫描”区分开。正常抓取也会请求多个路径但不会在几秒内密集命中大量敏感路径。建议把“单位时间内同一个 IP 命中敏感路径次数”作为告警条件而不是单纯看 UA。这样即使对方换个 UA 名称只要行为仍然是扫描一样能触发。4. 自动处置从 Fail2ban 到 WAF 策略4.1 Fail2ban 拦截“敏感路径 伪 AI UA”在单台 Linux 服务器上快速落地时Fail2ban 是成本最低的方案。思路是在 Nginx 访问日志中匹配特定 UA 和敏感路径超过阈值后自动封禁源 IP。先创建过滤器比如/etc/fail2ban/filter.d/fake-ai-bot.conf[Definition] failregex ^HOST .*(?:GET|POST|HEAD) \/(?:\.env|\.git\/config|wp-login\.php|\.\.\/\.\.\/).* 404 .*ClaudeBot/1\.0$ ignoreregex 再在/etc/fail2ban/jail.local中启用[fake-ai-bot] enabled true port http,https filter fake-ai-bot logpath /var/log/nginx/access.log findtime 60 maxretry 5 bantime 3600参数含义参数说明示例值findtime统计时间窗口单位秒60maxretry时间窗口内匹配的最大次数5bantime封禁时长单位秒3600logpath日志文件路径/var/log/nginx/access.log配置完成后先测试正则是否匹配真实日志fail2ban-regex /var/log/nginx/access.log /etc/fail2ban/filter.d/fake-ai-bot.conf这个工具会显示匹配次数。如果正则不匹配需要检查日志格式与正则中的字段顺序。4.2 WAF 的挑战与限流思路Fail2ban 适合单机和简单场景但对于多节点、分布式扫描和 CDN 场景更推荐在 WAF 层处理。WAF 通常提供三种能力Bot 管理识别常见爬虫和工具 UA并支持自定义 Bot 特征。JS Challenge对可疑请求下发一段 JavaScript 挑战正常浏览器能通过大多数命令行扫描工具无法完成。速率限制按 IP、Session、UA 组合限流。实际策略不要直接对 ClaudeBot 返回 403而是先分级正常且可验证的官方 AI Bot - 放行并限速 可疑 UA 但来源未知 - JS Challenge 或 429 疑似扫描 命中敏感路径 - 403 或封禁这样的好处是减少误伤。有些站点希望被 AI 搜索索引如果把所有 ClaudeBot 都封掉可能会造成收录异常。进入挑战流程后官方 Bot 即使无法完成 JS 挑战也有机会通过后续 IP 验证流程放行。4.3 封禁、观察、复核的完整处理流程任何自动封禁都可能误伤尤其涉及到 AI Bot 名称时。建议按下面顺序执行自动发现日志或 WAF 识别到“UA 疑似 AI Bot 敏感路径 高频”。临时限速先对该 IP 启用较慢的限速策略而不是直接 403。人工复核查看 IP 归属、ASN、反向 DNS 和该 IP 的完整请求序列。确认封禁如果确认为扫描再封禁 IP 或 IP 段并设置合理时长。定期复查每天检查被误杀的请求调整规则。保留证据把原始日志、请求头和响应状态保存下来便于后续调整规则。这里重点强调第六步。很多团队封完就不管了后来才发现某个正常爬虫 IP 被规则误伤。保留日志和规则快照可以让误伤恢复变得可操作而不是只能靠“感觉”。5. 避免误伤官方 AI Bot 和伪造扫描器怎么区分处理5.1 官方 AI Bot 通常会有哪些可验证特征虽然不同 AI 爬虫的实现细节不同但公开服务通常有相对稳定的特征会遵守robots.txt并且很多官方文档会说明爬虫用途和联系页面。会使用固定 UA并且 UA 中可能包含官方说明页地址。来源 IP 有较明确的云厂商或自有网段部分会公布 IP 范围。抓取行为以采集页面内容为主不会高频请求/.git、/.env这类路径。官方 AI Bot 也不一定永远表现完美比如某些海外云厂商的爬虫会访问不支持的地域、频繁请求动态接口但这不能作为直接封禁理由。更好的做法是建立“正常样本”和“可疑样本”两个队列持续观察。5.2 参考分级处理策略情况建议处理UA 匹配IP 归属正常访问路径正常放行并设置每秒请求数上限UA 匹配IP 归属未知但路径正常临时放行记录日志并持续观察UA 匹配IP 归属未知命中敏感路径限速观察后续行为UA 匹配IP 归属可疑高频命中敏感路径直接封禁至少封禁 24 小时UA 不匹配但行为与官方 AI Bot 一致按普通爬虫处理不做特殊放行在生产环境里建议把“UA 匹配”和“行为匹配”分开记分而不是用布尔判断。例如UA 匹配官方格式1 IP 归属在官方网段3 先请求 robots.txt2 命中敏感路径-3 短时间高频请求-2 缺少 Referer-1最终分越高越可信越低越可疑。这样即使攻击者不断更换 UA只要行为特征不变分数依然会偏低。提醒最好不要在规则里写死“只要 UA 等于 ClaudeBot 就放行”。AI 爬虫名称会不断增加和变化要把判断重点放在“来源和行为”上。6. 生产环境排错与预防清单6.1 接到告警后的排查顺序如果线上已经出现大量伪造 AI Bot 扫描建议按下面的顺序排查而不是先找封禁命令。第一步看告警信息和时间窗口确认是哪台服务器、哪个域名、什么时间段开始异常。第二步提取原始日志不要只看聚合结果。先从日志里复制几条最可疑的完整请求行看 UA、路径、状态码、Referer 和来源 IP。第三步验证来源 IP。使用 whois、ASN 查询和反向 DNS 解析判断该 IP 是否在 AI Bot 官方网段范围内。这里要注意很多攻击者会使用云主机IP 归属看起来也是正常云厂商所以不能只看“是不是云厂商”要看“是不是官方公告中使用的云厂商和网段”。第四步确认 CDN 场景下是否拿到真实 IP。如果源站只信任 CDN 转发请求日志里出现的客户端 IP 才可信如果攻击者直接访问源站入口日志里记录的 IP 可能不是真实攻击源。第五步再决定处置动作。如果是少量误报先限速后观察如果是大规模扫描就加入 WAF 规则或临时封禁。6.2 上线前和日常防护检查清单很多服务器既没有统一的访问日志格式也没有 WAF 规则出了问题只能临时翻日志。下面这份清单可以用于新服务上线前检查也适合作为日常巡检项访问日志是否记录了完整 UA、Referer、状态码和响应时间。是否有/.env、/.git、/wp-login.php、/actuator等敏感路径的访问告警。是否对源站入口做了访问控制避免 CDN 后的真实 IP 泄露。是否配置了限速策略尤其是 UA 为常见 AI Bot 的请求。是否维护了已知 AI Bot IP 段和 UA 样本库并定期更新。是否有误报回滚机制封禁后如何快速放行正常爬虫。是否对封禁规则做每日或每周复盘。其中“源站真实 IP 泄露”经常被忽略。攻击者可以直接扫描源站 IP绕过云 WAF即使你把 WAF 规则写得再好也会失去意义。所以生产环境要确保源站只允许 CDN 节点、负载均衡器或白名单网段访问。6.3 从“封 UA”升级到“行为基线”长期来看只靠 UA 关键词做防御是不够的。攻击者会不断学习新的 UA 名称今天伪装 ClaudeBot明天就可能伪装其它 AI 爬虫。真正有效的方式是建立流量行为基线正常业务接口的