深夜2時14分。PagerDutyのアラートがけたたましく鳴り響き、Grafanaのダッシュボードを見るとバックエンドデータベースのCPU使用率が100%に張り付いています。tail -f /var/log/nginx/access.logを確認すると、インデックスのない検索エンドポイントに対して毎秒3,200件ものPOSTリクエストが殺到していました。
攻撃者は' OR 1=1--といった典型的なSQLインジェクションのプローブに加え、/etc/passwdを狙ったパストラバーサルのスキャンを仕掛けています。WAFレイヤーが存在しない場合、こうした悪意あるトラフィックは直接アプリケーションワーカーへと到達します。不正なクエリがワーカーのスレッドを次々と占有し、あっという間に100接続のデータベース接続プールを枯渇させてしまいます。夜明けを迎える前に、Nginx上でインライン動作するWeb Application Firewallを立ち上げなければなりません。
クラウドエッジWAF vs. Nginxホスト型ModSecurity
オリジンサーバーに激しい攻撃が仕掛けられた際、不正なパケットを遮断する方法は主に2つあります。アップストリームのクラウドファイアウォールを利用するか、あるいはModSecurityのようなホスト内エンジンを利用するかです。
どちらの方式も既知の脆弱性シグネチャと照合してペイロードを評価しますが、アーキテクチャ上の動作レイヤーが異なります:
- クラウドWAF(AWS WAF、Cloudflare、Fastly):DNSおよびCDNエッジに配置されます。トラフィックがVPSやベアメタルのネットワークインターフェースに到達する前にリクエストを評価します。ポリシーは各プロバイダーの管理コンソールやTerraformスクリプト経由で管理します。
- ホスト型ModSecurity v3(libmodsecurity + Nginxコネクタ):動的モジュールとしてNginxインスタンス内部で動作します。リクエストが内部のアプリケーションソケットに渡される直前に、ヘッダー、パラメータ、クッキー、リクエストボディを評価します。
日常的な運用における両アプローチの比較は以下のとおりです:
| 運用上の比較項目 | クラウドエッジWAF | ホスト型ModSecurity + OWASP CRS |
|---|---|---|
| 導入・セットアップ | DNSを切り替えるだけで迅速に導入可能だが、外部ルーティングや証明書の共有が必要。 | Nginxへの動的モジュールのコンパイルまたはロードが必要。 |
| データプライバシーとコンプライアンス | 復号されたTLSペイロードが外部のCDNベンダーを経由する。 | サードパーティへのデータ露出ゼロ。ペイロードは完全にホストのRAM内でのみ処理される。 |
| 帯域消費型の大量攻撃(DDoS) | 物理ネットワークインターフェースが飽和する前に、マルチギガビット規模の攻撃トラフィックを吸収できる。 | サーバーの上り/下り回線帯域が攻撃で飽和した場合、防御できない。 |
| ルールエンジンの制御性 | ベンダーのルール制限や有償プランの制約を受ける。 | SecRuleディレクティブ、PCRE正規表現、Lua、生CRSルールファイルを完全に制御可能。 |
| コストの予測可能性 | リクエスト数(100万件単位)や検査帯域に応じた従量課金。急激なトラフィック急増時には高額化のリスクがある。 | 既存のCPUコア上で動作する完全無料のオープンソースソフトウェア。 |
エンジン内検査とエッジフィルタリングの比較・検討
Nginx内部でファイアウォールを稼働させることには大きなメリットがある一方で、運用上の責任も伴います。
Nginx上でModSecurityを動かすメリット
- データの主権(Data Sovereignty):サードパーティのプロキシが顧客のペイロード、セッションクッキー、認証トークンを読み取ることは一切ありません。HIPAA、PCI-DSS、GDPRなどの厳格なデータ隔離要件がある場合でも、コンプライアンス上の摩擦を回避できます。
- 内部コンテキストの把握:ModSecurityは、外部CDNからは見えない内部ルーティングヘッダー、マイクロサービスのパス書き換え、アップストリームのプロキシヘッダーまで検査できます。
- コストの確実性:トラフィックが急増しても、月末に想定外の多額な検査費用を請求される心配がありません。
Nginx上でModSecurityを動かすデメリット
- CPU負荷とレイテンシ:リクエストボディに対する正規表現のパース処理には計算リソースが必要です。標準的なワークロードにおいて、複雑なルールセットを実行すると通常HTTPリクエストごとに2ms〜8msの処理レイテンシが発生します。
- 誤検知(False Positives):デフォルトのルールでは、正当なJSONペイロードやユーザーが投稿したMarkdownテキストまでブロックしてしまうことがあります。正常なトラフィックを通すための除外ルールを策定する必要があります。
- バイナリの結合度:コネクタモジュールは、稼働中のNginxの正確なABIとリンクします。Nginxパッケージのマイナーアップグレード時であっても、バイナリの不一致を防ぐために
ngx_http_modsecurity_module.soの再コンパイルが必要になる場合があります。
推奨アーキテクチャ:Libmodsecurity3とOWASP CRS v4
インシデント発生中に場当たり的なカスタムルールを急造するのは避けましょう。ゼロデイ攻撃やOWASP Top 10の脆弱性を遮断するための実績ある基盤となるのが、ModSecurity v3とOWASP Core Rule Set(CRS)v4の組み合わせです。
Ubuntu 22.04および24.04 LTSサーバーでは、次の3つの要素を中心に構築します:
- コアエンジン:共有C++ライブラリとしてビルドされた
libmodsecurity3。 - Nginxコネクタ:既存のNginxパッケージに動的ロードされる
ngx_http_modsecurity_module.so。 - 検知ルール:パラノイアレベル1(Paranoia Level 1)のアノマリースコアリングモードで動作するOWASP CRS v4。
ステップ別の導入手順
エンジンのコンパイル、Nginxへのコネクタのロード、ルールの有効化までの手順を順を追って解説します。
ステップ1:ビルド依存パッケージのインストール
PCRE2、XMLパース、JSON処理に必要なコンパイラ、ビルドツール、開発用ヘッダーをインストールします:
sudo apt-get update
sudo apt-get install -y apt-utils autoconf automake build-essential \
git libcurl4-openssl-dev libgeoip-dev liblmdb-dev libpcre2-dev \
libpcre3-dev libtool libxml2-dev libyajl-dev pkgconf zlib1g-dev
ステップ2:Libmodsecurity v3のビルドとインストール
スタンドアロンのv3ブランチを取得し、システムの標準ライブラリパスにコンパイルしてインストールします:
cd /usr/local/src
sudo git clone --depth 1 -b v3/master https://github.com/owasp-modsecurity/ModSecurity.git
cd ModSecurity
sudo git submodule init
sudo git submodule update
sudo ./build.sh
sudo ./configure
sudo make -j$(nproc)
sudo make install
sudo ldconfig
これによりlibmodsecurity.soがコンパイルされ、/usr/local/modsecurity/lib/配下に配置されます。
ステップ3:動的Nginxコネクタのコンパイル
コネクタモジュールは、稼働中のNginxバイナリと完全に一致していなければなりません。現在のパッケージバージョンを確認します:
nginx -v
# 出力: nginx version: nginx/1.24.0
一致するソースコードをダウンロードし、--with-compatオプションを指定して動的モジュールを設定・コンパイルします:
cd /usr/local/src
sudo git clone --depth 1 https://github.com/owasp-modsecurity/ModSecurity-nginx.git
wget http://nginx.org/download/nginx-1.24.0.tar.gz
tar -xzvf nginx-1.24.0.tar.gz
cd nginx-1.24.0
./configure --with-compat --add-dynamic-module=/usr/local/src/ModSecurity-nginx
make modules
sudo cp objs/ngx_http_modsecurity_module.so /etc/nginx/modules/
ステップ4:ModSecurityとOWASP CRS v4の設定
設定ファイルとルールパッケージを配置するために、/etc/nginx/modsec/内にクリーンなディレクトリ構成を作成します:
sudo mkdir -p /etc/nginx/modsec
cd /usr/local/src/ModSecurity
sudo cp modsecurity.conf-recommended /etc/nginx/modsec/modsecurity.conf
sudo cp unicode.mapping /etc/nginx/modsec/
cd /etc/nginx/modsec
sudo git clone --depth 1 -b v4.0/master https://github.com/coreruleset/coreruleset.git
sudo cp coreruleset/crs-setup.conf.example coreruleset/crs-setup.conf
コア設定、セットアップ設定、CRSルールを読み込むためのメインエントリーポイント/etc/nginx/modsec/main.confを作成します:
cat << 'EOF' | sudo tee /etc/nginx/modsec/main.conf
Include /etc/nginx/modsec/modsecurity.conf
Include /etc/nginx/modsec/coreruleset/crs-setup.conf
Include /etc/nginx/modsec/coreruleset/rules/*.conf
EOF
ステップ5:エンジンモードの調整と監査ログの設定
本番切り替え時に過度なブロックによって正規ユーザーのセッションを遮断してしまわないよう注意が必要です。/etc/nginx/modsec/modsecurity.confを開き、エンジンディレクティブを確認します:
sudo sed -i 's/SecRuleEngine DetectionOnly/SecRuleEngine On/' /etc/nginx/modsec/modsecurity.conf
独自のペイロードスキーマを持つ大量トラフィックのAPIを運用している場合は、まず30〜60分ほどDetectionOnly(検知のみ)に設定しておきましょう。ログに記録された検知内容を確認し、誤検知をチューニングしてからディレクティブをOnに切り替えます。
サーバーメンテナンス中に管理インターフェースへのアクセスを制限し、認証情報ボールトのキーをローテーションする際、サーバー用パスワードの生成には toolcraft.app/ja/tools/security/password-generator のパスワードジェネレーターを活用しています。完全にブラウザ内で動作するため、データがネットワーク経由で送信される心配がありません。本番環境の管理画面を高エントロピーなシークレットで保護したら、次はNginxとの統合に進みましょう。
ステップ6:モジュールのロードとバーチャルホストへの適用
/etc/nginx/nginx.confの先頭行にモジュール読み込みディレクティブを追加します:
load_module modules/ngx_http_modsecurity_module.so;
user www-data;
worker_processes auto;
pid /run/nginx.pid;
対象となるバーチャルホストのserverブロック内でModSecurityを有効化します:
server {
listen 80;
server_name api.example.com;
modsecurity on;
modsecurity_rules_file /etc/nginx/modsec/main.conf;
location / {
proxy_pass http://127.0.0.1:8000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
設定テストを実行し、ダウンタイムなしでワーカープロセスをリロードします:
sudo nginx -t && sudo systemctl reload nginx
ステップ7:ブロック動作と監査ログの確認
外部クライアントから模擬的なパストラバーサルのプローブを送信し、Nginxがリクエストを正しく遮断するか検証します:
curl -i "http://api.example.com/?exec=/etc/passwd"
リバースプロキシが即座にペイロードを拒絶し、403 Forbiddenステータスを返すはずです:
HTTP/1.1 403 Forbidden
Server: nginx
Date: Thu, 15 Oct 2026 02:35:10 GMT
Content-Type: text/html
Content-Length: 153
Connection: keep-alive
/var/log/nginx/error.logでログに記録された検知内容を確認します:
sudo tail -n 20 /var/log/nginx/error.log
ルール930110または930120が発火していることが確認できます:[id "930110"] [msg "Path Traversal Attack (/../)"] [data "Matched Data: /etc/passwd found"] [severity "CRITICAL"]。パケットはアップストリームのワーカーに到達する前に破棄され、データベースの接続プールが解放され、アプリケーションのレイテンシが正常に戻ります。

