九月那次入侵之后,我最想知道的一件事,主机面板给不了答案:爬虫还会不会回来,它们回来时被喂了什么。面板里的访问日志要点好几层才能翻到,脚本读不到,Search Console 又得等两天,最后只给一个按周汇总的模糊形状。
于是我让网站自己记日志。大约 120 行 PHP:如果 user agent 命中已知爬虫,就在请求结束时追加一行,记下时间、爬虫名、实际返回的状态码、路径和 IP。真人访问永远不写入。
![]()
第一天的输出,从第一分钟开始,完整长这样:
- 15:51:01 bingbot 200 /calculators/pace-calculator 40.77.167.123
- 15:51:34 bingbot 404 /stimulated/a0d3o2b2o25378994 40.77.167.123
- 15:51:36 bingbot 404 /harshly/p0o9s1i9t9i3o7n38906 40.77.167.123
- 15:51:38 bingbot 404 /disservice/u1n6g2u8e5s4670872 40.77.167.123
- 15:51:40 bingbot 404 /dictation/g0o6g3g2l3e3e1y3e0264 40.77.167.123
- 15:51:41 bingbot 404 /coadjust/v1i4m1i5n4a2r1i8a6529 40.77.167.123
- 15:51:48 bingbot 404 /selfapproving/p1r3e2l1e9c2t1e3d9648 40.77.167.123
到当天结束,26 次爬虫请求里有 24 次打向了三周前才被凭空造出来的 URL。
那些路径不是随机垃圾
它们带着恶意软件生成时的精确形状:一个词典词,一个斜杠,第二个词把数字塞进字母之间。在网站被清理之前的六天里,它给每一个来要页面的爬虫递上大约 291 个这样的新地址。恶意软件几周前就没了,它排下的队还在。
这些 URL 当时全部返回 404。说它们不存在,这没错。但 404 的意思是"现在这儿没有",爬虫会把它当成过阵子再回来看看的理由。这就是它们三周后还在啃一份旧清单的原因。
410 的意思是"没了,别再问"。Google 和 Bing 丢掉一个 410 的速度都比 404 快,而这个差别恰好就是我要的行为。
这种规则的风险很明显:匹配太宽,就会把真实页面也判成 410。所以我先把形状写出来,在它靠近网站之前先量一遍:
- 路径按斜杠切分后必须正好两段
- 第二段不能含连字符(我们的 slug 是带连字符的)
- 第二段长度不能小于 10
- 第二段里数字至少 4 个、字母至少 4 个
结果:9 个已知垃圾路径全部命中,6240 个真实 URL 一个都没误伤。
规则放在哪一步,决定它会不会误杀
还有一道保险,也是我赶时间时最容易做错的地方。这条规则不在路由开头跑,而是在末尾、404 处理器里面跑——只有请求把真实路由全试完、什么都没匹配上,才会走到那里。
这个顺序不是装饰。我的站上有一条 /s/{code} 短链路由:两段、无连字符、字母加数字,正好符合那个形状。规则放前面,用户分享出去的每一条短链都会变成 410 Gone。放最后,活着的路由永远不会被它抓到,因为活路由根本走不到 404 处理器。
事后在线上验证:
- /accidence/d0e3p2o6s2i8t6a6r8y548 → 410(伪装者形状)
- /no-such-page → 404(普通拼写错误)
- /s/a1b2c3d4e5 → 302(短链,照常工作)
- /tools/json-formatter → 200
日志第一天就骗了我一次
有一行写着 googlebot 200 /。我高兴了大约十秒,直到看见 IP:39.34.131.166——我自己的网络。是我,那天下午用伪造的 user agent 做的测试。日志只是如实记下了它被告知的东西,而 user agent 从来就只是一个谁都能敲进去的声明。
所以日志现在会拿这个声明去比对爬虫自己公布的地址列表——Google 的 googlebot.json 和 special-crawlers.json,Bing 的 bingbot.json,缓存一天——并同时报告两个数字:
- bingbot 25 次命中(25 次已验证,0 次未验证)
- googlebot 1 次命中(0 次已验证,1 次未验证)
而那个"Googlebot 没来"的告警,现在只统计已验证的访问,因为一个谁都能在 user agent 里敲上 Googlebot 就能让它闭嘴的告警,不算告警。
如果你也在做这类检查:爬虫拿到的状态码,才是它对你网站的判断,所以要记实际返回了什么,而不是请求了什么。如果你最终需要永久退役一批 URL,在 .htaccess 里做比在应用代码里更省事——前提是你已经拿真实 URL 量过那个模式。
清理三周后,我的大部分抓取预算仍然花在攻击者的想象上。我之所以知道这一点,只是因为网站终于开始把事情记下来了。
特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.