Webサーバへの脆弱性スキャンをfail2banで弾く

この記事は自分用のメモで、技術的に新しい話は含んでいません。ごくたまにしかやらない設定は、書き残しておかないとすぐ記憶から消えてしまうので・・・。

2か月ほど前にささやかなWebサービスを公開しましたが、DNSに登録されるや否や、サービス利用の数百倍、数千倍の、脆弱性スキャンと思われるアクセスが来ました。

といってもサーバの能力からみたら全く問題ない範囲ですし、サーバにはクレデンシャル的なものは一切置いていないので、万一侵入されてもサーバを落とせば基本的には解決するはずです。

しかしながら、ひどいときには1日10万回を超えるアクセスがあり、さすがに鬱陶しくなってきたのでfail2banを導入しました。

fail2banはログファイルを監視し、同一のIPアドレスから、指定したパターン(主にはアクセス先のURL)のログが複数回連続したときに、当該IPアドレスからのアクセスをブロックするツールです。Ubuntuではaptでインストールできます。

指定するURLパターンは正規表現で指定できますが、2か月分のアクセスログの統計を取り、頻度の高いものを指定しました。頻度の高かったURLを以下に示します。(数字は2か月間でもっともアクセスが多かった1日の中での出現頻度)

  13100 /admin
  12315 /api
  11785 /config
   9097 /core
   4267 /:8181
   4196 /:8443
   4188 /:8008
   4182 /:8888
   4177 /:10000
   4174 /:9000
   4161 /:5601
   4161 /:5000
   4155 /:8880
   4139 /:8000
   4122 /:8080
    818 /backup
    344 /app
    276 /src
    218 /public
    203 /services

これらのURLパターンに限らず、ステータス404が短時間に連続した場合もbanすることにしました。

あと、特定のサーバの脆弱性を狙っているのか、HTTPリクエストではなくバイナリデータを突っ込んでくるアクセスもあり、これも問答無用でbanしました。

fail2banのフィルタ設定の例を以下に載せます。

[Definition]
failregex = ^ \- \S+ \[\] \"(GET|POST).*(\/admin\/|\/api|\/config|\/core|\.env|\.git).* HTTP\/.*\".*$
            ^ \- \S+ \[\] \"\\x.*\".*$
            ^ \- \S+ \[\] \"(GET|POST).*\/[^ ]* HTTP\/.*\" 404 .*$

ignoreregex =

Ubuntu 24.04のfail2banでは、このようなフィルタしたいURLパターンを/etc/fail2ban/filter.d/の下に置き、引っかかったアクセス元のIPアドレスへの対処方法(banする閾値、アクセス禁止する期間等)を/etc/fail2ban/jail.d/に置きます。
jailの設定では、以下のようにnginxのアクセスログを読みに行かせています。

[nginx-exploit-scanner]
enabled  = true
backend  = polling
filter   = nginx-exploit-scanner
port     = http,https
logpath  = /var/log/nginx/access.log
maxretry = 10
findtime = 600
bantime  = 172800

このとき、jailの設定ではbackend(監視対象)にpollingを指定する必要があります。Ubuntuではデフォルトのbackend設定がsystemdになっており、この設定を変えないとログファイルを読みに行ってくれません。(ここでちょっと嵌りました)

ちなみに今回、設定ファイルをChatGPTに書いてもらおうとしたら、どうもうまくいきませんでした。ChatGPTのコード生成は、正規表現をうまく書けてないことがたまにあります。

なお、fail2ban用のfilter定義に書かれた正規表現のテストは

$ fail2ban-regex [ログファイル] [フィルタ定義ファイルまたは正規表現]

で行うことができます。

コメント