WAF は、導入した時点で運用が終わる仕組みではありません。ModSecurity と OWASP Core Rule Set を有効にすれば、不審なリクエストを遮断できる可能性は高まります。しかし、実際の運用では「止めた」という結果だけでは不十分です。どのリクエストを、どのルールやスコアで、どの入口で止めたのかを後から確認できなければ、攻撃の可視化にも、誤検知の調整にもつながりません。
そのため、ModSecurity は通信を止める機能としてだけでなく、境界で発生した判断を記録する観測点として扱うべきです。audit log を Loki に集約し、Grafana でダッシュボード化すると、WAF の動作を「なんとなく効いている」状態から、運用上の判断材料へ変えられます。
この記事では、特定環境のホスト名や IP アドレスには踏み込まず、reverse proxy に置いた ModSecurity の audit log を Grafana で見る方法論を整理します。
WAF はアプリケーションの外側にある観測点である
Web アプリケーションの Pod や PHP プロセスの中だけを見ていると、アプリケーションに到達しなかった通信は見えにくくなります。WAF が reverse proxy に置かれている場合、アプリケーションへ渡す前の段階で、スキャン、認証攻撃、公開すべきではないファイルへのアクセス、異常な HTTP メソッド、ルールに一致したリクエストを観測できます。
この位置で記録する意味は、単に攻撃を数えることではありません。アプリケーションログ、Web サーバーログ、WAF audit log は、それぞれ見ている境界が違います。WAF audit log は、アプリケーションの手前で何が判断されたのかを残すためのログです。
| ログ | 主に見えるもの | 見えにくいもの |
|---|---|---|
| アプリケーションログ | 処理されたリクエスト、例外、業務上の状態 | WAF や reverse proxy で遮断された通信 |
| Web サーバーログ | HTTP ステータス、URL、User-Agent、転送量 | どの WAF ルールが判断したか |
| ModSecurity audit log | リクエスト内容、判定理由、ルール、 anomaly score、遮断結果 | アプリケーション内部の業務処理 |
WAF audit log は、アプリケーションログの代替ではありません。むしろ、アプリケーションの外側にある防御点として、別の観測面を提供します。
audit log で見るべき情報
ModSecurity の audit log は情報量が多いため、すべてを人間が毎回読む運用には向きません。Grafana で見る場合は、まず運用判断に使うフィールドを決めます。
| 観点 | 代表的なフィールド | 用途 |
|---|---|---|
| いつ発生したか | transaction_time | 急増、継続、特定時間帯の偏りを見る |
| どこから来たか | transaction_remote_address、CF-Connecting-IP | 送信元単位の集中や地域傾向を見る |
| 何を要求したか | request_request_line | wp-login.php、.env、wp-config.php などの探索を確認する |
| どう応答したか | response_status | 403、404、500 の偏りを見る |
| なぜ止めたか | audit_data_action_message、anomaly score | ルール調整や誤検知判断の材料にする |
| どの Host か | Host、X-Forwarded-Host | 複数サイトやサブドメインの入口を分けて見る |
重要なのは、WAF のログを「攻撃ログ」と決めつけないことです。403 が出ていても、それが期待通りの遮断なのか、正常な編集画面や API 呼び出しを壊しているのかは、リクエスト内容と判定理由を合わせて見なければ分かりません。
Loki へ JSON として入れる
Grafana で WAF audit log を扱いやすくするには、ログをただの文字列として保存するのではなく、JSON として検索できる状態にしておくことが重要です。Loki に source="modsecurity-audit" のようなラベルを付け、本文を JSON として扱える形にしておくと、LogQL の | json でフィールドを取り出せます。
実装上は、ModSecurity が出力する audit log をファイルとして受け、Grafana Alloy や Promtail などのログ収集エージェントで Loki へ送る構成になります。このとき、ホスト名、サービス名、ログ種別をラベルとして固定しておくと、Grafana のダッシュボードで扱いやすくなります。
| ラベル | 例 | 意味 |
|---|---|---|
source | modsecurity-audit | ModSecurity audit log であることを示す |
host | proxy-rev.example.local | どの reverse proxy から来たログかを示す |
job | modsecurity-audit | ログ収集ジョブを分ける |
filename | /var/log/apache2/modsec_audit.json | 収集元ファイルを確認する |
ラベルに入れる情報は検索の軸にするものへ絞ります。リクエスト URL や送信元 IP アドレスのように種類が増え続ける値をラベルに入れると、Loki のカーディナリティが増えすぎます。これらは JSON フィールドとして検索する方が扱いやすいです。
Grafana で見るべきパネル
ダッシュボードは、細かいログを読むためだけではなく、状況を短時間で把握するために作ります。最初に見るべきパネルは多くありません。
| パネル | 目的 |
|---|---|
| audit entries | WAF audit log 全体の量を見る |
| WAF blocks | 403 の増減を見る |
| status 別件数 | 200、403、404、500 の比率を見る |
| Top remote addresses | 特定送信元の集中を確認する |
| Top request lines | 狙われている URL や HTTP メソッドを見る |
| WordPress REST / login blocks | 正常操作と攻撃が混ざりやすい入口を確認する |
| Recent WAF blocks | 直近の遮断内容を時系列で読む |
たとえば、過去 24 時間の status 別件数を見ると、403 が増えているのか、404 の探索が多いのか、500 が混ざっていないかを確認できます。WAF の正常性を見るには、遮断件数だけでなく、成功応答やアプリケーションエラーとの関係も見ます。
sum by (response_status) (
count_over_time({source="modsecurity-audit", host="proxy-rev.example.local"} | json [24h])
)遮断されたリクエストの傾向を見る場合は、request_request_line で集計します。これにより、.env、wp-login.php、wp-comments-post.php、未知の HTTP メソッドなど、どの入口にアクセスが集中しているかを確認できます。
topk(10,
sum by (request_request_line) (
count_over_time(
{source="modsecurity-audit", host="proxy-rev.example.local"}
| json
| response_status="403"
[24h]
)
)
)このようなクエリは、単に攻撃者を探すためのものではありません。正常な編集操作や API 呼び出しが WAF に巻き込まれていないかを確認するためにも使います。
403 を攻撃件数として扱わない
WAF のダッシュボードを作ると、どうしても 403 の件数に目が行きます。しかし、403 は攻撃件数そのものではありません。WAF が遮断した通信、Web サーバー側で拒否した通信、認可上拒否された通信が混ざることがあります。さらに、誤検知によって正常な通信が遮断されている可能性もあります。
そのため、403 は「確認すべき判断結果」として扱います。送信元、リクエスト行、Host、WAF の action message、発生時間帯を合わせて見て、期待通りの遮断なのか、ルール調整が必要なのかを判断します。
| 見えた状態 | すぐに断定しない理由 | 次に見るもの |
|---|---|---|
403 が増えた | 攻撃増加とも誤検知とも限らない | request line、action message、対象 Host |
.env 探索が多い | 一般的なスキャンであり、個別侵害とは限らない | 送信元集中、継続時間、他の探索 URL |
wp-login.php が多い | Bot、正規ログイン、監視が混ざる可能性がある | User-Agent、送信元、成功応答との関係 |
| 特定 API が遮断された | 攻撃ではなく、アプリケーション更新後の仕様変更かもしれない | 直近の変更、WordPress / plugin の更新履歴 |
WAF ログを Grafana で見る価値は、数を眺めることではなく、判断を戻せることにあります。攻撃、誤検知、設定ミス、アプリケーション変更を分けて考えるための材料にします。
WAF ルール調整の流れ
ModSecurity のルール調整は、ログを見ながら例外を増やす作業ではありません。まず遮断結果を観測し、正常通信か不正通信かを分類し、必要な場合だけ範囲を限定した例外に落とします。
| 段階 | 行うこと |
|---|---|
| 観測 | status、request line、Host、送信元、action message を見る |
| 分類 | スキャン、Bot、正常操作、アプリケーション変更、誤検知を分ける |
| 影響確認 | 編集、REST API、ログイン、コメント投稿などの正常系を確認する |
| 例外設計 | URL、メソッド、パラメータ、Host、ルール ID などで範囲を絞る |
| 反映後確認 | 遮断が減ったかだけでなく、不要な許可が増えていないかを見る |
例外は広く入れるほど楽になりますが、防御点としての意味は薄くなります。特定の plugin や管理画面に必要な通信だけを許可するなど、観測結果から範囲を絞ることが重要です。
公開してはいけない情報もある
WAF audit log は、公開記事や共有資料へそのまま貼るべきログではありません。実ホスト名、内部 IP アドレス、Cookie、認証ヘッダー、POST body、攻撃元 IP アドレス、WordPress の管理 URL、plugin 名などが含まれる場合があります。
ブログ記事や運用メモにする場合は、実データを匿名化し、クエリ例も proxy-rev.example.local のような仮名に置き換えます。Grafana のスクリーンショットを使う場合も、変数、Host、IP アドレス、request body が写り込まないようにします。
また、WAF ログはセキュリティ運用上の情報です。Grafana の閲覧権限、Loki の保存期間、ログに含まれる個人情報や機微情報の扱いも設計対象になります。可視化することと、誰でも見られるようにすることは別です。
参考資料
- ModSecurity Reference Manual v3.x
- OWASP ModSecurity Core Rule Set
- Grafana Loki documentation: LogQL
- Grafana documentation: Dashboards
参考書籍
体系的に学ぶ 安全な Web アプリケーションの作り方 第 2 版
WAF だけに頼らず、Web アプリケーションの脆弱性、入力値、認証、セッション、運用上の防御を体系的に確認したい場合の参考書籍です。価格や在庫はリンク先で確認してください。
Amazon で見るこのリンクは Amazon アソシエイトリンクです。
関連する記事
まとめ
ModSecurity を導入しても、遮断結果を確認できなければ、WAF はブラックボックスになります。audit log を Loki に集約し、Grafana で可視化すると、WAF が何を見て、どのように判断したのかを運用に戻せます。
見るべきものは、単純な 403 の件数ではありません。送信元、request line、Host、response status、action message、anomaly score を合わせて見て、攻撃、誤検知、設定ミス、アプリケーション変更を分けることが重要です。
WAF は通信を止める装置であると同時に、境界で発生した判断を記録する観測点です。Grafana で ModSecurity の audit log を見ることは、防御を強くするだけでなく、防御の理由を説明できる状態にするための運用設計です。

