単一のアプリケーションに対し、許可と拒否をどう組むかを、設定画面の文言からではなく、通信が届く経路の点検から書き始める。テーマは how to build waf allow and deny rules for one application である。SafeLineは自前で運用するWAFで、nginxを基にしたHTTPおよびHTTPSのリバースプロキシとして動く。インターネットとアプリの間に入り、悪意のある要求を除いてから、安全な通信だけを元のアプリケーションへ渡す。ルールを先に書き足しても、その1本がプロキシを通っていなければ、許可も拒否も試験に現れない。この記事は公式の導入とプロキシの流れを土台に、チェックリストと切り分けの順で確認する。説明の所在は https://docs.waf.chaitin.com/en/home である。
着手前の点検表
ルールの良し悪しを疑う前に、次の項目を上から順に見る。
- ホストはLinuxで、アーキテクチャは x86_64 または arm64 である
- Dockerは20.10.14以降、Docker Composeは2.0.0以降である
- CPUは1コア以上、メモリは1GB以上、ディスクは5GB以上ある
- 確認コマンドは uname -m、docker version、docker compose version、free -h、df -h である
- コンソールは https://:9443 で開ける
- 対象はアプリ1件だけであり、ドメイン、待受ポート、アップストリームを別々に言える
- そのドメインの名前解決先を、元サーバではなくSafeLine側のIPだと説明できる
- 許可したい送信元と、拒否したい送信元を、ログ上の観察と対応づけて言える
1つでも説明できない項目があるなら、許可文や拒否文を増やす段階ではない。先に経路と対象を固定する。
番号付きの構築手順
-
ホスト要件をコマンドで確認する。uname -m が x86_64 か arm64 であること、docker version が20.10.14以降であること、docker compose version が2.0.0以降であること、free -h と df -h が1コア、1GB、5GBの下限を下回っていないことを見てから導入へ進む。
-
推奨の自動導入を行う。root権限で bash -c "$(curl -fsSLk https://waf.chaitin.com/release/latest/manager.sh)" -- --en を実行する。手動で置く場合は、Dockerを用意し、/data/safeline を作り、compose.yaml を取得し、.env へ文書どおりの変数を入れ、必要な秘密情報を生成してから docker compose up -d を実行する。どちらでも、待受の前提が揃ってから次へ進む。
-
コンソールを開き、管理者を作る。ブラウザで https://:9443/ へアクセスし、docker exec safeline-mgt resetadmin を実行する。表示された初期のユーザー名とパスワードを控え、その値でログインする。ここまでできなければ、アプリ単位の許可と拒否は保存できない。
-
対象を1件だけプロキシする。Applicationsの画面で Add Application を押し、Domainにアプリのドメイン名、ホスト名、またはIPアドレスを入れる。PortにはSafeLineが待ち受ける番号を入れ、例は80または443である。Upstreamには元アプリの実アドレスを入れる。HTTPSならSSLを有効にする。2件目を足してからルールを試験しない。効いているかどうかの画面が、どのアプリのものか分からなくなる。
-
ドメインの名前解決をSafeLineサーバのIPへ向ける。元アプリの公開アドレスへ向けたままでは、クライアントのHTTPとHTTPSはWAFの前を通らない。許可、拒否、レート制限、CAPTCHA、パスワード確認は、プロキシに入った通信に対して意味を持つ。
-
許可は、届ける必要があるものだけに限る。自前の監視とヘルスチェックの送信元、信頼できる管理者ネットワーク、既知の静的ファイルのパスを許可の候補にする。候補に入らない社内全域や、広いアドレス帯を慣例で許可しない。許可が広いと、拒否を後から足しても、その送信元はアプリへ届き続ける。
-
拒否は、届いてはいけないと既に言えるものに限る。ログで悪意と確認したIPアドレス、その範囲、ユーザーエージェントを拒否の候補にする。未確認の範囲をまとめて拒否すると、監視や管理者まで止まり、ルールが壊れているように見える。拒否の根拠は、試験の都合ではなく、観測済みの悪意に置く。
-
濫用と自動アクセスには、別の制御を重ねる。総当たり、通信の急増、定義した上限を超える濫用には、IPを単位にしたレート制限を当てる。人間の利用者は通し、クローラとボットは止めたい経路には Captcha Challenge を置く。通過前にパスワードの入力が必要な訪問者には Authentication Challenge を置く。これらは許可と拒否の代わりではなく、1つのアプリで残る穴を狭める制御である。
-
文書化された攻撃試験で、その1件だけを確認する。SQLインジェクション、XSS、パストラバーサル、コードインジェクション、XXEのペイロードを送り、ブラウザにブロックページが出るかを見る。併せて、コードインジェクション以外の文書化された防御対象、つまりOSコマンドインジェクション、CRLFインジェクション、LDAPインジェクション、XPathインジェクション、RCE、SSRF、バックドア、総当たり、HTTPフラッド、ボットの濫用も、同じアプリの経路で見る。中核機能には Web Access Control List があり、ウェブ攻撃への防御、ボット濫用への先回りした防御、HTMLとJSのコード暗号化、IP単位のレート制限と並ぶ。
具体的な誤設定と確認画面
保存済みに見えるのに試験が素通りするときは、ルール文より先に次の誤設定を疑う。
Applicationsにはアプリが1件あり、Domain、Port、Upstreamも入力済みである。しかしドメインの名前解決先が、SafeLineサーバのIPではなく、元のアプリケーションサーバのIPのままである。クライアントから見ればサイトは従来どおり応答する。WAFの許可も拒否も、その通信を見ていない。SQLインジェクションの試験文字列を送ってもブロックページは出ず、応答は元アプリそのものになる。画面上は追加済みなので、拒否が弱い、または試験ペイロードが古い、と誤解しやすい。
直し方は、名前解決先だけをSafeLineサーバのIPへ変更し、Upstreamは元アプリの実アドレスのまま維持することである。待受のPortは、クライアントが実際に使う80または443と一致させる。HTTPSのアプリならSSLを有効にする。Upstreamへ、SafeLine自身へ解決される公開ドメインを入れない。プロキシの転送先が自分へ戻ると、安全な通信を元アプリへ渡す役割を果たせない。
修正を確認する画面は、ブラウザのブロックページである。名前解決を直したあと、同じドメインへ、文書化されたSQLインジェクションまたはパストラバーサルの試験を送る。ブラウザにブロックページが表示されれば、通信がリバースプロキシを通り、悪意のある要求が上流へ転送される前に除かれたと分かる。続けてApplicationsの画面を開き、対象が1件であること、Domainが試験に使った名前と一致すること、Portが待受と一致すること、Upstreamが元アプリの実アドレスであることを見る。ブロックページが出て、この4点が一致していれば、許可と拒否を評価できる土台に戻っている。
ブロックページは出るが、監視のヘルスチェックまで止まるなら、拒否が広すぎる。ヘルスチェックの送信元だけを許可へ戻し、悪意と確認済みのIP、範囲、ユーザーエージェントは拒否に残す。逆に、管理者ネットワークを必要以上に広く許可していると、その範囲から送った試験は拒否も攻撃防御も素通りしやすい。許可を監視、管理者、既知の静的パスへ絞り、拒否は観測済みの悪意へ戻してから、同じペイロードを再送する。再送でもブロックページが出ることを、修正の確認画面にする。
再試験の点検順
許可は、内部ネットワークやヘルスチェックのように、信頼できる送信元へアクセスを与える。拒否は、既知の悪いIPやパターンを止める。SafeLineはリバースプロキシなので、アプリへ届くのはWAFを通過した通信だけである。したがって、1つのアプリで最初に固定するのは、長い拒否一覧ではなく、通信がプロキシを通るという事実である。経路が正しければ、ブロックページが修正の確認画面になる。経路が誤っていれば、拒否を何件足しても元アプリは直接応答する。
再試験では次の順を崩さない。ホスト要件、コンソールへのログイン、アプリ1件、Domain、Port、Upstream、SSL、名前解決、許可の狭さ、拒否の根拠、レート制限、Captcha Challenge、Authentication Challenge、そしてブロックページ。別ドメインや別の上流の成功を、この1件の成功として流用しない。この順で見れば、許可と拒否が効かない原因を、文言の問題と、名前解決が元サーバのままという誤設定へ切り分けられる。
- Demo: https://demo.waf.chaitin.com:9443/statistics
- Official docs: https://docs.waf.chaitin.com/en/home
- GitHub: https://github.com/chaitin/SafeLine