使用 fail2ban 透過反向解析動態阻擋偽裝成 Googlebot 的惡意 IP

6 min

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

你好,我是無能。
上次
調查自稱來自 Google bot 的請求 IP,包含惡意利用的情況 - SOULMINIGRIG

在這裡確認了偽裝成 Google 發送請求的 IP 群組確實存在不少。
但要如何封鎖這些 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 的情況下,若執行時收到失敗的狀態碼,就會被視為 ban 的對象處理。
也就是說,透過傳入 IP 位址作為參數並接收其執行時的狀態碼,就能判定是要 Ban 還是要跳過。

#!/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 被誤 Ban。

# 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)

但是,在這種情況下,每次有來自 Googlebot 的請求時都會進行 PTR 記錄查詢,因此最好採用類似偽快取的方式,在查詢之前對已經是 ALLOW 的 IP 直接予以許可,而不進行查詢。

Related Posts