
real_ip_header CF-Connecting-IP 才能拿到真实客户端 IP。那天早上我照例 tail -f 看日志,发现一个段的所有 IP 都很“勤奋”。
103.236.84.x,十几个 IP,一天干了四万多请求。更骚的是 UA——同一个 IP,上午是 Googlebot,下午是 bingbot,晚上变 Baiduspider,一共轮换了 9 种蜘蛛 UA。
\n你说它是搜索引擎蜘蛛?哪家搜索引擎会用同一批机房 IP 精分成 9 个身份?
\n顺着日志往下翻更刺激:这批 IP 还在轮询爆破 /admin/login,UA 换成 Chrome 伪装真人。人家这是突击套利:偷内容、试密码,一鱼两吃,我直接被坑惨了。
无独有偶。另一个美国数据中心的 IP,1.8 万次请求全打在验证码接口上,UA 稳定自称 Googlebot。Google 的蜘蛛会帮你压测验证码接口吗?别赌运气,直接验证。
\n说人话:日志就是案发现场,第一步是拉嫌疑人名单。
\nnginx 日志默认第一个字段就是 IP(前提是配好了 real_ip,第五节讲)。一行命令把所有自称 Googlebot 的 IP 按频次排出来:
\ngrep -i "Googlebot" /var/log/nginx/access.log \\\n | awk '{print $1}' \\\n | sort | uniq -c | sort -rn | head -30\n跑完你会看到类似输出:
\n 18234 104.28.x.x # 自称Googlebot,全打验证码接口\n 9120 103.236.84.11 # 9种UA轮换的惯犯\n 640 66.249.66.1 # 真蜘蛛,访问节奏像人\n频次高就是假蜘蛛吗?不一定。真蜘蛛更新抓取时也会冲量,所以频次只是嫌疑,不是罪证。定性得靠下一步:验 DNS。
\n为什么 DNS 能验明正身?因为 PTR 记录和域名的正向解析,伪造成本极高,且握在官方基础设施手里。
\n反向解析:把 IP 解析回域名。真 Googlebot 的 IP 一定反解到 *.googlebot.com 或 *.google.com,这是 Google 自己维护的,李鬼碰不到。
正向回查:拿到反解域名后,再把它正向解析回 IP,两边对得上才算数。只做反解不做回查是个硬伤——理论上 PTR 是可以被动的,回查才闭环。
\n直接上我一直在用的 verify_bot.py:
\n#!/usr/bin/env python3\n# -*- coding: utf-8 -*-\n"""\nverify_bot.py —— 验证自称 Googlebot/Bingbot 的 IP 是不是李鬼\n原理:反向解析 IP -> 拿到域名 -> 正向解析域名 -> 比对 IP 是否一致\n用法:python3 verify_bot.py 66.249.66.1\n"""\nimport socket\nimport sys\nimport re\n\n# 官方允许的域名后缀,不在白名单里的直接判死刑\nALLOWED_PATTERNS = [\n r'\\.googlebot\\.com$', # Google\n r'\\.google\\.com$', # Google\n r'\\.crawl\\.baidu\\.com$', # 百度\n r'\\.search\\.msn\\.com$', # 必应\n r'\\.crawl\\.sogou\\.com$', # 搜狗\n r'\\.yandex\\.com$', # Yandex\n]\n\ndef verify(ip: str) -> bool:\n # 第一步:反向解析,拿不到 PTR 记录的基本就是野蜘蛛\n try:\n host = socket.gethostbyaddr(ip)[0]\n except socket.herror:\n print(f'[FAKE] {ip} 没有 PTR 记录,真蜘蛛不会这么寒酸')\n return False\n\n # 第二步:反解出的域名必须命中官方白名单\n if not any(re.search(p, host) for p in ALLOWED_PATTERNS):\n print(f'[FAKE] {ip} 反解到 {host},不在官方域名白名单')\n return False\n\n # 第三步:正向回查,把域名再解析回 IP,对不上就是 DNS 欺骗\n try:\n addrs = socket.gethostbyname_ex(host)[2]\n except socket.gaierror:\n print(f'[FAKE] {host} 正向解析失败')\n return False\n\n if ip in addrs:\n print(f'[OK] {ip} <-> {host} 双向一致,真蜘蛛')\n return True\n print(f'[FAKE] {ip} 反解到 {host},但正向指向 {addrs},对不上')\n return False\n\nif __name__ == '__main__':\n if len(sys.argv) < 2:\n sys.exit('用法: python3 verify_bot.py <ip> [ip2 ip3 ...]')\n for target in sys.argv[1:]:\n verify(target)\n拿真蜘蛛和嫌疑人各验一遍:
\n$ python3 verify_bot.py 66.249.66.1 104.28.221.55\n[OK] 66.249.66.1 <-> crawl-66-249-66-1.googlebot.com 双向一致,真蜘蛛\n[FAKE] 104.28.221.55 反解到 xxx.hostinger.com,不在官方域名白名单\n一秒定性。103.236.84.x 那批更惨,连 PTR 记录都没有,机房 IP 光着膀子就来了。
\n嫌疑人几百个的时候,手工一个个验?验到第二天你就知道什么叫崩溃。
\n写成循环,FAKE 的直接进黑名单:
\n#!/bin/bash\n# 批量验证可疑 IP,FAKE 的直接进封禁列表\nSUSPECTS=$(grep -iE "Googlebot|bingbot|Baiduspider" /var/log/nginx/access.log \\\n | awk '{print $1}' | sort -u)\n\nfor ip in $SUSPECTS; do\n result=$(python3 verify_bot.py "$ip")\n if echo "$result" | grep -q "FAKE"; then\n echo "deny ${ip%.*}.0/24;" >> /etc/nginx/blocklist.conf\n echo "[BLOCKED] ${ip%.*}.0/24"\n fi\ndone\n\n# 先 nginx -t 测语法再 reload,别直接 reload 翻车\nnginx -t && nginx -s reload\n注意脚本里我封的是 /24 段。为什么?103.236.84.11 今天被封,明天来个 103.236.84.37,你一个一个封要封到猴年马月。
\n这是我踩过最大的坑。
\n站点套了 Cloudflare 之后,日志里的 IP 全变成 CF 节点的 IP。怎么判断中招没有?看日志,如果 99% 的请求 IP 都来自几个固定段,那就是了。
\n照着这种日志去封,封的全是 Cloudflare 自己——等于把自己的 CDN 接盘封了,网站直接 502。
\nnginx 配置直接抄:
\n# 从 Cloudflare 回源头拿真实客户端 IP,不然日志里全是 CF 节点 IP\n# CF 官方段:https://www.cloudflare.com/ips/ 定期同步,别抄一年前的\nset_real_ip_from 173.245.48.0/20;\nset_real_ip_from 103.21.244.0/22;\nset_real_ip_from 103.22.200.0/22;\nset_real_ip_from 103.31.4.0/22;\nset_real_ip_from 104.16.0.0/13;\nset_real_ip_from 104.24.0.0/14;\nset_real_ip_from 108.162.192.0/18;\nset_real_ip_from 131.0.72.0/22;\nset_real_ip_from 141.101.64.0/18;\nset_real_ip_from 162.158.0.0/15;\nset_real_ip_from 172.64.0.0/13;\nset_real_ip_from 188.114.96.0/20;\nset_real_ip_from 190.93.240.0/20;\nset_real_ip_from 197.234.240.0/22;\nset_real_ip_from 198.41.128.0/17;\n\n# 真实客户端 IP 在这个头里\nreal_ip_header CF-Connecting-IP;\n\n# 顺手把惯犯的段拉黑(blocklist.conf 由第四节脚本生成)\n# include /etc/nginx/blocklist.conf;\n配完之后 $remote_addr 就是访客真实 IP,第二节的抓取和第三节的验证才全部成立。
Q1:robots.txt 能挡住假蜘蛛吗?
\n不能。robots.txt 是君子协定,人家连 UA 都是偷的,你指望它守规矩?它爆破你后台的时候想过 robots.txt 吗。
\nQ2:频率限制能不能替代 DNS 验证?
\n能缓解,不能根治。真蜘蛛高峰期也会触发限频,误伤 Googlebot 导致收录掉了,你哭都来不及。DNS 验证后精准封禁才是正解。
\nQ3:封假蜘蛛会影响 SEO 吗?
\n不会,前提是先验证再封。真蜘蛛 IP 全在官方段且双向解析一致,这套流程永远不会误伤它们。
\n最后一个习惯安利给你:封禁前后各导出一份日志摘要(按 UA + IP 段聚合),丢进【文本对比】(/tools/text-diff/)跑一遍 diff,假蜘蛛流量归没归零、有没有误伤正常流量,一眼看穿。
评论列表 (0条)