Fail2banでUbuntuサーバーをブルートフォース攻撃から守る設定方法

Ubuntu tutorial - IT technology blog
Ubuntu tutorial - IT technology blog

午前2時、SSHのログが炎上している

VPSを立ち上げて3日後、初めて/var/log/auth.logを開いたときのことを今でも覚えている。6時間で異なるIPアドレスから4,000回以上のSSHログイン試行があった。成功したものは一つもなかった。しかし、24時間365日サーバーを叩き続けているという事実を考えるだけで、眠れなくなる。

Fail2banは、どのサーバーでもSSHキーを設定した直後にインストールするツールだ。Ubuntu Server 22.04のVPSを20台以上扱ってきた今では、この手順はほぼ体が覚えている。この記事では遠回りせず、インストール・設定・テスト・よくあるトラブルの対処法を解説する。

Fail2banの仕組み

仕組みは思ったより単純だ。Fail2banはログファイル(auth.log、nginx/access.logなど)を監視し、一定時間内にログイン失敗が多すぎるIPアドレスを検出すると、自動的にiptables/nftablesのルールを追加してそのIPをブロックする。

3つの中心的な概念:

  • jail — 特定のサービス(SSH、Nginxなど)を監視するルールセット
  • filter — 「不審な」ログ行を識別するための正規表現パターン
  • action — 違反を検出したときに実行する処理(IPのban、メール送信など)

Fail2banには数十の一般的なサービス向けのフィルターが標準で付属している。ほとんどの場合、jailを有効にするだけで完了する。

UbuntuへのFail2banインストール

sudo apt update
sudo apt install fail2ban -y

インストール後、Fail2banは自動的に起動する。確認するには:

sudo systemctl status fail2ban

active (running)と表示されれば正常だ。表示されない場合は次を実行する:

sudo systemctl enable --now fail2ban

正しい設定方法 — 元のファイルは編集しない

Fail2banには2層の設定ファイルがある:

  • /etc/fail2ban/jail.conf — 元のファイル。パッケージ更新時に上書きされる
  • /etc/fail2ban/jail.local — ユーザーの設定ファイル。常に優先される

原則としてjail.confは絶対に編集しない。コピーからjail.localを作成する:

sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
sudo nano /etc/fail2ban/jail.local

[DEFAULT]セクションの設定

ここでの設定は、各jailで上書きされない限り、すべてのjailに適用される:

[DEFAULT]
# banしないIPアドレス/サブネットのリスト — 重要
ignoreip = 127.0.0.1/8 ::1 YOUR_HOME_IP

# banの継続時間(秒)。-1 = 永久ban
bantime = 3600

# 失敗回数をカウントする時間範囲(秒)
findtime = 600

# banするまでの最大失敗回数
maxretry = 5

# ログの読み取りバックエンド — systemdまたはauto
backend = systemd

YOUR_HOME_IPは自分の実際のIPアドレスに置き換えること。このステップを忘れて自分でサーバーから締め出されたことがある — 夜11時にコンソールアクセスもない状況は本当に最悪だった。

SSH jailの有効化

Ubuntu 22.04(systemd環境)でのjail.localのSSH jail設定は以下のとおりだ:

[sshd]
enabled = true
port = ssh
logpath = %(sshd_log)s
backend = %(sshd_backend)s
maxretry = 3
bantime = 86400

SSH用にmaxretry = 3bantime = 86400(24時間)を選んだ。SSHはあらゆるスキャナースクリプトの最大の標的であるため、デフォルトより厳しく設定している。

設定を反映するためにリロードする:

sudo systemctl reload fail2ban

jailの動作確認

# 実行中のjailリストを確認する
sudo fail2ban-client status

# sshdのjailの詳細を確認する
sudo fail2ban-client status sshd

最後のコマンドの出力には、現在banされているIPの数、合計ban数、具体的なIPリストが表示される:

Status for the jail: sshd
|- Filter
|  |- Currently failed:	2
|  |- Total failed:	47
|  `- Journal matches:  _SYSTEMD_UNIT=ssh.service + _COMM=sshd
`- Actions
   |- Currently banned:	3
   |- Total banned:	12
   `- Banned IP list:	203.0.113.42 198.51.100.17 192.0.2.88

実践:NginxとWordPressの保護

ブルートフォース攻撃はSSHだけから来るわけではない。Webサーバーを運用しているなら、WordPressのログインページやNginxも頻繁に攻撃対象になる — SSHより激しい場合もある。

Nginx用jail — スキャンと4xxフラッドのブロック

[nginx-http-auth]
enabled = true
port = http,https
logpath = /var/log/nginx/error.log

[nginx-botsearch]
enabled = true
port = http,https
logpath = /var/log/nginx/access.log
maxretry = 2

WordPress xmlrpc.php用カスタムjail

xmlrpc.phpは非常によく狙われる攻撃ポイントだ。XML-RPC multicallを使って認証情報をブルートフォースするのによく悪用される。専用フィルターを作成する:

sudo nano /etc/fail2ban/filter.d/wordpress-xmlrpc.conf
[Definition]
failregex = <HOST> .* "POST /xmlrpc.php
ignoreregex =

続いてjail.localにjailを追加する:

[wordpress-xmlrpc]
enabled = true
port = http,https
filter = wordpress-xmlrpc
logpath = /var/log/nginx/access.log
maxretry = 5
bantime = 86400

IPのunbanとデバッグ

よくある状況:別のマシンからSSHをテストしているときに、パスワードを3回間違えて自分自身がbanされてしまった。素早く対処する方法:

# 特定のIPをunbanする
sudo fail2ban-client set sshd unbanip 1.2.3.4

# フィルターがログに正しくマッチするかテストする
sudo fail2ban-regex /var/log/auth.log /etc/fail2ban/filter.d/sshd.conf

# fail2banのログを確認する
sudo tail -f /var/log/fail2ban.log

fail2ban-regexコマンドはカスタムフィルターを作成する際に特に重宝する — パターンに一致するログ行が何行あるかを正確に教えてくれるため、デバッグの時間を大幅に節約できる。

違反履歴に応じたbantime自動増加

繰り返し違反するIPにはより重いペナルティを与えるべきだ。Fail2banのbantime.incrementはまさにそれを実現する — 違反するたびにban時間が倍増する。[DEFAULT]セクションに追加する:

[DEFAULT]
bantime.increment = true
bantime.factor = 1
bantime.formula = ban.Time * (1<<(ban.Count if ban.Count<20 else 20)) * banFactor
bantime.multiplier = 2
bantime.maxtime = 604800  # 最大7日間

bantime = 3600(1時間)を基準にした場合:1回目は1時間ban、2回目は2時間ban、3回目は4時間ban…しつこく繰り返すIPは最終的に1週間ブロックされるまでエスカレートする。

リロード前の設定全体の確認

# 設定ファイルの構文チェック
sudo fail2ban-client --test

# エラーがなければリロードする
sudo systemctl reload fail2ban

# アクティブなjailを確認する
sudo fail2ban-client status

まとめ

Fail2banですべての問題が解決するわけではない。パスワードの代わりにSSHキーを使うことや、定期的なパッケージ更新の代わりにはならない。しかし、その役割においては非常に優秀だ:リソース消費が少なく、ボットスキャナーからのノイズのほとんどを自動処理し、手動での介入が不要。

15分のセットアップで、より安心して眠れるようになる。設定完了後は、cronで毎朝sudo fail2ban-client status sshdを実行して状況を把握している。日々増え続けるbanリストを眺めるたびに安心する — サーバーが自分で自分を守ってくれているのだ。

Share: