开启代理工具后,爬虫的安全检查误把正常网站当成内网地址,排查记录
1747 字约 6 分钟
摘要本地爬虫开启 Clash 等代理工具的 Fake-IP 模式后,27 个大学教师主页全部被 SSRF 校验拒绝。本文介绍如何在不放松安全边界的前提下,处理透明代理与内网防护之间的冲突。
在 Auto Email Sender 的智能抓取模块中,有一条严格的安全要求:防范 SSRF(服务端请求伪造)。
抓取目标中有些链接是大模型从网页里推荐的,因此必须防止恶意网页把爬虫引到内网:比如探测用户的 127.0.0.1:8080、读取内网路由器配置,或扫描公司局域网中的 NAS。
为此,系统在每次发起 HTTP 请求前,都会先对域名做 DNS 解析,拒绝任何指向私有 IP(如 10.0.0.0/8、192.168.0.0/16、127.0.0.1)的请求。即使发生了 302 重定向,最终落地的 IP 也要重新检查。
这套逻辑本身是标准的。直到有一位同学报告了一个奇怪的问题:他在软件中输入了 27 个 985 高校的教师主页,任务一启动,控制台就出现了大量报错:
“请求被拒绝:URL 不允许指向本机、内网或不可解析地址。”
27 位正常的教授主页,一个字节都没能抓到,全部被安全检查拦截了。
什么是 SSRF 和私有保留网段?SSRF(Server-Side Request Forgery)是一种常见的安全漏洞。攻击者诱导服务端向内网地址发起请求,从而绕过防火墙探测内部资源。因此,成熟的网络库通常会拦截
10.0.0.0/8、172.16.0.0/12、192.168.0.0/16以及127.0.0.1等私有保留地址。
原因是 Clash 的 Fake-IP
在普通浏览器中打开这几个网址,都能快速加载,没有任何问题。
我在本地运行单元测试,用 Python 的 socket.getaddrinfo() 解析了出问题的大学域名。
输出的 IP 是 198.18.0.23。
这个 IP 段正好触发了安全规则。
原因是:用户电脑上开着代理软件(如 Clash / Mihomo),并且启用了“增强模式 / 系统代理”的 Fake-IP 功能。
通俗比喻:游乐园里的虚拟排队手环为什么代理软件会返回一个不存在的
198.18.x.x地址? 想象你去一个热门游乐园:
- 常规流程:你需要自己去问清楚项目是否开放、真实的位置在哪(向 DNS 服务器解析真实的公网 IP);
- Fake-IP 模式:入口的工作人员(代理核心)直接给你一个写着
023 号的手环(虚拟 IP),告诉你“不用管它在哪,拿着这个手环走专用通道,我会带你过去”。对游客来说,只要能玩到项目,手环编号无所谓;但对园区的安保(SSRF 防御)来说,它只认正规的门牌号。看到公网地图上查不到的编号,安保会认为这个人持有伪造证件,直接拦下。
什么是代理的 Fake-IP 模式?传统的代理转发需要先把域名交给本地 DNS 解析,然后连接真实的公网 IP。 在 Fake-IP 模式下,为了加快网络握手并防止 DNS 污染,代理程序会拦截所有 DNS 请求,并从 RFC 2544 规定的基准测试保留段
198.18.0.0/15中分配一个虚拟 IP 返回给操作系统。 应用程序拿这个虚拟 IP 发起 TCP 连接,流量被系统驱动透明地转交给代理核心,代理核心再根据原始域名去连接真实的服务器。
从操作系统的角度看,这只是代理软件的一种工作方式。但从安全模块的角度看,198.18.* 并不是合法的公网可路由地址,而且属于保留的私有段,因此会被拒绝。
直接放行的做法不可取
找到原因之后,最直接的改法是:“既然是代理导致的,那就把 198.18.0.0/15 加入白名单,或者检测到系统开了代理就直接关闭 SSRF 检查。”
这种做法很危险。
攻击者完全可以在网页中构造一个解析到 127.0.0.1 的域名。如果因为开了代理就无条件放行,恶意页面就能借助爬虫探测用户的本地服务,抓到的内网数据甚至可能被送给大模型,进一步泄露出去。
安全检查不能因此放松。
需要区分的是两种情况:
- 情况 A: 域名在公网上确实是合法的网站,只是在本地被代理映射成了 Fake-IP;
- 情况 B: 域名本身就指向私有网络或回环地址,属于恶意地址。
为此,我们重新设计了校验流程:
1. 发起校验 ──> 使用系统默认 DNS 解析 (得到 IP_1)
2. IP_1 为 127.0.0.1 / 192.168.* ──> 直接拒绝
3. IP_1 位于 198.18.* (疑似 Fake-IP 段) ──> 启动【可信公网 DNS 交叉复核】
└──> 通过独立的 223.5.5.5 / 119.29.29.29 直接查询公网权威 DNS (得到 IP_2)
4. 公网复核确认为合法公网 IP ──> 判定为正常的代理流量,放行
5. 公网复核仍为私网地址或解析失败 ──> 直接拒绝
6. 发生 302 重定向 ──> 对跳转后的地址完整重新执行第 1 到 5 步交叉复核的好处这个方案既不需要维护学校域名白名单,也不会在开启代理时放松安全要求。只有当本地 DNS 的结果带有代理特征时,才会通过独立的通道向公网确认域名的真实地址。
修复只做了一半
修改之后,我在本地写了单元测试,用那几个教师主页做了验证,校验全部通过,抓取也正常。
新版本发布不到两天,又有人报告了同样的问题:
“我用的就是最新版本,开着代理抓取,还是被内网拦截?”
我按照用户的操作流程逐步回放,才发现问题所在。
Auto Email Sender 的抓取流程有两个入口:
- 入口 1(个人主页): 直接抓取某位老师的个人主页;
- 入口 2(教师列表): 先抓取学院的列表页,再抓取分页,最后抓取每位老师的详情。
我上一次的修复,只在入口 1 的校验函数中启用了公网复核。 而用户最常用的入口 2 列表提取器,仍在使用旧的严格模式。
测试用例只覆盖了单人主页的抓取,所以测试全部通过,但主要的业务路径上仍有遗漏。
总结
这次排查不仅解决了 Fake-IP 与安全规则之间的冲突,也统一了整个系统的出站网络检查:
| 网络访问场景 | 旧版行为 | 修复后的行为 |
|---|---|---|
| 公网域名被代理映射为 Fake-IP | 误判为私网并拦截 | 经公网 DNS 复核确认后放行 |
| 直接输入私网 IP(如 192.168.1.1) | 拒绝访问 | 继续拒绝访问 |
| 公网域名跳转到内网地址 | 存在被绕过的风险 | 对重定向的每一跳重新校验并拦截 |
| 列表页、分页、正文、OCR 多个入口 | 规则不统一,各自为政 | 全部经过统一的安全检查 |
现在的桌面应用需要面对各种网络环境,包括 VPN、透明代理、TUN 虚拟网卡和自建 DNS 服务。
在编写爬虫或任何需要主动对外访问的系统时:
- 安全检查不能因为网络环境复杂而放松;
- 用外部权威源做交叉校验,是识别本地网络映射的可靠方法;
- 修复安全问题时,要梳理完整的业务链路,避免只修一个入口、漏掉其他入口。