公司动态
当ClaudeBot成为攻击面具:识别与拦截伪装爬虫扫描
凌晨一点我本想看一眼服务器今天的访问情况tail 出来的日志却让人睡意全消。过去十分钟Nginx 的 access log 里刷进来上千条请求User-Agent 整整齐齐写着 ClaudeBot。第一反应是 Anthropic 的爬虫又来抓内容了。可下一秒就不对劲——URL 路径全是 wp-login.php、.env、config.php.bak、.git/config 这类组合这哪是抓网页内容这是在试探站点有没有可被利用的入口。“ClaudeBot”跑来做批量漏洞扫描已经不是孤例。在不少站长的日志里同样的戏码正在反复上演攻击者不用自己的 User-Agent而是把身份伪装成正牌的 AI 爬虫比如 ClaudeBot、GPTBot、Bytespider。日志上看是 AI 机器人密集访问实际是一轮早期的批量漏洞探测。这篇文章不打算讲攻击手法而是想从运维和站长的视角聊清楚一件事当“AI 爬虫”出现在不该出现的路径上你怎么识别、怎么拦截、又该怎么避免误伤真正有价值的抓取流量。1. 别急着骂 AI 爬虫先看清日志里的行为差异真实情况是ClaudeBot 这类正规爬虫确实会持续、大量地访问公开网页这也是很多站长在日志里看到大量 AI bot 请求的原因。它本身不是问题。问题在于这些请求的路径完全超出了爬虫的正常行为范围。1.1 现象ClaudeBot 为什么不该出现在这些路径上从官方说明看ClaudeBot 是 Anthropic 用于抓取公开网页内容的机器人主要服务于模型训练和内容处理这类任务。它的行为模式通常更接近一个常规网络爬虫会先请求 robots.txt抓取路径以内容页、列表页、静态资源为主请求以 GET 为主速率保持在相对可控的范围内。而日志里那些伪装请求完全不是这个画风一分钟内连续请求大量已删除、不存在或明显不该公开访问的路径路径组合像字典枚举.env、.bak、.sql、.git/config、phpMyAdmin、adminer.php、wp-login.php以及带日期后缀的备份文件名某些请求带 POST 方法打在登录接口、上传接口或 API 接口上不请求 robots.txt不按网站目录结构走一上来就直奔高价值目标。这时候 UA 写什么已经不重要了。行为已经构成“批量漏洞扫描”的特征。真正值得关注的是为什么它敢大摇大摆地顶着 ClaudeBot 的名字进来1.2 一个关键判断单看 UA 已经说明不了任何问题很多站点在接入 WAF 或写访问控制策略时习惯用 UA 判断“这是不是好机器人”。这个习惯在早期还能用但现在基本失效了。原因很直接User-Agent 是一段由客户端自行声明的文本没有任何协议层面的强制校验。同样一个 HTTP 请求可以标成浏览器可以标成搜索引擎爬虫也可以标成 Anthropic 的 ClaudeBot服务端光看这一行字无法区分谁真谁假。所以这里先给出全文的主判断不要把“识别爬虫”当成一次 UA 过滤而要当成一次行为审计。UA 只能作为辅助线索真正能说明问题的是请求路径、请求方法、来源 IP、请求节奏以及访问后的状态码分布。注意看到“ClaudeBot”访问 .env 这类路径时不要直接给 Anthropic 发邮件质询先确认日志里的行为是否真的来自官方爬虫。多数情况下这只是一个借了壳的扫描器。2. 为什么攻击者要伪装成 ClaudeBot 这类爬虫伪装成 AI 爬虫不是新鲜事但这两年明显变多。背后不是某个单一原因而是三件事凑到了一起。2.1 伪装成本几乎为零一个 curl 请求就能把 UA 改成任何值curl -A ClaudeBot/1.0 https://example.com/wp-login.php这不是什么复杂攻击技巧它只是利用了 HTTP 头“自报家门”这一基础事实。问题在于一旦这种零成本伪装开始流行传统基于 UA 的放行策略就成了默认突破口。有的站点配置了“对 AI 爬虫放行”有的站点为了观测流量来源保留了各大搜索引擎和 AI 爬虫的访问权限甚至还有一些站点专门给这类爬虫开了较高优先级。伪造成 ClaudeBot 或 GPTBot等于直接进入了这些“受信任名单”。2.2 信任 AI 爬虫的惯性成了最好的掩护这里还有一个容易被忽略的心理因素。当一个 UA 写着大厂 AI 爬虫的名字时运维第一反应通常不是拦截而是“这是别人家的正规机器人尽量别误伤”。尤其像 ClaudeBot 这类爬虫抓取量大、官方有文档说明、IP 段也可能横跨多个云厂商站长更不愿意轻易动它。攻击者很清楚这一点。他们顶着 ClaudeBot 的名字进入一是在扫描阶段降低被管理员注意的概率二是万一被拦截也可以随时切换 UA换一个身份继续探测。对防御方来说单纯拉黑一个 UA基本等于什么都没做。所以伪装的根本原因不是某个爬虫品牌被盯上而是“UA 身份 大厂品牌”组合成了当代日志过滤体系里的盲区。3. 一张表讲清楚真爬虫和伪装扫描怎么区分判断一个请求是不是真的 AI 爬虫永远不要只看 UA。下面这张表是我处理这类日志时常用的判断维度每个维度都只能算一个信号不能单独定罪。3.1 判断维度表判断维度真爬虫常见特征伪装扫描常见特征User-Agent与官方公布的 UA 一致版本号稳定UA 固定不变但请求内容和官方行为不匹配请求路径内容页、列表页、静态资源路径符合站点结构.env、.bak、.sql、.git/config、admin、备份文件请求方法绝大多数是 GET可能出现 POST 打向登录、上传或 API 接口来源 IP / ASN与官方公布的 IP 段或对应 ASN 匹配来自小型 VPS、IDC 随机段、住宅代理等反解 PTR有较规范 PTR 记录或解析到官方域名PTR 缺失或解析到普通 VPS 域名robots.txt首次抓取前通常先请求 robots.txt完全不理会 robots.txt直接打敏感路径请求节奏速率相对均匀时间分散分钟级上千条时间集中可能 24 小时不停404 占比正常爬虫 404 率通常不高大量请求不存在路径404 占比明显偏高TLS / HTTP 指纹官方爬虫客户端特征相对固定常见 curl、Python requests、Go 等工具指纹这张表的价值不在于让你对着日志逐项打勾而在于建立一种“组合判断”的直觉。单个信号出现可能是巧合多个信号同时出现就需要认真对待了。3.2 组合判断不要用单一信号定罪IP 是不是绝对可信也不是。攻击者可以用大量机器轮换来源甚至用代理池所以不能因为“这个 IP 不在官方列表里”就立刻断定它在扫描也不能因为“这个 IP 看起来像官方段”就完全放心。更稳妥的做法是打分式判断。我一般会先看最近一小时 access log 里出现次数最多的 UA再按路径复杂度排序。路径越像字典枚举、404 占比越高、POST 比例越高就越值得怀疑。一个正经爬虫的 404 率通常不会高到哪里去更不会盯着 .env 和 wp-login.php 反复试探。另外官方信息要查但要用保守的方式参考。比如 Anthropic 是否公开了 ClaudeBot 的完整 IP 段公开到什么粒度更新频率如何都要以官方最新文档为准。如果你在某个技术博客里看到一个“ClaudeBot 完整 IP 列表”它可能已经过时甚至本身就是别人编的。实操建议把判断维度做成一个脚本每天扫描一遍 access log输出“高嫌疑访问”清单。刚开始可以只输出不拦截先跑一周看看误报率再决定要不要自动处理。4. 确认异常后按这个顺序处理更稳确认日志里的“ClaudeBot”是伪装扫描后正确的反应不是骂两句然后封掉 Anthropic 的整个网段而是按顺序做几件事。4.1 留证先拷贝日志再谈封禁第一条原则先留证据再动手。因为后续如果要排查影响范围、要看请求是否已经打到真实漏洞上都要回到原始日志。具体做法把 access log 里包含可疑 UA 或可疑 IP 的行单独导出成文件保留足够长的时间窗口比如至少 72 小时记录重要时间点、请求路径、方法、状态码、响应字节数确认日志已经包含完整 UA 字段如果网站前面还有一层代理X-Forwarded-For 也要留否则看到的全是代理 IP没法溯源。先用一条 shell 命令做初筛从已保留的日志里筛选“爬虫 UA 敏感路径”的请求并按来源 IP 统计zgrep -h ClaudeBot /var/log/nginx/access.log* \ | grep -E wp-login\.php|\.env|\.git/config|adminer\.php|\.sql|\.bak \ | awk {print $1} | sort | uniq -c | sort -rn | head -20这只是最粗糙的初筛但它能快速告诉你真正异常的来源是几个 IP还是散成一大片。如果来源集中在少数几个 IP处理起来很简单如果来源分散说明对方可能有代理池这时候单纯封 IP 意义不大要转向路径层面的统一防护。4.2 封禁与限速从 IP 和路径两个维度一起下手处理扫描流量我建议遵循一个顺序先拦明显恶意的高频 IP再对敏感路径做统一访问控制最后再决定要不要限速。第一层系统层或防火墙层直接拒绝确认恶意的高频 IP。这一步最好用 fail2ban 或防火墙规则自动化而不是手动一条条加。第二层无论什么 UA敏感路径都不能直接裸奔。.env、.git/config、备份文件、数据库导出文件这类路径本来就不该允许匿名访问。即使没有爬虫捣乱也建议在 Web 服务层面统一挡住。Nginx 里可以这样处理这类路径# 对明显敏感路径做统一访问控制不管 UA 是什么 location ~* \.(env|sql|bak|zip|tar)(\?.*)?$ { deny all; return 403; } # 对声明为爬虫的请求做限速避免异常流量拖垮站点 limit_req_zone $binary_remote_addr zonebot_limit:10m rate5r/s; server { location / { limit_req zonebot_limit burst20 nodelay; } }这里要特别提醒不要把限速和封禁混为一谈。限速是为了控制影响封禁是为了消除持续探测。对于伪装扫描如果对方只有几个固定 IP封禁更直接如果对方有轮换 IP限速加敏感路径阻断比单纯封禁更有效。4.3 用 fail2ban 做自动化拦截示例如果日志格式比较规整可以用 fail2ban 自动完成“识别异常行为 → 封禁来源 IP”的流程。下面是一个常见写法用来匹配“爬虫 UA 命中敏感路径”的请求# /etc/fail2ban/filter.d/nginx-scan-spoof.conf [Definition] failregex ^HOST .* (?:GET|POST) .*(?:\.env|\.git/config|wp-login\.php|adminer\.php).*(?:ClaudeBot|GPTBot) ignoreregex # /etc/fail2ban/jail.d/nginx-scan-spoof.local [nginx-scan-spoof] enabled true port http,https filter nginx-scan-spoof logpath /var/log/nginx/access.log maxretry 5 findtime 60 bantime 3600含义是在 60 秒窗口内如果某个 IP 出现 5 条匹配“爬虫 UA 命中敏感路径”的日志就把这个 IP 封禁 1 小时。注意fail2ban 的正则高度依赖 Nginx 日志格式不能拿这套配置直接套生产环境。正确做法是先下载匹配的日志样本用 fail2ban-regex 工具测一遍确认能命中再启用。启动后也要观察一两天防止误伤。5. 比拦截更重要的是把日志和监控补起来很多站点在处理完这一波扫描之后就当事情结束了。但从长期看真正值得投入的不是这一次封禁而是“下次再出现时能不能第一时间发现”。5.1 日志至少保留哪些字段如果要识别“伪装成 AI 爬虫”的扫描日志只记录 IP、时间、方法和 URL 是不够的。建议至少保留以下字段来源 IP最好同时记录直连 IP 和 X-Forwarded-For完整 User-Agent不要截断因为你要判断它是不是被伪装过的请求方法和完整路径包含查询参数否则漏掉很多有效信息状态码和响应字节数用来计算 404 占比请求耗时用于识别异常的高负载请求尽可能记录 TLS 版本和加密套件在 UA 完全不可信时TLS 指纹能提供额外判断线索如果日志里能记录 Header Referer 和 Content-Type对分析 POST 类扫描也很有帮助。这些字段不是每一条都有用但等到需要的时候缺一个都会让排查变得很难受。5.2 告警规则从这三条开始不用一上来就上复杂 SIEM先用简单规则跑起来。最容易见效的告警规则有三条高 404 占比加爬虫 UA某个 UA 在 10 分钟内产生大量请求且 404 占比超过 60%先标记为嫌疑对象敏感路径命中任何 UA 访问 .env、.git/config、备份文件、数据库导出文件直接告警不做二次判断同 IP 频繁切换 UA一个来源 IP 在短时间内出现多种不同 UA且其中包含主流浏览器或爬虫标识说明自动化工具在反复变更身份需要观察。如果你已经有了 CDN 或云 WAF这些规则通常都能在控制台里配置不一定非要自己写脚本。真正要保证的是告警发出后有人看有明确的处理流程而不是告警邮件躺在邮箱里没人管。落地建议先用一个固定目录存放告警快照比如/var/log/security/bot-scan/每次触发规则就把相关日志行复制过去。这样不仅方便复盘也能为后续写更精准的规则积累样本。6. 这件小事背后是一个长期要适应的安全变化处理完“ClaudeBot 伪装扫描”这件事最值得记住的其实不是某条封禁命令而是一个正在发生的安全习惯转移。6.1 从信任 UA 转向信任行为过去运维判断“好机器人”和“坏机器人”很大程度上依赖身份标识UA 对不对、IP 在不在白名单、ASN 是不是官方网段。这套模式的问题在于身份是可声明的攻击者可以伪造 UA可以租用不同地区的服务器甚至可以伪造反解记录。更可靠的路径是转向行为判断请求什么路径用什么方法访问节奏如何失败率多高是否触发了业务核心资源。把这些行为特征组合起来形成基线。基线之外的流量先怀疑再确认而不是先放行。这个转变对普通站点来说并不容易因为行为分析往往需要历史日志和数据积累。但你可以从一个很小的起点开始每天花十分钟看一眼 access log 的异常请求每周分析一次高嫌疑流量每月更新一次防护规则。6.2 对僵尸扫描的实用边界也要承认伪装扫描只是 Web 攻击里最基础的一种形态。它不是一次就能彻底防住的威胁而是一种持续存在的背景噪声。如果你运营的是个人博客或小站点做到“敏感路径防护 异常 UA 告警 定期看日志”就足够了没有必要为一次扫描上全套商业安全产品如果你运营的是业务系统或中大型站点建议把这类请求交给 CDN/WAF 统一处理同时保证源站日志完整、权限收敛、敏感接口有独立鉴权无论站点大小都不要因为一次伪装扫描就去封杀所有 AI 爬虫。真正需要长期维护的能力是“能快速区分异常访问和正常抓取”的监控体系。这类扫描流量还有一个特点它会不断换皮。今天顶的是 ClaudeBot明天可能就是另一个新出现的 AI 爬虫品牌。如果你的防护只认几个固定 UA那这场猫鼠游戏你永远慢半拍。回到最初那个场景。看到 ClaudeBot 在你的日志里访问 wp-login.php真正该做的不是第一时间把 Anthropic 拉黑而是把这条日志当成一个信号你的访问日志和监控体系是否已经足以让你分辨“好爬虫”和“借壳扫描”如果答案是模糊的那么这次异常反而是一个机会。趁这个信号还热着把该补的日志字段补上把该拦的敏感路径拦住把三两条告警规则跑起来。下一次再有机器人顶着大厂名字进来时你就能少一点深夜的紧张多一点明确的判断。