大家好,欢迎来到 Crossin 的编程教室。
今天给大家分享我自己网站中一次用户异常行为的排查过程。
老读者里有人知道,我多年前搭建过一个编程教程网站(后来也推出了小程序版)。除了放置 Python 编程教程外,还做了一些在线写代码、提交作业和记录打卡的小功能。
这几年因为精力有限,网站没怎么宣传,平时主要是些老用户在使用,或者靠自然搜索进来的流量。
最近,服务器刚好又要到期续费了。我上后台看了眼,发现十几年前配置的老机型,如今续费价格性价比实在太低,不如直接重新买一台新机型,把数据迁移过去。
然而,就在我迁移服务器、顺便检查系统日志的时候,发现了一个令人匪夷所思的现象——
日志里记录了大量的给其他用户主页的“点赞”操作。
一、异常
我的第一反应是:不会吧,难道这个功能还有这么多忠实用户在天天使用?
但仔细一分析,不对劲:
1. 这些点赞行为全来自于匿名用户;
2. 除了“访问主页”和“点赞”这两个动作外,没有任何其他的操作记录。
显然这不像是真人用户的行为。
我的好奇心一下子被勾起来了,决定一查究竟。
整理了一下手头已知的线索:
1. 请求高度集中在“用户主页”和“点赞”这两个 URL 接口上;
2. 全都是未登录的匿名请求;
3. IP 地址极其不固定,查了几个归属地,全国各地都有,甚至还有国外的 IP;
4. 没有固定时间段;
5. 最让我震惊的是:我沿着日志一路往前追溯,发现这类请求竟然从 9 年前就已经开始了,一直持续至今!而且近两年频率明显更高了。
二、排查
一开始我做出了几种猜测:
1. 读者拿网站练手写爬虫?毕竟我之前还专门写过一个“靶子网站”供大家练习爬虫技术。如果是某个读者拿主站练手,倒也说得通。
2. 爱好黑客技术的“脚本小子”用工具扫漏洞?以前确实也发生过类似的事情。
但这两个猜想很快被否定了——谁家读者练手或者脚本小子扫漏洞,能坚持不懈地跑上 9 年啊?这显然不符合常理。
3. 那是有人恶意攻击?
这就更不可能了。持续性的攻击都是有成本的,谁会闲得无聊,连续 9 年花成本去“攻击”我这个偏公益性质的学习网站?
排除了这些选项后,只剩下一种可能:这是某种自动化机制在跑。
三、真相
幸好,当年在设计点赞功能时,我记录下了请求的 IP。
我开始随机挑选 IP 去查询归属地。一开始 IP 太分散没看出规律,但当我查到一个早年的 IP 时,它的反向解析记录成功引起了我的注意:
Spider!是搜索引擎的爬虫蜘蛛!
我瞬间全都明白了!原来这“攻击”了 9 年的罪魁祸首,竟然是搜索引擎的内容采集脚本!
真相大概是这样的:
1. 这些网页是公开的,用户页面和点赞不需要登录权限即可访问;
2. 一个用户的主页上,包含了给该用户点赞的链接,以及其他更多用户主页的链接;
3. 当爬虫蜘蛛沿着页面上的链接爬进“点赞 URL”时,服务器执行了点赞逻辑,导致页面上的点赞数和排行榜发生改变;
4. 搜索引擎发现页面内容“更新”了,于是再次派蜘蛛来抓取;
5. 死循环形成:蜘蛛抓取 -> 触发点赞 -> 内容变动 -> 页面更新 -> 再次抓取 ……
就这样,搜索引擎的蜘蛛在我的网站里陷入了一个长达 9 年的无尽循环。
为了验证这个设想,我去搜索引擎里搜了一些用户主页上的随机文本。这些文本平平无奇,本身不包含“编程”“Python”等任何关键字。但果不其然,我的网站页面高高地挂在搜索结果前列。
更有意思的是,连相关 AI 生成的结果里,也会莫名其妙联系到我的网站——看来这些被蜘蛛抓去的无意义页面,还顺便被拿去当成大模型的训练语料了。
(不过在我修正了这个问题之后,图中相关搜索和回答已经不会关联到了)
四、修复
看到这里,懂Web开发的读者可能要吐槽了:
“你一个点赞操作,为什么要设计成 GET 请求?而且还允许未登录操作?”
我回想了一下,当年写这段代码的时候,大概是想着方便大家在微信里直接转发 URL,“喊朋友来集赞”,所以才做成了这种无需登录、点击即赞的极简设计。当时记录点赞 IP,也只是为了做个简单的防刷限制,没想到却给搜索引擎蜘蛛留下了这么大一个口子。
发现问题后,我先试着更新了 robots.txt,试图禁止蜘蛛抓取点赞相关路径。然而观察了几天,发现收效甚微,已经陷入死循环的抓取依然存在。
既然现在网站早就没有了这种社交集赞的需求,干脆“彻底根治”:
1. 直接关闭匿名点赞权限,改为必须登录后才可以查看和操作;
2. 重构并更换了新的 URL 地址,把写操作规范化。
世界终于清静了。
五、总结
一次常规的服务器迁移,意外揭开了这段 9 年的“误会”。虽然没有造成严重的破坏,但回顾整件事,对于做 Web 开发和编程学习的朋友来说,依然有几个非常典型的经验教训值得吸取:
1. 遵守 HTTP 规范,GET 应是“幂等”的
GET 请求应该只用于获取数据(Read),会产生数据变更的操作(Write/Update)应使用 POST、PUT 或 DELETE 请求。如果这样设计,爬虫可能不会触发“点赞”和页面更新。
2. 不要低估搜索引擎蜘蛛的“执着”
爬虫的逻辑非常简单且机械:只要 HTML 里有 <a href="..."> 标签,它就会顺着爬过去。如果你的 URL 设计不规范,或者包含了无限循环的逻辑链条,蜘蛛就会陷入其中,变成一种无意的“软 DDoS 攻击”,白白消耗服务器资源。
3. robots.txt 是君子协定,不是安全防火墙
robots.txt 只能起到引导作用,并不是强制约束。一方面,有些爬虫可能会忽略它;另一方面,对于已经建立索引、甚至形成死循环的历史 URL,仅仅依靠 robots.txt 很难立刻见效。涉及权限和逻辑的安全边界,必须在后端代码层面做好防护。
4. 警惕“技术债”,定期审查日志
很多年前为了“图方便”或“赶进度”写的临时代码,往往会成为日后的隐患。即便是一个看似不起眼的小功能,如果缺乏身份校验与频次限制,在长期运行过程中,也会产生意想不到的副作用。
