アーキテクチャ
コントロールプレーンとデータプレーンの関係、gRPC が運ぶもの、ポリシーがエッジに届くまで。
PingWAF は 1 つのバイナリを共有する 2 つのプロセスに分かれます。コントロールプレーンがすべての状態を持ち、データプレーンがトラフィックを運びポリシーを適用します。データプレーンは独自のデータベースを持たず、持たせるべきでもありません。
コントロールプレーン
pingwaf server は 3 つの面を公開します。
| 面 | ポート | 用途 |
|---|---|---|
| REST API + コンソール | 9080(HTTPS) | サイト、ルール、ログ、設定バージョン |
gRPC ControlPlane | 9090 | エージェント登録、ハートビート、ルール同期、ログとメトリクス |
| PostgreSQL | 5432 | 唯一の永続ストア。ログ用途で Elasticsearch は任意 |
コンソールは rust-embed でバイナリに埋め込まれるため、API と同期させる独立したフロントエンドはありません。
データプレーン
pingwaf agent は :80 と :443 でトラフィックを受け、WAF ルールを評価し、TLS を終端してオリジンプールへ転送します。cache_dir にディスク上のルールキャッシュを保持し、キャッシュの設定ハッシュが変わると約 5 秒間隔でメモリ上のプロバイダを再構築します。リクエストは常に ArcSwap 経由で現在のプロバイダを読むため、ポリシー変更に再起動は不要です。
gRPC 契約
唯一の正解は pingwaf-proto/proto/control_plane.proto で、7 つの RPC から構成されます。
| RPC | 種別 | 用途 |
|---|---|---|
RegisterAgent | 単項 | フリートに参加。agent_id、agent_token、ハートビート間隔、初期設定を受け取る |
Heartbeat | 双方向ストリーム | 生存性・統計・証明書状態の上り、コマンドの下り |
SyncRules | サーバストリーム | 変更後に新しいルールバンドルを配信 |
ShipLogs | クライアントストリーム | リクエスト/攻撃ログの一括送信 |
ShipCertEvents | クライアントストリーム | ACME の発行・更新イベント |
ShipMetrics | クライアントストリーム | トラフィックとキャッシュのメトリクス |
GetSiteConfig | 単項 | 1 サイトの完全な設定を取得 |
同じサービスはチャレンジのための訪問者ログイン、パスキー、セッション検証も提供します。これらはエージェントトークンで認証され、コントロールプレーンに到達できない場合は拒否側に倒れます。
変更がエッジに届くまで
- REST の書き込みが設定を PostgreSQL に保存します。
- コントロールプレーンが対象スコープの設定スナップショットを記録します。
notify_config_changedが該当サイトを扱う各エージェントへ新しいSiteConfigを送ります。- エージェントはバンドルをキャッシュへ保存し、ハッシュ変化を検知してメモリ上で差し替えます。
障害時の挙動
fail_open はコントロールプレーンに接続できない場合の動作を決めます。true(既定)は最後に同期したポリシーで提供を継続し、false は同期済みルールのないホストに 503 を返します。サイト単位のポリシーがグローバル既定より優先され、設定として保存されます。
実行モード
| モード | コマンド | 役割 |
|---|---|---|
| コントロールプレーン | pingwaf server | API、gRPC、コンソール、データベース。トラフィックは転送しない |
| データプレーン | pingwaf agent | リモートのコントロールプレーンへ接続し :80/:443 で転送 |
| All-in-one | pingwaf all-in-one | 1 プロセスで両方を担当。エージェントはループバック接続 |
サブコマンドを省略した場合は PINGWAF_MODE で同じモードを選べます。
設定バージョン
変更はスコープ単位でバージョン管理されます。保持はスコープあたり最大 50 バージョン、30 日間、スナップショットは最大 2 MiB です。ロールバックはアドバイザリロックを取り、pre-rollback スナップショットを書いてから復元し、結果を新しいバージョンとして記録します。つまりロールバック自体も監査可能で、再度戻せます。