Fail2banの設定:SSHをパスワードの総当たりから守る
Fail2banはサービスのログを監視し、繰り返される失敗したログイン試行を見つけて、攻撃元のIPアドレスをファイアウォール経由で一時的にブロックします。SSHを守るには、パッケージをインストールし、/etc/fail2ban/jail.local に [sshd] セクション(enabled = true、maxretry、findtime、bantime)を記述して、サービスを再起動します。状態は fail2ban-client status sshd で確認します。
Fail2banは、サービスのログを監視し、繰り返される失敗したログイン試行を見つけると、その試行元のIPアドレスを一定時間ブロックするデーモンです。SSHにとっては、パスワードの総当たりに対する最も簡単な防御策です。数回失敗すると、ボットはサーバーへのアクセスを諦めます。以下では、fail2banの設定をインストールから、BANの確認や典型的な問題の解決まで解説します。
SSHの鍵認証があるのに、なぜfail2banが必要なのか
ポート22を開けているサーバーは、起動から数分もすると、ボットからのログイン試行を受け始めます。実際に確認してみてください。
$ sudo journalctl -u ssh --since "1 hour ago" | grep -c "Failed password"
412
パスワード認証を無効にして鍵だけを使っていれば、アクセスを突破されることはほぼありません。それでもfail2banは役立ちます。ログのノイズを減らし、数千の接続による負荷を抑え、誤ってパスワード認証が有効のまま残った場合の影響を抑えられます。fail2banは鍵認証の代わりではなく、2つ目の防御層です。
fail2banの仕組み
fail2banは3つの部分から成ります。
- フィルター(filter):ログの中から、認証失敗の行を見つけて、そこからIPアドレスを取り出す正規表現の集まりです。フィルターは
/etc/fail2ban/filter.d/にあります。 - アクション(action):違反者に対して何をするかを決めます。iptables、nftables、ufw、firewalld にルールを追加します。アクションは
/etc/fail2ban/action.d/にあります。 - ジェイル(jail):フィルター、アクション、ログの取得元、しきい値を組み合わせたものです。たとえば
sshdジェイルはSSHのログを監視します。
1つのIPから findtime の間に maxretry 回一致があると、そのアドレスは bantime の間ブロックされます。期間が過ぎると、BANは自動的に解除されます。
fail2banのインストール
DebianやUbuntuでは次のとおりです。
sudo apt update
sudo apt install fail2ban
RHEL、Rocky、AlmaLinuxでは、パッケージはEPELリポジトリにあります。
sudo dnf install epel-release
sudo dnf install fail2ban
自動起動を有効にして、サービスの状態を確認します。
sudo systemctl enable --now fail2ban
sudo systemctl status fail2ban
DebianやUbuntuでは、SSH用のジェイルが /etc/fail2ban/jail.d/defaults-debian.conf を通じて既定で有効になっています。RHEL系では、インストール後に何も有効になっていないため、ジェイルを手動で有効にする必要があります。
設定ファイルの場所:jail.conf と jail.local
主要な設定ファイルは /etc/fail2ban/jail.conf ですが、直接編集してはいけません。パッケージを更新すると上書きされてしまうためです。独自の設定は /etc/fail2ban/jail.local か、/etc/fail2ban/jail.d/*.local の個別ファイルに書きます。fail2banは次の順に読み込み、後から読み込まれたものが前の設定を上書きします。
jail.confjail.d/*.confjail.localjail.d/*.local
jail.conf を丸ごと jail.local にコピーしないでください。古い既定値が固定されてしまいます。jail.local には変更する項目だけを書きます。
SSH用のfail2ban設定:最小限のjail.local
ファイルを作成します。
sudo nano /etc/fail2ban/jail.local
次の内容を追加します。
[DEFAULT]
# 決してBANしないアドレス(自分のIPなど)
ignoreip = 127.0.0.1/8 ::1 203.0.113.10
bantime = 1h
findtime = 10m
maxretry = 5
# ログの取得元:systemdのジャーナルまたはファイル
backend = systemd
[sshd]
enabled = true
port = ssh
maxretry = 3
サービスを再起動して、ジェイルが起動したことを確認します。
$ sudo systemctl restart fail2ban
$ sudo fail2ban-client status
Status
|- Number of jail: 1
`- Jail list: sshd
各パラメーターの意味
| パラメーター | 意味 | 例 |
|---|---|---|
enabled | ジェイルを有効にするかどうか | true |
port | 違反者をブロックするポート | ssh、2222、ssh,2222 |
maxretry | BANされるまでに許容する失敗の回数 | 3 |
findtime | 失敗を数える時間の枠 | 10m |
bantime | BANの期間。-1 は無期限 | 1h、1d |
ignoreip | BANしないアドレスやサブネット | 10.0.0.0/8 |
backend | ログの取得元 | systemd、auto |
logpath | ファイルを使う場合のログファイルのパス | /var/log/auth.log |
banaction | BANに使うファイアウォール | nftables-multiport、ufw |
時間は s、m、h、d、w の単位を付けて書けます。単位のない数値は秒として扱われます。
backend:systemdかファイルか
Debian 12やUbuntu 24.04では、rsyslogがインストールされていないと /var/log/auth.log が存在しないことがあります。SSHのログはsystemdのジャーナルにしか残りません。その場合は backend = systemd が必要です。そうしないと、ログファイルが見つからないというエラーでfail2banが起動しません。rsyslogがある場合は、ファイルを使う方法もあります。
[sshd]
enabled = true
backend = auto
logpath = /var/log/auth.log
RHEL系のシステムでは、対応するファイルは /var/log/secure です。
標準以外のポートのSSH
sshdが、たとえばポート2222で待ち受けている場合は、ジェイルにそのポートを指定してください。指定しないと、fail2banはポート22をブロックし、攻撃は2222で続いてしまいます。
[sshd]
enabled = true
port = 2222
違反者のすべてのポートを一度にブロックするには、banaction で iptables-allports または nftables-allports のアクションを指定します。
ファイアウォールの選び方:iptables、nftables、ufw、firewalld
Debianでは既定で banaction = nftables が使われます(古いバージョンではiptables)。RHELでは firewalld です。サーバーでufwを設定している場合は、BANがufwに表示されるようにすると管理しやすくなります。
[DEFAULT]
banaction = ufw
firewalldの場合は次のとおりです。
[DEFAULT]
banaction = firewallcmd-rich-rules
ルールが実際に追加されたかは、sudo nft list ruleset | grep f2b または sudo iptables -L -n | grep f2b で確認できます。fail2banは f2b- という接頭辞のチェーンを作成します。
動作の確認:fail2ban-client status
fail2banの主要な管理ツールは fail2ban-client です。特定のジェイルの状態は次のように確認します。
$ sudo fail2ban-client status sshd
Status for the jail: sshd
|- Filter
| |- Currently failed: 2
| |- Total failed: 147
| `- Journal matches: _SYSTEMD_UNIT=sshd.service + _COMM=sshd
`- Actions
|- Currently banned: 4
|- Total banned: 38
`- Banned IP list: 45.148.10.12 92.118.39.7 185.224.128.40 218.92.0.112
ここには、現在の時間枠内の失敗回数、BANされているIPの数、そしてそのアドレスが表示されます。実際に動作を確かめるには、別のマシン(ignoreip に含まれていないもの)から間違ったパスワードで数回ログインしてみてください。3回目の試行の後には接続できなくなるはずです。
fail2ban自身のログは /var/log/fail2ban.log にあります。
$ sudo tail -n 3 /var/log/fail2ban.log
2026-10-14 09:12:41,118 fail2ban.filter [812]: INFO [sshd] Found 218.92.0.112
2026-10-14 09:12:44,302 fail2ban.filter [812]: INFO [sshd] Found 218.92.0.112
2026-10-14 09:12:47,551 fail2ban.actions [812]: NOTICE [sshd] Ban 218.92.0.112
fail2banでIPのBANを解除する
自分自身や同僚をBANしてしまった場合は、サーバーのコンソール(ホスティングのパネルや別のIPからのSSH)から解除します。
sudo fail2ban-client set sshd unbanip 203.0.113.25
すべてのジェイルのBANをまとめて解除するには次のとおりです。
sudo fail2ban-client unban --all
フィルターが発動するのを待たずに、手動でアドレスをBANすることもできます。
sudo fail2ban-client set sshd banip 198.51.100.7
同じ問題を繰り返さないために、自分の固定IPやオフィスのサブネットを ignoreip に追加してください。
繰り返し違反するIPへの段階的なBAN
多くのボットは、BANが解除されるとすぐに戻ってきます。バージョン0.11以降のfail2banには、繰り返し違反するIPに対して期間を延ばす機能があります。
[DEFAULT]
bantime = 1h
bantime.increment = true
bantime.factor = 2
bantime.maxtime = 4w
同じIPが再びBANされるたびに、期間は前回より長くなりますが、4週間を超えることはありません。古いバージョンの代替策は、recidive ジェイルです。これはfail2banのログ自体を読み、何度も引っかかったアドレスを長期間ブロックします。
[recidive]
enabled = true
logpath = /var/log/fail2ban.log
bantime = 1w
findtime = 1d
maxretry = 5
フィルターの検証:fail2ban-regex
ジェイルは動いているのに誰もBANされない場合は、フィルターがログの行を実際に見つけているかを確認してください。ファイルのログの場合は次のとおりです。
sudo fail2ban-regex /var/log/auth.log /etc/fail2ban/filter.d/sshd.conf
systemdのジャーナルの場合は次のとおりです。
sudo fail2ban-regex systemd-journal sshd
出力の Lines: ... matched の行を確認してください。一致がゼロなら、フィルターがログの形式に合っていないか、ログの取得元が間違っています。再起動の前に、設定全体の構文を確認しておくと安心です。
sudo fail2ban-client -t
よくあるエラー
- サービスが起動しない:「Have not found any log file for sshd jail」:
/var/log/auth.logがありません。backend = systemdを設定するか、rsyslogをインストールしてください。 - BANは表示されるのに攻撃が続く:ポートの指定が違っているか(SSHのポートを変更した場合など)、より前にある許可ルールがファイアウォールのBANを上書きしています。
portの設定とnft list rulesetの出力を確認してください。 - 変更が反映されない:
jail.confを編集したのに、jail.localやjail.d/*.localに別の値が設定されています。実際に有効な値はsudo fail2ban-client get sshd maxretryで確認できます。 - 自分自身をBANしてしまった:コンソールからBANを解除し、IPを
ignoreipに追加してください。 - Dockerのあるサーバーでfail2banが攻撃を検知しない:コンテナのポートは、INPUTをバイパスするDOCKERチェーンを通じて公開されます。こうしたサービスには、アクションで
chain = DOCKER-USERを指定します。
SSHをさらに守るための設定
fail2banは、/etc/ssh/sshd_config の基本的な設定と組み合わせると効果が高まります。
PasswordAuthentication no
PermitRootLogin no
MaxAuthTries 3
変更後は sudo sshd -t で設定を確認し、サービスを再起動します。新しい設定で鍵認証のログインが成功することを確認するまで、現在のセッションは閉じないでください。さらに、ファイアウォールで、SSHへのアクセスを必要なアドレスだけに制限することもできます。
まとめ
fail2banの設定は、いくつかの手順にまとめられます。パッケージをインストールし、[sshd] セクションを持つ jail.local を作成し、正しいbackendとポートを選び、maxretry、findtime、bantime を設定します。自分のアドレスは ignoreip に追加し、fail2ban-client status sshd で動作を確認します。鍵認証のみのログインと組み合わせれば、SSHをパスワードの総当たりから確実に守れます。サーバーの防御とfail2banは、Linuxコースで実践的に解説しています。
よくある質問
パスワード認証を無効にしていても、fail2banは必要ですか?
必須ではありませんが有用です。何千件もの無駄な試行をログから減らし、負荷を抑えます。また、誰かがパスワード認証を誤って再び有効にしてしまった場合の保険にもなります。
すべてのジェイルでBANされているIPをまとめて確認するにはどうすればよいですか?
sudo fail2ban-client banned を実行すると、ジェイルごとにBANされたアドレスの一覧が表示されます。1つのジェイルだけを確認するには fail2ban-client status sshd を使います。
サーバーを再起動しても、BANは保持されますか?
はい。fail2banはBANの情報をSQLiteのデータベース(/var/lib/fail2ban/fail2ban.sqlite3)に保存し、起動時に有効なブロックを復元します。ただし dbpurgeage によって、それより前に削除されている場合は除きます。
SSH以外のサービスもfail2banで守れますか?
はい。nginx、Apache、Postfix、Dovecotなどのフィルターが同梱されています。jail.local で対応するジェイルを有効にするだけで済みます。たとえば [nginx-http-auth] に enabled = true を設定します。
fail2banとファイアウォールのアクセス制限の違いは何ですか?
ファイアウォールはアドレスを静的に許可または拒否します。一方fail2banは、ログに不審な動きを残したアドレスを動的にBANします。両者を組み合わせて、信頼できるアドレスは許可リストに、それ以外はfail2banで管理するのが一般的です。