使用 fail2ban 通过反向解析动态拦截伪装成 Googlebot 的恶意 IP

6 min

language: ja bn en es hi pt ru zh-cn zh-tw

你好,我是无能。
上次
调查自称来自 Google bot 的请求 IP(包括滥用情况) - SOULMINIGRIG

在这里,我确认了确实存在相当一部分伪装成 Google 发送请求的 IP 组。
但是如何拦截它们呢?也就是说,只要能在 fail2ban 侧检测到并运行指定的脚本即可,我在以下 issue 中找到了提示:
apache-fakegooglebot: whitelist · Issue #1318 · fail2ban/fail2ban · GitHub

简单来说,就是先大范围匹配 Google 的 Bot,然后通过指定的脚本进行 ignoreip 的判定。
这样应该可行。

jail.local

添加以下内容:


[fake-googlebot]
enabled = true
filter = fake-googlebot
port = http,https
logpath = /var/log/nginx/access.log
findtime = 1w
maxretry = 1
bantime = 99999w
ignorecommand = /usr/local/bin/check_googlebot.sh <ip>
action = pf[name=fake-googlebot]

在这种情况下,需要创建一个名为 fake-googlebot 的过滤器条件。
此外,还需要 ignorecommand 中设置的 Shell 脚本。

filter.d/fake-googlebot.conf

如下所示进行大范围匹配:

[Definition]
failregex = ^<HOST> - .*"(GET|POST|HEAD|PUT|DELETE|OPTIONS|PATCH) .*" \d+ \d+ ".*" ".*Googlebot.*"$
ignoreregex =

/usr/local/bin/check_googlebot.sh

ignorecommand 的情况下,如果执行时返回失败的状态码,则会被处理为封禁对象。
也就是说,通过将 IP 地址作为参数传递并接收执行时的状态码,就可以判定是进行封禁还是将其作为跳过对象。

#!/bin/sh
IP="$1"
LOG="/var/log/check_googlebot.log"
# 反向解析
HOST=$(getent hosts "$IP" | awk '{print $2}' | head -n1)
if [ -z "$HOST" ]; then
  echo "[$(date)] DENY $IP: no PTR" >> "$LOG"
  exit 1
fi
# 确认是否为 Google 系域名
case "$HOST" in
  *.googlebot.com|*.google.com)
    ;;
  *)
    echo "[$(date)] DENY $IP: invalid domain ($HOST)" >> "$LOG"
    exit 1
    ;;
esac
# 正向解析并确认是否与原 IP 一致
MATCH=1
getent hosts "$HOST" | awk '{print $1}' | while read -r RESOLVED; do
  if [ "$RESOLVED" = "$IP" ]; then
    MATCH=0
    break
  fi
done
if getent hosts "$HOST" | awk '{print $1}' | grep -Fxq "$IP"; then
  echo "[$(date)] ALLOW $IP: valid Googlebot ($HOST)" >> "$LOG"
  exit 0
else
  echo "[$(date)] DENY $IP: mismatch ($HOST)" >> "$LOG"
  exit 1
fi

没有使用 host 命令的原因是它不是一个通用命令。在 Debian 系系统中,它似乎包含在 bind-utils 中,但只要安装了 glibc,就可以通过 getent hosts 获取 PTR 记录。
[SOLVED] Host command / Newbie Corner / Arch Linux Forums

验证

尝试执行一下,确认 Google Bot 的 IP 返回值为 0

# sh /usr/local/bin/check_googlebot.sh 66.249.74.78
# echo $?
0

那么如果是不同的 IP 呢?试着输入我自己的服务器 IP。

# sh /usr/local/bin/check_googlebot.sh 163.44.113.145
# echo $?
1

判定似乎正常。

fail2ban

fail2ban 侧重启以应用此过滤器。

service fail2ban restart
fail2ban-client status 

通过以下命令确认最近的 IP 中没有误封 Google 的 IP。

# fail2ban-client status fake-googlebot
Status for the jail: fake-googlebot
|- Filter
|  |- Currently failed: 0
|  |- Total failed:     0
|  `- File list:        /var/log/nginx/access.log
`- Actions
   |- Currently banned: 0
   |- Total banned:     0
   `- Banned IP list:

虽然日志中还留有一些刚才指定自己服务器 IP 执行时的记录,但从日志上看,Google 的 bot 判定似乎是正常的。

# tail /var/log/check_googlebot.log 
[Sun Apr 19 01:58:18 JST 2026] ALLOW 66.249.74.65: valid Googlebot (crawl-66-249-74-65.googlebot.com)
[Sun Apr 19 01:58:18 JST 2026] ALLOW 66.249.74.78: valid Googlebot (crawl-66-249-74-78.googlebot.com)
[Sun Apr 19 01:58:18 JST 2026] ALLOW 66.249.74.64: valid Googlebot (crawl-66-249-74-64.googlebot.com)
[Sun Apr 19 01:58:18 JST 2026] ALLOW 66.249.74.64: valid Googlebot (crawl-66-249-74-64.googlebot.com)
[Sun Apr 19 01:58:19 JST 2026] ALLOW 66.249.74.64: valid Googlebot (crawl-66-249-74-64.googlebot.com)[Sun Apr 19 01:58:19 JST 2026] ALLOW 66.249.74.78: valid Googlebot (crawl-66-249-74-78.googlebot.com)
[Sun Apr 19 01:58:19 JST 2026] ALLOW 66.249.74.64: valid Googlebot (crawl-66-249-74-64.googlebot.com)
[Sun Apr 19 01:58:19 JST 2026] ALLOW 66.249.74.78: valid Googlebot (crawl-66-249-74-78.googlebot.com)
[Sun Apr 19 03:56:30 JST 2026] ALLOW 66.249.74.78: valid Googlebot (crawl-66-249-74-78.googlebot.com)
[Sun Apr 19 03:58:18 JST 2026] DENY 163.44.113.145: invalid domain (v163-44-113-145.v1i0.static.cnode.jp)

Related Posts