【AlmaLinux 9】Apache中級者講座 第3回:mod_securityとAIを活用した最強WAF構築・チューニング術

こんにちは!「LINUX工房」管理人の「リナックス先生」です。
全8回の「Apache中級者講座」、第3回目となる今回は、Webサーバーをアプリケーションレベルの攻撃から守る最終兵器、「WAF(Web Application Firewall)」の構築と、AIを活用した高度な運用チューニングについて解説します。

前回の第2回では、アクセス制御やセキュリティヘッダによって「不審なアクセスを入り口で弾く」「ブラウザの防御力を高める」手法を学びました。
しかし、正常なアクセスを装って送られてくる「SQLインジェクション」や「クロスサイトスクリプティング(XSS)」といった、Webアプリケーションの脆弱性を突く攻撃は、IP制限やヘッダ設定だけでは防ぎきれません。

そこで登場するのが、通信の「中身(ペイロード)」を検査して悪意あるリクエストを遮断するWAF、すなわち「mod_security」です。

コウ君

先生、WAFって言葉はよく聞きますが、導入すると「正常なユーザーまでアクセスできなくなる(誤検知)」って先輩から脅されて、怖くて手が出せません…。
設定もすごく複雑だって聞きました。

リナックス先生

コウ君の先輩の言う通り、WAF運用の最大の敵は「フォルス・ポジティブ(誤検知)」よ。
でも安心して。今回は世界標準のルールセット「OWASP CRS」を使って安全に導入する方法と、呪文のように難解なエラーログを「AI」に丸投げして一瞬でチューニングルール(例外設定)を作らせる、現代のプロエンジニアのチート技を伝授するわ!
これをマスターすれば、WAFはもう怖くないわよ。

本記事は、AlmaLinux 9環境において、エンタープライズレベルの防御力を誇るWAFを構築し、実践的な運用ベースに乗せるための完全ガイドです。

📚 Apache中級者講座・連載アーカイブ(全8回)


1. なぜWAFが必要なのか?Firewalldとの決定的な違い

サーバー構築の基本として、AlmaLinux 9には標準で firewalld が導入されています。しかし、これだけではWebサイトを守ることはできません。

ネットワークレベルの防御(Firewalld)

Firewalldは「IPアドレス」や「ポート番号(80や443)」を見て、通信を通すか弾くかを決定します。例えるなら、「建物の入り口にいる警備員」です。「社員証(正しいポート)を持っていれば、誰でも中に入れる」という状態です。

アプリケーションレベルの防御(WAF)

一方、Webアプリケーションへの攻撃(SQLインジェクションやOSコマンドインジェクションなど)は、許可された80番や443番ポートを通って、正常なHTTPリクエストの「中身(POSTデータやURLパラメータ)」に隠れてやってきます。
WAF(mod_security)は、通信の荷物の中身を一つ一つ開けて危険物がないか確認する「手荷物検査(X線検査)」の役割を果たします。

WordPressなどのCMSや、自作のPHPアプリケーションを運用している場合、この手荷物検査なしでインターネットに公開するのは、爆弾を持ち込まれるのを待っているようなものです。


2. AlmaLinux 9への mod_security と OWASP CRS のインストール

それでは、実際にAlmaLinux 9環境のApacheに mod_security をインストールしていきます。
AlmaLinux 9では、EPEL(Extra Packages for Enterprise Linux)リポジトリから最新の安定版パッケージを取得するのが標準的です。

2-1. EPELリポジトリとパッケージのインストール

まずはEPELリポジトリを有効化し、本体である mod_security と、世界中のセキュリティ専門家が作成したルール集である mod_security_crs(OWASP ModSecurity Core Rule Set)をインストールします。

# EPELリポジトリのインストール
sudo dnf install epel-release -y

# mod_security と CRS のインストール
sudo dnf install mod_security mod_security_crs -y

インストールが完了すると、Apacheのモジュールディレクトリに自動的に設定ファイルが配置されます。

2-2. モジュールのロード確認

Apacheにモジュールが正しく認識されているか確認します。

httpd -M | grep security

出力に security2_module (shared) と表示されていれば、インストールは成功です。


3. mod_securityの初期設定と「検知モード」での安全な起動

WAFを導入する際、絶対にやってはいけないのが「いきなり防御(遮断)モードで本番稼働させること」です。
誤検知によって、WordPressの管理画面へのログインや記事の投稿まで遮断されてしまう可能性があるからです。
まずは、「攻撃を検知してログには残すけれど、通信は通す(DetectionOnly)」という設定で運用を開始します。

3-1. mod_security.conf の編集

メインの設定ファイルである /etc/httpd/conf.d/mod_security.conf をエディタで開きます。

sudo vi /etc/httpd/conf.d/mod_security.conf

以下のディレクティブを探し、設定を変更します。

# 変更前(デフォルトでOnになっている場合があります)
# SecRuleEngine On

# 変更後(まずは検知のみ行うモードに設定)
SecRuleEngine DetectionOnly

# 監査ログ(Audit Log)の出力先を確認(デフォルトのままでOK)
SecAuditLog /var/log/httpd/modsec_audit.log

設定を保存したら、Apacheの構文チェックを行い、再起動します。

sudo apachectl configtest
sudo systemctl restart httpd

これで、あなたのサーバーには「最強の監視カメラ」が設置されました。数日間この状態で運用し、どのようなアクセスが「攻撃」と判定されるのかをログに蓄積します。


4. アノマリースコアリング(Anomaly Scoring)の深い理解

OWASP CRS(Core Rule Set)は、現在「アノマリースコアリング」という高度な判定方式を採用しています。中級者として、この仕組みを理解することは必須です。

従来の判定方式との違い

昔のWAFは、「1つでもブラックリストに一致する文字列(例:`<script>`)があれば、即座に通信を遮断する」という方式でした。これは非常に誤検知が多く、運用を難しくしていました。

アノマリースコアリングとは?

現在の方式では、リクエストがルールに違反するたびに「スコア(点数)」が加算されていきます。
例えば:

  • 「User-Agentが怪しい」→ +2点
  • 「URLパラメータにSQLの予約語が含まれている」→ +5点
  • 「存在しないファイルへのアクセス」→ +3点

このようにスコアを蓄積し、合計点数が「閾値(デフォルトは5点)」を超えた場合のみ、最終的にアクセスを遮断(403 Forbidden)します。
これにより、「少し怪しいけれど決定打に欠ける」ようなグレーな通信を許容しつつ、複合的な攻撃を確実に防ぐことができるようになりました。

このスコアリングの閾値や、検査の厳格さ(パラノイアレベル:PL1〜PL4)は、/etc/httpd/modsecurity.d/crs-setup.conf で細かく設定することができます(初期設定では最も安全なPL1に設定されています)。


5. AIを活用した監査ログ(Audit Log)の解析と例外ルールの生成

数日間 DetectionOnly で運用すると、/var/log/httpd/modsec_audit.log に大量のログが蓄積されます。
この監査ログは、WAFが何を検知したかを詳細に記録していますが、人間が読むにはあまりにも難解で、文字の暴力と言っても過言ではありません。

例えば、WordPressで記事を保存した際に誤検知が発生した場合、以下のようなログが出力されます。

--3a4b5c6d-A--
[10/May/2026:15:20:00 +0900] Xyz1234567890 192.168.1.100 54321 10.0.0.1 443
--3a4b5c6d-B--
POST /wp-admin/post.php HTTP/1.1
Host: www.linuxkoubou.com
Content-Type: application/x-www-form-urlencoded
--3a4b5c6d-H--
Message: Warning. Pattern match "(?i)<script[^>]*>[\\s\\S]*?</script>" at ARGS:content. [file "/etc/httpd/modsecurity.d/activated_rules/REQUEST-941-APPLICATION-ATTACK-XSS.conf"] [line "120"] [id "941110"] [msg "XSS Filter - Category 1: Script Tag Vector"] [data "Matched Data: <script>alert(1)</script> found within ARGS:content: ..."] [severity "CRITICAL"] [ver "OWASP_CRS/3.3.0"] [tag "application-multi"] [tag "language-multi"] [tag "platform-multi"] [tag "attack-xss"]
Action: Intercepted (phase 2)
...

これを手作業で読み解き、「どのURL」の「どのパラメータ」に対して「どのルールID」を除外すべきかを考えるのは、熟練のエンジニアでも骨が折れます。

ここで、生成AI(GeminiやChatGPT)を活用します。

5-1. AIへのプロンプト:監査ログの丸投げ解析

該当する時間のログブロック(`–xxx-A–` から `–xxx-Z–` まで)をコピーし、AIに以下のプロンプトとともに投げ込みます。

あなたは熟練のWAF(mod_security)チューニングエンジニアです。
以下の modsec_audit.log の内容を解析し、誤検知(フォルス・ポジティブ)を解消するための「例外設定(SecRuleRemoveById または SecRuleUpdateTargetById)」のコードを生成してください。

【要件】
1. どのURL(REQUEST_URI)に対するリクエストで検知されたか。
2. どのパラメータ(ARGSなど)が検知に引っかかったか。
3. トリガーされたルールID(id)は何か。
4. なぜこの検知が発生したのか、分かりやすく解説すること。
5. この誤検知を回避するための、Apacheの設定ファイル(VirtualHost内や専用のconfファイル)に記述すべき具体的なカスタムルールを提示すること。対象のURLとパラメータに限定した、最も安全な除外方法(SecRuleUpdateTargetById)を優先してください。

【監査ログ】
(ここに抽出した modsec_audit.log のログブロックを貼り付けます)

5-2. AIによる圧倒的なチューニング提案

このプロンプトを使用すると、AIは難解なログを一瞬で解析し、以下のようなプロレベルの回答を提示してくれます。

【AIの回答例】

1. 検知の概要
・対象URL: /wp-admin/post.php
・対象パラメータ: ARGS:content(記事の本文データ)
・検知されたルールID: 941110 (XSS Filter – Script Tag Vector)

2. 原因の解説
WordPressの管理画面から記事を投稿・編集(POST)した際、本文(content)の中に <script> タグに類似する文字列が含まれていたため、OWASP CRSが「クロスサイトスクリプティング(XSS)攻撃」と判定して警告を出しました。これは管理者による正当な操作であるため、典型的な誤検知(フォルス・ポジティブ)です。

3. 解決策(カスタムルールの提示)
ルールID 941110 を完全に無効化するとサーバー全体のセキュリティが低下するため、特定のURL(/wp-admin/post.php)に対するリクエスト時のみ、対象パラメータ(content)の検査を除外する設定が最適です。

SecRule REQUEST_URI "@beginsWith /wp-admin/post.php" \
    "id:10001,phase:2,pass,nolog,\
    ctl:ruleRemoveTargetById=941110;ARGS:content"

いかがでしょうか。AIを利用することで、数時間かかるログ解析とマニュアルの読み込みが、わずか数十秒で完了します。これが現代の「AI主導のインフラ運用」です。


6. チューニングの適用と「防御モード」への移行

AIが生成してくれた例外ルールを、Apacheに適用していきます。

6-1. 例外ルール専用ファイルの作成

OWASP CRSの本体ファイルを直接編集すると、アップデート時に上書きされてしまいます。
そのため、カスタムルール専用のファイルを作成します。

sudo vi /etc/httpd/conf.d/modsecurity_custom.conf

ここに、先ほどAIが生成したルールを貼り付けます。

# WordPress投稿時のXSSルール誤検知を除外
SecRule REQUEST_URI "@beginsWith /wp-admin/post.php" \
    "id:10001,phase:2,pass,nolog,\
    ctl:ruleRemoveTargetById=941110;ARGS:content"

# 別の誤検知ルールの追加などがあれば、idを連番(10002, 10003...)にして追記していきます。

6-2. いよいよ「On(防御モード)」へ

必要な例外処理(チューニング)が完了したら、ついにWAFを本稼働させます。
/etc/httpd/conf.d/mod_security.conf を再び開き、SecRuleEngine を変更します。

# 変更前
# SecRuleEngine DetectionOnly

# 変更後(防御・遮断モード)
SecRuleEngine On

構文チェックと再起動を行います。

sudo apachectl configtest
sudo systemctl restart httpd

これで、あなたのAlmaLinux 9サーバーは、SQLインジェクションや悪意あるスクリプトを自動的に弾き返す、鉄壁の要塞へと進化しました。


総まとめ:WAF運用はAIとの対話で極める

第3回の講座、お疲れ様でした。

かつて、WAF(mod_security)の導入は「茨の道」と呼ばれ、専任のセキュリティエンジニアがいなければ運用不可能とさえ言われていました。
しかし、AlmaLinux 9のパッケージ管理による容易なインストールと、何より「AIによる難解なログの翻訳と解決策の提示」という強力な武器を手に入れた今、中級者レベルのエンジニアでも十分にエンタープライズ級のセキュリティを維持することが可能です。

WAFは生き物です。Webサイトを更新したり、新しいプラグインを入れたりするたびに、新たな誤検知が発生する可能性があります。
その時は慌てず、DetectionOnly に戻すか、AIにログを読ませて迅速にチューニングを行ってください。

次回、第4回「リバースプロキシ(mod_proxy)とロードバランシングの実践」では、アクセス集中に耐えるための負荷分散アーキテクチャの構築方法について解説します。
いよいよ、インフラの大規模構成の領域へ踏み込みます。お楽しみに!

▼ プロ仕様の環境でWAFを検証しよう ▼

mod_securityをフル活用するなら
「root権限付き 高性能VPS」

VPSおすすめランキングを見る

セキュリティ設計のスキルを武器に
「ITエンジニア専門転職」

転職エージェントを比較する

コメント