午前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 = 3とbantime = 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リストを眺めるたびに安心する — サーバーが自分で自分を守ってくれているのだ。

