蜘蛛爬虫分析中的反向 DNS 验证方法。
通过提取真实客户端 IP、反向 DNS 查询 PTR 记录并正向回查确认域名解析回原 IP,验证自称 Googlebot、Bingbot 等爬虫请求的真伪,避免仅依赖可伪造的 User-Agent,无 PTR 记录不能直接判定为恶意。
学完这篇,你能用「反向 DNS + 正向回查」两步法,把日志里那些自称 Googlebot、Bingbot 的请求分出真假,而不是只看 User-Agent 被随便骗。
第一步:拿到来访者的真实 IP
这一步要做的,是把日志里的客户端 IP 提取出来,作为后面所有验证的输入。
如果你用 Nginx,默认 access.log 第一列就是 IP,直接 awk 取:
awk '{print $1}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -20
如果你在 Python 里处理,用 Flask 的 request.remote_addr、Django 的 request.META['REMOTE_ADDR']。
注意:不要用
X-Forwarded-For的第一个 IP 做验证源,这个头是客户端可以自己伪造的。要取 TCP 连接层看到的对端地址;如果前面有自己可控的反向代理,也只取代理追加的那一段。
第二步:用 dig 做反向解析,拿到 PTR 记录
这一步把 IP 反查成域名,得到候选的「爬虫身份」。
dig -x 66.249.66.1 +short
dig -x 40.77.167.1 +short
# 输出:msnbot-40-77-167-1.search.msn.com.
dig -x 220.181.108.0 +short
# 输出:baiduspider-220-181-108-0.crawl.baidu.com.
习惯用 host 也行:host 66.249.66.1。
常见爬虫的 PTR 后缀对照:Googlebot 用 googlebot.com 或 google.com,Bingbot 用 search.msn.com,百度用 baidu.com,Yandex 用 yandex.com / yandex.ru / yandex.net,搜狗用 sogou.com。
注意:很多 IP 根本没有 PTR 记录,
dig会返回空。这不能直接判定是坏人——大量云主机、自建爬虫都没配 PTR。这一步只是筛选,不是判决。
第三步:正向回查,确认域名指向同一个 IP
这一步是整套方法的核心。因为 PTR 记录是由 IP 所有者自己设置的,攻击者完全可以给自己的 IP 配一个 crawl-x-x-x-x.googlebot.com 来骗你。所以必须把第二步拿到的域名再正向解析一次,看结果是否回到原 IP。
dig +short crawl-66-249-66-1.googlebot.com A
# 输出:66.249.66.1 ← 和原始 IP 一致,通过
Python 里可以这样写:
import socket
def verify(ip):
try:
host = socket.gethostbyaddr(ip)[0]
except socket.herror:
return False
try:
forward = socket.gethostbyname_ex(host)[2]
except socket.error:
return False
return ip in forward
gethostbyaddr 底层就是 PTR 查询,gethostbyname_ex 是正向 A 查询,两者都走系统解析器,行为和你手动 dig 一致。
第四步:叠加域名后缀白名单
正向回查通过后,还要检查域名后缀是否落在官方白名单里。两步同时满足才算真爬虫:
WHITELIST = ("googlebot.com", "google.com", "search.msn.com",
"baidu.com", "sogou.com", "yandex.com", "yandex.net", "yandex.ru")
def is_verified_bot(ip):
return verify(ip) and host.endswith(WHITELIST)
注意:
endswith判断要小心evil-googlebot.com这种域名。更稳的写法是把主机名按.拆开,比较最后两段(或三段)是否精确等于白名单项,而不是做字符串包含判断。
第五步:加缓存和超时,别把 DNS 打成瓶颈
线上每条请求都做两次 DNS 查询,量一大就会把解析器拖慢,甚至被上游限流。
实践里做三件事:一是对结果做缓存,用 functools.lru_cache 或者 Redis,TTL 设 10~30 分钟(Google 官方也建议不要过度频繁查询);二是给解析设超时,Python 的 socket.setdefaulttimeout(2),超时就按「未验证」处理;三是把验证结果写进日志字段,方便后面按 is_verified_bot 做统计和规则调整。
注意:没通过验证 ≠ 一定是恶意流量。许多小众搜索引擎、监控探针、RSS 阅读器都没有 PTR。建议对未验证的爬虫按请求频率、是否遵守 robots.txt、抓取路径分布做二次判断,而不是直接封 IP。
小结
- 只信 IP,不信 User-Agent;IP 要取 TCP 层对端地址。
- 反向 DNS(PTR)负责「找出候选身份」,正向 DNS 负责「验证身份」,两步缺一不可。
- 正向回查的 IP 必须和原始 IP 完全一致,域名后缀必须精确匹配官方白名单。
- 结果要缓存、要设超时,避免 DNS 成为性能瓶颈。
- 未通过验证只代表「无法确认」,不等于恶意,最终封禁策略要结合行为特征。
原文链接:https://www.gj0.com/thread-1816.html
转载请注明出处并保留本声明;内容仅代表作者观点,与本站立场无关。若本文涉嫌侵权,请联系本站处理。