悪質なbotのアクセスをNginxでバッサリ切り捨てる

# 前書き

悪質なbotはスリープをかけず巡回したり、ありもしないリンクを踏みに来たりと、サービスを運営するうえで厄介な代物です。
通常よりサーバの負荷が高いなと思ってログを解析するとbotだった・・・ということが少なくありません。

別に巡回してほしいわけでもないし、アクセスを容認する意味もないのでブロックできるとうれしいよねという話をしていたところ、同僚が[Nginx Ultimate Bad Bot Blocker](https://github.com/mitchellkrogza/nginx-ultimate-bad-bot-blocker)(以下、NginxUB3と表記します)というものを見つけてきてくれたので早速導入してみました。

# 結論

- NginxUB3自体はNginxの設定ファイルを駆使して、UA / リファラ / IPアドレスの条件によるアクセス遮断を行う仕組み
    - **mapディレクティブを使った定義ファイルをcronで更新し続ける**
    - **許可したいbotは、UA / リファラ / IPアドレスを指定してホワイトリストをカスタマイズできる**
- アクセス遮断したログはHTTPステータス444で記録される
- いらないbotのアクセスだけを遮断してくれていてとても気分がいい
- ただし、AWSやGCPを使ってスクレイピングするようなお手製ツールは[Fail2Ban](https://github.com/fail2ban/fail2ban)などで別途対処が必要
- モジュールじゃないのでコンパイルしなくてよい。気軽に導入して合わなければ捨てる。

# 実績
## Good
- 200(requests/sec)という理不尽な要求を遮断してくれたおかげで余分なリソースを使わずに済んだ。
    - トータルではなく、ピークのアクセス数を下げるのが目的なので大成功 :tada:

## Bad
- http://search.goo.ne.jp 経由のアクセスをbotと判断して捨ててしまった :sob:
  - Kibanaでフィルタリングしながらウォッチしていると、必要な流入を捨てていないかはここでチェックする。

# 導入

- インストーラのダウンロード

```shell-session
$ sudo wget https://raw.githubusercontent.com/mitchellkrogza/nginx-ultimate-bad-bot-blocker/master/install-ngxblocker -O /usr/sbin/install-ngxblocker
$ sudo chmod +x /usr/sbin/install-ngxblocker
```

- インストーラ(という名のダウンローダ)の実行

```shell-session
$ cd /usr/sbin
$ sudo ./install-ngxblocker -x #xオプションなしでDRY RUN
```

- セットアップスクリプトの実行
    - vhostのserverブロックにNginxUB3の設定ファイルのincludeディレクティブを挿入する
    - **<font color=red>1つのvhostにserverブロックが複数ある場合、最後のserverブロックにしか挿入されないので要注意</font>**
    - デフォルトでは、Ubuntu版のNginxのパス(/etc/nginx/sites-available)が設定されているため、/etc/nginx/conf.dにvhostを置いている場合は -v /etc/nginx/conf.dを付ける
    - デフォルトでは、vhostの拡張子は**\*.vhost**を想定している
        - デフォルトの場合、/etc/nginx/conf.d/example.com.vhostのようにファイル名を変更する<font color=red>**※nginx.confのincludeディレクティブも忘れずに書き換えること**</font>
        - /etc/nginx/conf.d/example.com.confのままにしたい場合、-e confを付ける

```shell-session
$ sudo ./setup-ngxblocker -x -v /etc/nginx/conf.d -e conf #xオプションなしでDRY RUN
```

- Nginxの設定反映

```shell-session
$ sudo nginx -t
$ sudo nginx -s reload
```

- アップデータの設定

```shell-session
$ sudo echo "00 */8 * * * root /usr/sbin/update-ngxblocker" > nginx_ub3
$ sudo mv nginx_ub3 /etc/cron.d/
$ sudo chown root:root /etc/cron.d/nginx_ub3
```

- テスト
    - 確認事項1. Google, Yahoo, BingなどのbotのUAを指定してHTTPステータス200で応答すること
    - 確認事項2. 360SpiderなどのbotのUAを指定してHTTPステータス502で応答すること(アクセスログを確認して444が記録されていること)

```shell-session
$ curl -A "Mozilla/5.0 (Linux; Android 6.0.1; Nexus 5X Build/MMB29P) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.96 Mobile Safari/537.36 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)" http://yourdomain.com
$ curl -A "mozilla/5.0 (compatible; msie 9.0; windows nt 6.1; trident/5.0); 360spider(compatible; haosouspider; http://www.haosou.com/help/help_3_2.html)"  http://yourdomain.com
```

# 設定ファイルのメンテナンス

## 対象ファイル
    - メンテナンス時には以下のファイルを編集する。
    - /etc/nginx/conf.d/globalblacklist.confをいじってもアップデートのたびに上書きされる。

```
/etc/nginx/bots.d/whitelist-ips.conf
/etc/nginx/bots.d/whitelist-domains.conf
/etc/nginx/bots.d/blacklist-user-agents.conf
/etc/nginx/bots.d/blacklist-ips.conf
/etc/nginx/bots.d/bad-referrer-words.conf
/etc/nginx/bots.d/custom-bad-referrers.conf
```

## フラグの説明
- 0, 1: アクセスを許可
- 2: アクセスは許可、メモリ割り当てなど一部Nginxのふるまいを制限する
- 3: アクセス遮断

## 実践
- AhrefsBotを許可する場合
    - /etc/nginx/bots.d/blacklist-user-agents.confに以下を追加

```diff
diff --git a/nginx/bots.d/blacklist-user-agents.conf b/nginx/bots.d/blacklist-user-agents.conf
index cb63618..3d3315a 100644
--- a/nginx/bots.d/blacklist-user-agents.conf
+++ b/nginx/bots.d/blacklist-user-agents.conf
@@ -49,6 +49,7 @@
        "~*\bsomeverygooduseragentname1\b"                      0;
        "~*\bsomeverygooduseragentname2\b"                      0;
        "~*\bsome\-very\-good\-useragentname2\b"        0;
+        "~*\bAhrefsBot\b"               0;
```

- GoogleBotを遮断する場合
    - /etc/nginx/bots.d/blacklist-user-agents.confに以下を追加

```diff
diff --git a/nginx/bots.d/blacklist-user-agents.conf b/nginx/bots.d/blacklist-user-agents.conf
index cb63618..3d3315a 100644
--- a/nginx/bots.d/blacklist-user-agents.conf
+++ b/nginx/bots.d/blacklist-user-agents.conf
@@ -57,4 +58,5 @@
        "~*\bsomeverybaduseragentname1\b"                       3;
        "~*\bsomeverybaduseragentname2\b"                       3;
        "~*\bsome\-very\-bad\-useragentname2\b"         3;
+       "~*\bGooglebot\b" 3;
```

- 補足
    - mapディレクティブは一致したタイミングで処理を打ち切るため、優先度が高いもの上に、低いものを下に書く

# 最後に
NginxUB3で一定数弾いたIPアドレスはFail2Banに登録するというアドオンもあったりするので、気軽に導入できる割に有用な仕組みです。
途中、書きましたが、合わなければ設定を戻せばいいだけなので、気軽に試してもらえると、うんざりするbotから解放される道が見えてくると思います。

うつらうつら書いた記事ですが、意外と読んでいただけたので、最後やっつけで書いた部分を書き直しました。