本ページの位置づけ
Fail2banの内部構造(なぜそう動くのか)を解説する教材です。実務での設定・運用手順は「Fail2banの運用管理」をご参照ください。
目次
第1章:マクロ構造 ── システム全体像とネットワークパケット制御
Fail2banは、単独でパケットを遮断するソフトではありません。システム上の各種サービスが出力するログファイルをリアルタイムに監視し、攻撃を検出した段階でOSのファイアウォール(firewalld)に「IP遮断の命令」を送ることで機能します。
1-1. Fail2ban 全体システム図
サーバー内部における各サービス、ログファイル、Fail2ban、そしてファイアウォールの位置関係とデータの流れを示した全体構造です。
インターネット(クラウドVPS・国内踏み台ボット含む)
│
┌──────────────┐
│ 攻撃者(IP) │
└──────────────┘
│
│ L3/L4トラフィック
▼
┌────────────────┐
│ FortiGate │ (境界FW:ポートスキャン・帯域攻撃をドロップ)
└────────────────┘
│
│ L7トラフィック(SSH / HTTP / SMTP / IMAP)
▼
┌────────┐
│ Rocky Linux 9 │
└───────┘
│
┌─────┬───────┬───────┐
▼ ▼ ▼ ▼
sshd Caddy Postfix Dovecot
(SSH制御)(Web/Proxy) (メール送信)(メール受信)
│ │ │ │
▼ ▼ ▼ ▼
auth.log access_log maillog maillog
(ジャーナル) (ファイル保存) (ジャーナル) (ジャーナル)
│ │ │ │
└─────┴──┬────┴───────┘
│
▼
Fail2ban (ログをリアルタイム監視・解析)
│
「同じIPが短時間に何回も失敗」
│
▼
firewalldへ命令 (「このIPをブロックせよ」)
│
▼
IPアドレス遮断(アクセス不能に)
1-2. データ処理シーケンス
攻撃者が接続を行ってから、ログを経由してFail2banが検知し、最終的にパケットが破棄(DROP)されて通信がタイムアウトするまでの論理的な流れ(シーケンス)です。
攻撃者 sshd systemd journal Fail2ban firewalld
│─ ssh接続試行 ───>│ │ │ │
│ │─ 認証失敗を記録 ─>│ │ │
│ │ (ログ出力) │ │ │
│ │ │─ ログを検知 ───>│ │
│ │ │ ※5回失敗をカウント│ │
│ │ │ │─ 遮断を命令 ──>│
│ │ │ │ │─ [ルール追加]
│ │ │ │ │ IPを遮断
│─── (再接続試行) ────────────────────────────────────────────>│
│ │ │ │ firewalldが破棄
│<── Connection timeout ─────────────────────────────────────│ (接続タイムアウト)
1-3. ファイアウォール(firewalld/ipset)との高速連携構造
Fail2banがIPを遮断する際、数千〜数万件の攻撃IPアドレスを1つずつファイアウォールの個別ルール(iptables等)として登録すると、CPUに甚大な負荷がかかります。これを防ぐため、Fail2banはLinuxカーネルの高速なメモリ検索構造であるipsetを利用して連携を行います。
Fail2ban (ログ検知エンジン)
│
▼
firewallcmd-ipset (実行アクション定義:[banaction])
│
▼
firewalld (OSのファイアウォール管理サービス)
│
▼
ipset (メモリ上に構築されたハッシュ型IPアドレス高速検索リスト)
│
▼
DROP (該当するIPからのパケットをシステム手前で即時に破棄)
構造上のメリット
ipsetはIPアドレスをメモリ上でハッシュテーブルとして管理するため、登録されているIPが1件であっても10万件であっても、通信がブロック対象かどうかをミリ秒以下の等価な速度で判定できます。
第2章:ミクロ構造 ── Jail と Filter の内部結合
Fail2banの内部は、監視の定義を行うJail(ジェイル/牢獄)と、ログの解析パターンを定義するFilter(フィルター)の2層構造に分かれています。
2-1. Fail2ban 内部構造図
設定ファイル/etc/fail2ban/jail.localで定義された各Jailが、どのように各アプリケーション用のフィルターファイルを呼び出し、最終的なBANアクション(遮断)に至るかの内部プロセスです。
jail.local (全体管理の設計図:どのログを、どういう条件で監視するか)
│
├───────────────┼───────────────┐
▼ ▼ ▼
[sshd] [postfix-sasl] [apache-404] ← 監視対象の窓口(Jail)
│ │ │
▼ │ ▼
ログ監視(journal) │ フィルター定義ファイル
│ │ (/etc/fail2ban/filter.d/apache-404.conf)
│ │ │
│ │ ▼
│ │ failregex (エラーを検知する正規表現パターン)
│ │ │
└───────────────┴───────────────┘
▼
ログの一致を検出
│
▼
攻撃元IPの抽出(<HOST>部のIPアドレスを認識)
│
▼
【 BAN 】
2-2. 設定ファイルの役割と管理手法
Fail2banの設定ファイルは、デフォルトファイルと、管理者が作成するカスタム用ファイルに明確に分離して構成されます。
- /etc/fail2ban/jail.conf(標準設定ファイル:不変)
インストール時に提供されるデフォルト設定です。パッケージのアップデート時に自動的に上書きされるため、このファイルは絶対に直接編集してはいけません。 - /etc/fail2ban/jail.local(カスタム設定ファイル:管理者作成)
管理者が新規に作成するファイルです。Fail2banは起動時にjail.confを読み込んだ後、jail.localの内容で設定を上書き(オーバーライド)します。必要な変更差分のみをこのファイルに記述します。
第3章:ログ解析エンジン「backend」の構造的違い
Fail2banが最も効率的に動作するか、あるいはCPUを過剰消費して遅延するかは、ログを監視する方式であるbackend(バックエンド)の選択にかかっています。
3-1. backendとは?(ログの読み込み方式)
| 方式 | 動作 | 主な対象 |
|---|---|---|
systemd | journald(システムの日記帳データベース)から、API経由で直接ログデータを読み取る。 | sshd, postfix, dovecot など、OS標準のユニットサービス |
polling | 実際のテキストログファイル(/var/log/...)を、一定周期で物理的に読みに行く。 | Apache, Caddy, Nginx など、独自のテキストログを出力するWebサービス |
auto | 対象のログパスに応じて、Fail2banが自動的に最適な読み込み方法を判定する。 | - |
3-2. Apache(Webログ)だけbackendの設定を変える理由
Modern Linux(Rocky Linux 9等)において、システムサービス(SSH、Postfix、Dovecotなど)の出力はすべてsystemd-journaldによって統合・インデックス化されています。しかし、Apacheなどのwebサーバーが出力するアクセスログは、Webサーバー自身が直接ファイルシステムに書き出しています。
Rocky Linux 9
│
┌──────────────────┴──────────────────┐
▼ ▼
systemd journal Apache独自出力
(ジャーナルデータベース) (ログファイル)
│ │
┌──────┴──────┐ ▼
▼ ▼ /var/log/httpd/access_log
SSH Dovecot
│
Postfix
▲ ▲
│ │
backend=systemd backend=polling
(システム連携で高速処理) (ログファイルを直接監視)
注意すべきシステム動作の罠
全体設定([DEFAULT])でbackend = systemdを指定した状態で、Apacheのテキストログ監視(/var/log/httpd/access_log)を行おうとすると、Fail2banは内部的にjournalmatch(ジャーナル内の検索キー)を探します。しかし、Webサーバーのアクセスログはジャーナル内にインデックスされていないため、Fail2banは検索を完了するためにバックグラウンドでjournalctlコマンドを大量に実行し、CPU使用率の高騰や、最悪の場合は検知遅延・フリーズを引き起こします。そのため、Webアクセスログを監視するJailでは、明示的にbackend = pollingを指定し、物理ファイルを追従する方式に分離する必要があります。
第4章:ログマッチングとフィルタリングの挙動原理
Fail2banが、膨大なログの中から「誰が攻撃者か」を物理的に特定するプロセスについて学習します。
4-1. ログ監視の抽象化イメージ
アクセスログ(access_log)を常時スキャンし、同一のIPアドレスから特定のエラーコードが集中する挙動を捉える概念図です。
Webアクセスログ (access_log)
──────────────────────────────────────────────
192.168.1.1 - - [...] "GET /administrator HTTP/1.1" 404 1234 ... <── 1回目(404検出)
192.168.1.1 - - [...] "GET /wp-login.php HTTP/1.1" 404 5678 ... <── 2回目(404検出)
192.168.1.1 - - [...] "GET /info.php HTTP/1.1" 404 9012 ... <── 3回目(404検出)
192.168.1.1 - - [...] "GET /phpmyadmin/ HTTP/1.1" 404 3456 ... <── 4回目(404検出)
192.168.1.1 - - [...] "GET /.env HTTP/1.1" 404 7890 ... <── 5回目(404検出)
──────────────────────────────────────────────
│
▼
Fail2banがログ抽出
│
5回検知したため
▼
【 192.168.1.1 を BAN 】
4-2. 404フィルターを例にした <HOST> 抽出の仕組み
フィルターファイルに記述された正規表現(failregex)は、ログの行と照合(パターンマッチ)を行います。
【実際のログデータの構造】
192.168.1.50 - - [01/Jan/2026:12:00:00 +0900] "GET /wp-login.php HTTP/1.1" 404 1547 "-" "Mozilla/5.0"
│ │
▼ ▼
<HOST> ──────────── 一致するか照合 ─────────────── 404
(IPアドレス部) (エラーコード)
│
▼
[ 192.168.1.50 ] を特定 ──► カウント対象とし、しきい値到達時にファイアウォールへこのIPを伝達
<HOST> タグの秘密
failregexに記述されている<HOST>は、Fail2banの内部で自動的に「IPv4またはIPv6アドレスを抽出するための強力な正規表現パターン」に展開されます。ログの先頭からこのパターンに合致した文字列を探索し、マッチしたIPアドレスを「攻撃元IP(ホスト)」としてメモリに記録します。
第5章:時間軸制御の構造(maxretry / findtime / bantime)
Fail2banは、攻撃判定の厳しさを「失敗回数(回)」「判定期間(秒)」「遮断時間(秒)」の3つのパラメータで時間軸制御しています。※設定でBANになる度合いを変更可能
1回失敗 ──> 2回失敗 ──> 3回失敗 ──> 4回失敗 ──> 5回失敗 (maxretry到達)
│
▼
【 BAN開始 】 (firewalldにIPを登録し、パケットを遮断)
│
└──► [ 30分(設定例)経過 ] (bantime経過) ───> 【 自動解除 】
5-1. スライディングウィンドウ(findtime)の物理的挙動
findtime(監視対象期間)は、固定された時間単位ではなく、「ログが記録された瞬間から、時間を過去へさかのぼるスライディングウィンドウ」として動作します。
■ パターンA:10分以内に5回失敗した場合(BAN対象)
【 現在(ログが届いた瞬間)から10分さかのぼる時間枠 】
│─ 1回 ─ 2回 ─ 3回 ─ 4回 ─ 5回(今届いたログ)──│ ──> 【 条件成立:BAN 】
└────────────────────────────────────────┘
■ パターンB:失敗の間隔が10分を超えている場合(BAN対象外)
【 現在から10分さかのぼる時間枠 】
│(枠外に消えた古い1回目) ─ 2回 ─ 3回 ─ 4回 ─ 5回(今届いたログ)─│
└────────────────────────────────────┘
※過去10分間の枠内を計算すると「4回」しか失敗していないため、BANは発動しません。
第6章:実務運用(ゼロトラスト・多層防御)へのブリッジ
このガイドでFail2banの内部構造を学習したことで、「Fail2ban運用管理」に記載された実務設定が、なぜそのように設計されているのかが論理的に理解できるようになります。
6-1. Caddyプロキシにおける自爆BAN回避の理由が理解できる
- 構造上の理由:Fail2banの<HOST>抽出プレースホルダーが、Caddyの内部IP(172.16.1.18)にマッチしてしまうと、Fail2banはCaddyを攻撃者と誤認して遮断します。
- 運用書との連携:X-Forwarded-For(クライアントのグローバルIP)を正確に抽出する正規表現(failregex)の設定が、いかにシステム維持において生命線であるかが分かります。
6-2. 厳格な ignoreip 設定が必要な理由が理解できる
- 構造上の理由:ignoreipに指定されたIPアドレスは、Jail処理を通過する前にFail2banの判定エンジンから「無視(Ignore)」されます。
- 運用書との連携:サブネット全体(/24など)をホワイトリスト化してしまうと、内部端末が1台ウイルス感染した際にその内部攻撃がFail2banを素通りしてしまいます。そのため、ピンポイント指定による「最小権限原則」が設計されています。
6-3. TLSエラー一括BANが非推奨である理由が理解できる
- 構造上の理由:TLSエラー(SSLハンドシェイクエラーなど)は、ネットワークの瞬断(電波障害)や古い端末の接続時にも、システムによって「エラーログ」として記録されます。
- 運用書との連携:これを一律で正規表現マッチングしてしまうと、一般的なスマートフォンユーザーが移動中(4GとWi-Fiの切り替え時)に高確率で誤BANされる運用障害を引き起こすため、ログ分類から明確に除外する設計になっています。
おわりに
Fail2banは、「ログをパースするFilter」、「監視条件を定めるJail」、そして「高速にIPを処理するipset」の3つの構造が美しく連携することで、サーバーのシステムリソースをほとんど消費せずに数万の攻撃からインフラを強固に守る仕組みです。この内部構造の知識を基礎として、「Fail2banの運用管理」で実務用のゼロトラスト環境セキュリティ設定を確認してください。
Fail2banの内部構造、これで整理完了 🎉
システム全体像・Jail/Filter構造・backend方式・時間軸制御まで一通り確認しました。実務設定は「Fail2banの運用管理」もあわせてご参照ください。