2026年5月24日

2026年5月24日

fail2ban で不正アクセスを自動ブロックする設定手順(SSH・Webログイン)

fail2ban は、ログに「ログイン失敗」などの記録が短時間に何度も出たIPアドレスを見つけ、ファイアウォールで一定時間ブロックするツールです。設定の中心は jail.local に「どのログを見て(フィルター)」「何回失敗したら(maxretry)」「どのくらいの期間内に(findtime)」「どれだけの間(bantime)」「どの方法で止めるか(banaction)」を書くことです。この記事では、SSH を対象にした基本設定から、Webサーバーのログを使ったログイン保護、誤って自分をブロックしたときの解除方法、動かないときの確認ポイントまでを説明します。

fail2ban でできること・できないこと

fail2ban は、パスワードの総当たりや、同じ相手から繰り返されるログイン試行を減らすのに向いています。ログに失敗が記録されるたびに数え、しきい値を超えた送信元IPを、iptables・nftables・firewalld・ufw などのルールで一時的に遮断します。

一方で、次のことはできません。

  • 多数のIPアドレスから少しずつ試す分散型の攻撃は、1つのIPあたりの回数が少ないため検知しにくい
  • 大量の通信でサーバーを埋める DDoS への対策にはならない
  • 弱いパスワードや、更新していないソフトウェアの脆弱性を補うものではない

SSH であれば、公開鍵認証を使いパスワードログインを無効にすることが基本の対策で、fail2ban はその上でログを静かにし、無駄な試行を減らす役割と考えると位置づけが分かりやすくなります。

インストールと最初の確認

Debian・Ubuntu では標準のリポジトリから、RHEL 系(AlmaLinux、Rocky Linux など)では EPEL リポジトリからインストールするのが一般的です。

# Debian / Ubuntu
sudo apt update
sudo apt install fail2ban

# RHEL系(EPEL を有効にしたうえで)
sudo dnf install fail2ban fail2ban-firewalld

sudo systemctl enable --now fail2ban
sudo systemctl status fail2ban

インストール直後に起動しない場合は、まず journalctl でエラーを確認します。ディストリビューションとパッケージの組み合わせによっては、初期状態のままでは起動に失敗する問題が報告されたこともあります。最新の状況は各ディストリビューションのバグ情報で確認してください(2026年10月現在)。多くはパッケージの更新か、後述する backend の設定で解消します。

sudo journalctl -u fail2ban -n 50 --no-pager

設定ファイルの置き方

設定の元になる /etc/fail2ban/jail.conf は、パッケージの更新で上書きされることがあるため直接編集しません。変更は /etc/fail2ban/jail.local、または /etc/fail2ban/jail.d/ 配下の .local ファイルに書きます。.local に書いた項目だけが .conf の値を上書きする仕組みなので、変えたい項目だけを書けば十分です。

ディストリビューションによっては /etc/fail2ban/jail.d/ に独自の初期設定(Debian の defaults-debian.conf など)が置かれ、sshd の jail がはじめから有効になっていることがあります。自分の設定と重ならないよう、最初に中身を見ておいてください。

SSH を守る基本の設定

まずは SSH のログイン失敗を対象にした設定です。

# /etc/fail2ban/jail.local
[DEFAULT]
# 自分の管理用IPやローカルは対象外にする(スペース区切り)
ignoreip = 127.0.0.1/8 ::1 203.0.113.10

# 10分間に5回失敗したら、1時間ブロック
findtime = 10m
maxretry = 5
bantime  = 1h

# ログの読み方:systemd の journal を読む
backend = systemd

# 遮断に使う仕組み(環境に合わせて選ぶ。下の説明を参照)
banaction = nftables-multiport
banaction_allports = nftables-allports

[sshd]
enabled = true
port    = ssh

各項目の意味は次のとおりです。

  • findtime と maxretry:この期間内にこの回数の失敗があればブロックする、というしきい値です。厳しくしすぎると、パスワードを打ち間違えた正規の利用者も止まります
  • bantime:ブロックしておく期間です。-1 にすると無期限になりますが、ルールがたまり続けるので、まずは時間を区切る方が運用しやすくなります
  • ignoreip:決してブロックしない送信元です。固定IPの管理用回線があれば入れておくと、自分を締め出す事故を防げます
  • backend:ログの取得方法です。最近の Debian や Ubuntu では、SSH のログが /var/log/auth.log ではなく systemd の journal にしか出ない構成が増えています。その場合はファイルを読む設定のままだと何も検知できないので、systemd を指定します

banaction は、ブロックを実際に行う仕組みの選択です。使っているファイアウォールに合わせて、たとえば次のように選びます。

  • nftables を直接使っている:nftables-multiport
  • firewalld を使っている:firewallcmd-rich-rules など(RHEL 系のパッケージでは、fail2ban-firewalld を入れると firewalld 向けの初期設定が入ることがあります)
  • ufw を使っている:ufw
  • iptables を使っている:iptables-multiport

利用できるアクションは /etc/fail2ban/action.d/ にあるファイル名で確認できます。名前はバージョンで増減することがあるので、手元のディレクトリにあるものを選んでください。SSH のポートを22番から変えている場合は、port = 2222 のように実際の番号を書きます。ここが違うと、ブロックしたつもりで別のポートを塞ぐことになります。

設定を変えたら、構文を確かめてから反映します。

sudo fail2ban-client -t        # 設定の読み込みテスト
sudo systemctl restart fail2ban
sudo fail2ban-client status
sudo fail2ban-client status sshd

status sshd の出力で、「Currently failed」(失敗を数えている数)や「Currently banned」(ブロック中の数)と、ブロック中のIPの一覧が確認できます。

繰り返す相手はブロック期間を延ばす

一度ブロックが解けるとまた試してくる相手には、ブロックのたびに期間を延ばす設定が使えます。比較的新しい fail2ban では bantime.increment という設定項目があります。

[DEFAULT]
bantime.increment = true
bantime.maxtime   = 1w

古い版で使われてきた方法として、fail2ban 自身のログを監視して、何度もブロックされた相手を長期間止める recidive という jail もあります。どちらを使うかは、手元のバージョンの jail.conf に書かれている説明を確認して決めてください。

Webサーバーのログでログイン試行を止める

WordPress のログイン画面への総当たりも、Webサーバーのアクセスログを使って検知できます。WordPress はログインに失敗するとログインフォームを再表示し(ステータス200)、成功するとリダイレクト(ステータス302)を返すのが標準の動作です。この違いを使って、POST /wp-login.php に200が返った記録を「失敗」として数えるのが代表的な方法です。

# /etc/fail2ban/filter.d/wp-login.conf
[Definition]
failregex = ^<HOST> -[^"]*"POST /wp-login\.php[^"]*" 200
ignoreregex =
# /etc/fail2ban/jail.local に追記
[wp-login]
enabled  = true
port     = http,https
filter   = wp-login
backend  = auto
logpath  = /var/log/nginx/access.log
maxretry = 5
findtime = 10m
bantime  = 1h

この判定は標準のログイン画面を前提にしています。二段階認証やログイン画面をカスタマイズするプラグインを使っていると、ステータスの返し方が変わることがあるので、実際のログを見て正規表現を調整してください。WordPress の中で失敗回数を数えるプラグインと併用する場合は、どちらで止めるかを決めておくと、問い合わせがあったときに原因を追いやすくなります。

正規表現が意図どおりにログへ一致するかは、fail2ban-regex で確認できます。本番で有効にする前に、ここで一致件数を確かめるのが安全です。

sudo fail2ban-regex /var/log/nginx/access.log /etc/fail2ban/filter.d/wp-login.conf

CDN やリバースプロキシの裏にある場合の注意

Cloudflare などの CDN やロードバランサーを経由していると、アクセスログに記録される送信元IPが、利用者ではなく CDN やプロキシのアドレスになっていることがあります。この状態で fail2ban を動かすと、CDN のアドレスをブロックしてしまい、正規の利用者も含めてサイトにつながらなくなります。

先に Webサーバー側で本来の送信元IPをログに記録する設定(Nginx の real_ip モジュールで信頼するプロキシを指定する、など)を行ってください。また、CDN 経由の通信はオリジンのファイアウォールで送信元IPを止めても効かないため、その場合は CDN 側のファイアウォール機能でブロックする構成を検討します。

自分をブロックしてしまったときの解除

管理用のIPがブロックされた場合は、別の回線やクラウドのコンソール接続からサーバーに入り、次のコマンドで解除します。

# 特定の jail から外す
sudo fail2ban-client set sshd unbanip 203.0.113.10

# ブロック中の一覧を確認
sudo fail2ban-client status sshd

再発を防ぐには、そのIPを ignoreip に追加します。IPが変わる回線なら、ignoreip に頼らず、VPN 経由で入るなどの方法を併用してください。

動かないときの確認ポイント

設定したのにブロックされない場合は、次の順に確認します。

  1. jail が有効になっているか:sudo fail2ban-client status の一覧に名前があるか
  2. ログを読めているか:backend と logpath が実際のログの場所と合っているか。SSH が journal にしか出ていないのに、ファイルを読む設定になっていないか
  3. フィルターが一致しているか:fail2ban-regex で一致件数が0になっていないか。ログの形式(log_format)を変えていると一致しなくなります
  4. 時刻がずれていないか:ログの時刻が古いと判定の対象外になります
  5. 遮断の仕組みが合っているか:sudo nft list ruleset や sudo iptables -L -n に fail2ban のルールが入っているか。ufw や firewalld を使っているのに別の仕組みを指定していないか

fail2ban 自身のログ(多くの環境で /var/log/fail2ban.log)には、検知やブロックの記録が出るので、あわせて確認すると原因を絞り込みやすくなります。

まとめ

  • fail2ban は、ログの失敗記録が多いIPを一定時間ファイアウォールで止めるツールです。分散型の攻撃や DDoS への対策にはなりません
  • 設定は jail.local に書き、findtime・maxretry・bantime・ignoreip・backend・banaction を環境に合わせて決めます
  • SSH のログが journal にしか出ない環境では backend = systemd を指定します
  • Web のログイン保護はアクセスログとフィルターで行い、fail2ban-regex で一致を確かめてから有効にします
  • CDN やプロキシの裏では、本来の送信元IPをログに残す設定が先です

お気軽にご相談ください

お見積りへ お問い合わせへ
▲