去年秋天,持扫我帮一家小电商查一起怪事:用户投诉说访问他们的持扫支付页面时,跳转到了一个长得几乎一模一样的持扫钓鱼站。域名没错,持扫HTTPS 证书也没报错。持扫问题出在 DNS 上——有人在中途把解析结果换成了恶意 IP。持扫这就是持扫典型的 DNS 劫持,而发现它,持扫靠的持扫就是扫描。
DNS 劫持不像漏洞利用那样留下一堆日志。持扫它更像邮局里有人偷偷改了你寄信的持扫地址,信还是持扫寄出去了,只是持扫收信人换了。扫描的持扫核心思路很简单:拿一组已知的、可信的持扫域名解析结果做基准,再去问不同网络位置、不同 DNS 服务器,看返回的 IP 是否一致。不一致的地方,就是疑点。
我常用的做法分三层。第一层,本地对比。用 dig 或 nslookup 分别向 8.8.8.8、1.1.1.1 和本地运营商 DNS 查询同一个域名。如果本地 DNS 返回的 IP 和公共 DNS 差得离谱,比如一个在美国,一个在从没听说过的东欧机房,那基本可以标记。第二层,多地探测。借助公开的 DNS 探测平台,从十几个国家同时解析,把结果聚合成地图。劫持往往有地域性,某些省份的运营商干这事不是新闻。第三层,被动监听。在网关抓 DNS 响应包,比对 TTL 和 IP 的异常变化。TTL 突然从 300 变成 30,或者 IP 落在已知恶意段里,警报就该响了。
说个具体案例。某次扫描一个教育类域名,公共 DNS 返回的是 Cloudflare 的 IP,但某省电信 DNS 返回了一个 123.xx.xx.xx 的地址。查 whois,注册人是一家做“网络优化”的公司。再查这个 IP 的历史解析记录,发现它同时托管着几十个博彩和色情站。这不是误伤,是典型的流量劫持——运营商把域名解析到自己的缓存服务器,插入广告或者直接导流。
扫描工具方面,dnsrecon 和 dnscat2 偏渗透测试,日常运维我更推荐 dnsdiag 或者自己写个 Python 脚本,用 dnspython 批量查询然后做 diff。关键是维护一份可信基线,比如每天凌晨从多个公共 DNS 拉一遍全量域名解析结果,存进数据库。第二天再拉,差异超过阈值的就人工看。这比事后救火强得多。
劫持的动机无非几种:广告注入、钓鱼、DDoS 反射、或者单纯是运营商缓存污染。扫描不能阻止劫持,但能让你在用户投诉之前就知道。我见过太多团队,直到支付接口被劫持到假站才反应过来。那时候损失已经发生了。
有个细节值得留意:DNSSEC 能防篡改,但部署率低得可怜。很多中小网站连 CAA 记录都没配。扫描的时候顺便检查 DNSSEC 链是否完整,比只盯着 IP 差异更有价值。毕竟,你没法保证每个递归服务器都老实。
最后说个反直觉的观察。有些“劫持”其实是 CDN 调度策略导致的 IP 差异,不是恶意。比如 Akamai 会根据用户子网返回不同边缘节点。扫描时得先排除这种正常调度,否则误报能把你淹了。判断依据是看返回的 IP 是否属于该 CDN 的官方段,以及 TTL 是否合理。恶意劫持通常 TTL 很短,因为攻击者要随时换 IP。
扫描这件事,做多了会有直觉。某个域名解析突然从三个 A 记录变成一个,或者 CNAME 链里多了一跳没见过的域名,心里就该咯噔一下。工具是辅助,真正管用的是对网络基线的那份熟悉。