ファイアウォールをすり抜ける「アプリケーションへの攻撃」を防げ。
こんにちは!「LINUX工房」管理人の「リナックス先生」です。
前回は、大規模なトラフィックをさばくためのロードバランシングとキャッシュ戦略について学びました。
サーバーが落ちなくなった今、次に心配すべきは「中身(データ)の安全」です。
一般的なファイアウォール(L4)は、ポート(80/443)を開けるか閉じるかしか制御できません。
しかし、ハッカーは開いているポートを通って、堂々と「SQLインジェクション」や「クロスサイトスクリプティング(XSS)」といった攻撃コードを送り込んできます。
これらはアプリケーションの仕様やバグを突くため、通常のネットワーク防御では防げません。
先生、また怖い話ですか…。
一応、アプリ側(PHPやNode.js)でも入力チェックはしてるつもりなんですけど、それだけじゃダメなんですか?
WAFって導入が難しそうで、専用のアプライアンス製品を買わないといけないイメージがあります。
僕の小規模なサーバーにも導入できるんでしょうか?
アプリ側の対策はもちろん必須よ。それがセキュリティの基本。
でも、人間が書くコードにバグは付きもの。WordPressのプラグインに脆弱性が見つかることだって日常茶飯事よ。
だからこそ、アプリに届く前のNginxの段階で「怪しいリクエスト」を検知して遮断するWAF(Web Application Firewall)が必要なの。
今回は、オープンソース最強のWAF「ModSecurity」をNginxに組み込んで、最強の盾を手に入れるわよ!
本記事では、NginxにModSecurity v3を導入し、世界標準のルールセットであるOWASP CRSを適用して、Webアプリケーションをサイバー攻撃から守る方法をステップバイステップで解説します。
🚀 Nginx応用講座(全8回)カリキュラム
現在地:【第2回】WAF(Web Application Firewall)の構築。ModSecurityと最新のNginxセキュリティ
- 【第1回】大規模負荷分散とキャッシュ戦略。数万リクエストをさばく「Proxy Cache」と「Upstream」の極意
- 【第2回】WAF(Web Application Firewall)の構築。ModSecurityと最新のNginxセキュリティ
- 【第3回】マイクロサービス時代のルーティング。gRPC、WebSocket、認証プロキシ(auth_request)の統合
- 【第4回】Nginxをプログラマブルに。Lua言語(OpenResty)による動的処理と機能拡張
- 【第5回】絶対停止させない高可用性(HA)。KeepalivedによるVIP管理とフェイルオーバー
- 【第6回】可観測性(Observability)の確保。Prometheus/Grafana連携とカスタムメトリクス
- 【第7回】動的モジュールとカスタムビルド。必要な機能だけを組み込む軽量化テクニック
- 【第8回】Kubernetes Ingress Controller入門。クラウドネイティブ時代のNginx運用
※基本講座の復習はこちら:Nginx基本講座(全8回)アーカイブ
第1章:ModSecurityとOWASP CRSの基礎知識
構築を始める前に、今回使う2つの重要なコンポーネントについて理解しておきましょう。
単にインストールするだけでなく、「何がどう動いて守ってくれるのか」を知ることが重要です。
ModSecurity(モド・セキュリティ)とは?
元々はApache用に開発された、世界で最も普及しているオープンソースのWAFエンジンです。
バージョン3(ModSecurity v3 / libmodsecurity)からはアーキテクチャが刷新され、Webサーバーに依存しない独立したライブラリとなりました。
これにより、Nginxでもパフォーマンスを落とさずに利用可能になっています。
注意点: ModSecurityはあくまで「エンジン」です。これ単体では動きません。Nginxと連携する「コネクタ」と、攻撃を判定する「ルール」が必要です。
OWASP Core Rule Set (CRS) とは?
ModSecurityを動かすための「ルールの詰め合わせセット」です。
セキュリティの世界的権威であるOWASPプロジェクトがメンテナンスしており、以下の「OWASP Top 10」を含む主要な攻撃を防ぐルールが含まれています。
- SQLインジェクション (SQLi): データベースを不正操作する攻撃
- クロスサイトスクリプティング (XSS): 悪意あるスクリプトを埋め込む攻撃
- ローカルファイルインクルード (LFI): サーバー内のファイルを不正に読み出す攻撃
- シェルショック等の既知の脆弱性攻撃: 古いミドルウェアの穴を突く攻撃
- 悪質なボットやクローラー: サイトを重くしたり情報を盗むボット
「ModSecurity + OWASP CRS」の組み合わせは、OSSでWAFを構築する場合のデファクトスタンダードであり、多くの商用WAFサービスのベースにもなっています。
第2章:ModSecurity v3の導入(ビルドとインストール)
NginxでModSecurityを使うには、少し高度ですが「動的モジュール」としてコンパイルして組み込むのが一般的です。
パッケージ管理ツール(dnf/apt)だけでは最新版の連携が難しいため、ソースコードからのビルドを行います。
※OS: AlmaLinux 9 / Nginx: Mainline版 を前提とします。
ステップ1:必要な依存パッケージのインストール
ビルドに必要なコンパイラやライブラリ群をインストールします。
sudo dnf groupinstall "Development Tools" sudo dnf install git wget pcre-devel zlib-devel openssl-devel libxml2-devel libcurl-devel geoip-devel yajl-devel doxygen
ステップ2:ModSecurity本体(libmodsecurity)のビルド
GitHubからソースコードを取得し、コンパイルします。libmodsecurity はNginxとは独立したライブラリとしてシステムにインストールされます。
cd /usr/local/src sudo git clone --depth 1 -b v3/master --single-branch https://github.com/SpiderLabs/ModSecurity cd ModSecurity sudo git submodule init sudo git submodule update sudo ./build.sh sudo ./configure sudo make sudo make install
これで /usr/local/modsecurity 配下にライブラリがインストールされます。
※コンパイルには数分〜十数分かかる場合があります。
ステップ3:Nginxコネクタのビルド
次に、NginxとModSecurityを繋ぐためのモジュール(ModSecurity-nginx)を作成します。
【最重要】 ここでは、現在インストールされているNginxと「全く同じバージョン」のソースコードが必要です。
# バージョン確認 nginx -v # 例: nginx version: nginx/1.27.0 と表示された場合 # 同じバージョンのソースをダウンロード cd /usr/local/src sudo wget http://nginx.org/download/nginx-1.27.0.tar.gz sudo tar -zxvf nginx-1.27.0.tar.gz # コネクタのソースを取得 sudo git clone --depth 1 https://github.com/SpiderLabs/ModSecurity-nginx.git # モジュールのコンパイル # --with-compat オプションをつけることで、既存のNginxバイナリと互換性を持たせます cd nginx-1.27.0 sudo ./configure --with-compat --add-dynamic-module=../ModSecurity-nginx sudo make modules
成功すると objs/ngx_http_modsecurity_module.so というファイルが生成されます。
これをNginxのモジュールディレクトリにコピーします。
sudo cp objs/ngx_http_modsecurity_module.so /etc/nginx/modules/
ステップ4:モジュールの読み込み設定
nginx.conf の先頭(eventsブロックより前)に、作成したモジュールを読み込む設定を追記します。
sudo vi /etc/nginx/nginx.conf
load_module modules/ngx_http_modsecurity_module.so;
events {
...
}
第3章:OWASP Core Rule Set (CRS) のセットアップ
エンジンが入ったので、次は頭脳となる「ルール(CRS)」を配置します。
1. CRSのダウンロード
設定ファイルを置くディレクトリを作成し、GitHubからCRSをクローンします。
sudo mkdir /etc/nginx/modsec cd /etc/nginx/modsec # ModSecurityの推奨設定ファイルをソースからコピー sudo cp /usr/local/src/ModSecurity/modsecurity.conf-recommended ./modsecurity.conf sudo cp /usr/local/src/ModSecurity/unicode.mapping . # OWASP CRSのダウンロード sudo git clone https://github.com/coreruleset/coreruleset.git sudo mv coreruleset/crs-setup.conf.example coreruleset/crs-setup.conf
2. メイン設定ファイル(main.conf)の作成
これら全てのルールファイルを読み込むための親ファイルを作成します。
sudo vi /etc/nginx/modsec/main.conf
# ModSecurity基本設定 Include /etc/nginx/modsec/modsecurity.conf # OWASP CRS設定(バージョンによりパスが異なる場合があるため確認推奨) Include /etc/nginx/modsec/coreruleset/crs-setup.conf # OWASP CRSルール本体 Include /etc/nginx/modsec/coreruleset/rules/*.conf
3. Nginxでの有効化
WAFを適用したい server ブロック、または特定の location ブロックに記述します。
APIサーバーだけ守りたい場合は location /api/ の中に書くことも可能です。
server {
listen 80;
server_name example.com;
# ModSecurity有効化
modsecurity on;
# 設定ファイルの指定
modsecurity_rules_file /etc/nginx/modsec/main.conf;
location / {
proxy_pass http://backend;
}
}
これで設定完了です。Nginxをリロードしましょう。sudo systemctl reload nginx
💡 プロのノウハウ:まずは「検知モード」から
ModSecurityのデフォルト設定は “DetectionOnly”(検知のみ) です。
攻撃を見つけてもログに残すだけで、ユーザーへのレスポンスは遮断しません。
いきなり遮断モード(On)にすると、正常なアクセスまでブロックしてしまう可能性があるため、最初の1〜2週間は必ずこのモードで運用を開始してログを観察します。
第4章:WAFの動作確認と遮断テスト
実際に攻撃コードを送って、ログに残るか確認してみましょう。
※注意:以下のテストコードはご自身の管理下にあるサーバーに対してのみ実行してください。
テスト1:XSS攻撃のシミュレーション
ブラウザで以下のURLにアクセスしてみます。
http://example.com/?q=<script>alert(1)</script>
まだ遮断モードではないので、ページは普通に表示されます(アプリ側でエスケープされていれば安全ですが、WAFとしては検知すべきです)。
しかし、ログ(/var/log/modsec_audit.log)を見てみましょう。
Message: Warning. Pattern match "<script" at ARGS:q. ... [id "941100"] [msg "XSS Attack Detected via libinjection"] ...
しっかりと「XSS Attack」として検知され、ルールID 941100 が反応していることが分かります。
遮断モードへの切り替え
ログを確認して問題なさそうであれば、実際に遮断するように設定を変更します。
sudo vi /etc/nginx/modsec/modsecurity.conf
# 変更前 SecRuleEngine DetectionOnly # 変更後 SecRuleEngine On
Nginxをリロード後、もう一度さきほどのURLにアクセスしてみてください。
今度はNginxのデフォルトエラー画面 403 Forbidden が表示されるはずです。
これで、あなたのサーバーは攻撃から守られています。
第5章:運用最大の壁「誤検知(False Positive)」との戦い
WAF運用で最も大変なのが、正常なアクセスを攻撃とみなしてしまう「誤検知(False Positive)」の対応です。
例えば、WordPressの記事投稿で「SQL文の解説」を書いたり、プログラミングブログで「<script>タグを含むコード」を投稿したりすると、WAFにブロックされることがあります。
チューニング(除外設定)の手順
誤検知が発生した場合、以下の手順で特定のルールを除外(ホワイトリスト化)します。
1. ログの確認:
403エラーが出た時の audit.log または error.log を確認し、どのルールIDが反応したかを特定します。
(例: ルールID 941160 が反応)
2. 除外ルールの作成:
/etc/nginx/modsec/coreruleset/rules/ 内のファイルを直接編集するのではなく、独自の除外ファイルを作ります。
sudo vi /etc/nginx/modsec/whitelist.conf
例1:特定のルールIDを全体で無効化する(危険なので慎重に)
そのルール自体をサーバー全体でオフにします。
SecRuleRemoveById 941160
例2:特定のURL(/wp-admin/)でのみ、特定のルールを無効化する(推奨)
管理画面でのみ、特定のチェックをスキップします。
SecRule REQUEST_URI "@beginsWith /wp-admin/" \
"id:1001,phase:1,pass,nolog,ctl:ruleRemoveById=941160"
3. 読み込み設定:
作成したホワイトリストを main.conf の最後で読み込むようにします。
Include /etc/nginx/modsec/whitelist.conf
このように、ログを見ながら「これは正常な通信だ」と判断したものを一つひとつ許可していく作業(チューニング)が、WAF運用には不可欠です。
これをサボると、ユーザビリティが著しく低下してしまいます。
第6章:パフォーマンスへの影響と対策
WAFはすべてのリクエストの中身(POSTデータ含む)を詳細に検査するため、CPU負荷が高くなります。
アクセス数が多いサイトでは、パフォーマンス低下が懸念されます。
対策1:静的ファイルを除外する
画像やCSS、動画ファイルにSQLインジェクションを仕込むことはまずありません。
静的ファイルへのリクエストではModSecurityをオフにします。
location ~* \.(jpg|jpeg|png|gif|css|js|ico|woff|svg)$ {
modsecurity off;
# その他の設定...
}
対策2:監査ログの出力を絞る
デフォルトでは全てのリクエストの詳細ログ(Audit Log)を保存するため、ディスクI/Oが激増します。
「遮断した時だけログに残す」設定に変更するのが一般的です。
/etc/nginx/modsec/modsecurity.conf
# RelevantOnly: 警告やエラーがあった時だけ記録 SecAuditEngine RelevantOnly
まとめ:WAFは「育てていく」セキュリティ
お疲れ様でした!
これであなたのNginxサーバーは、アプリケーションレベルの攻撃を防ぐ強力な盾を手に入れました。
今回の重要ポイント:
- ModSecurity + OWASP CRS は最強のOSS WAF構成。
- 最初は「DetectionOnly」でログを収集し、影響を確認する。
- 誤検知は避けて通れない。除外ルール(ホワイトリスト)でチューニングする。
- 静的ファイルへのWAF適用はオフにして、パフォーマンスを守る。
WAFは「入れたら終わり」ではありません。
アプリケーションの更新や新しい攻撃手法に合わせて、日々ルールを調整し、育てていくものです。
少し手間はかかりますが、その分、あなたのサイトの安全性は格段に向上します。
さて、セキュリティの次は、現代のWeb開発トレンドである「マイクロサービス」への対応です。
最近のアプリは、REST APIだけでなく、gRPCやWebSocketといった新しい通信プロトコルを使うことが増えています。
Nginxはこれらのプロトコルも完璧にハンドリングできます。
次回、第3回は「マイクロサービス時代のルーティング。gRPC、WebSocket、認証プロキシ(auth_request)の統合」です。
最新の通信プロトコルをNginxでさばく設定や、アプリの手前に認証機能を外付けする「認証プロキシ」パターンなど、モダンなアーキテクチャに必須の技術を解説します。お楽しみに!
▼ セキュリティ技術を実践で学ぶ ▼
攻撃と防御をシミュレーション
「VPS」で自分専用環境
セキュリティスペシャリストへ
「ITエンジニア転職」


コメント