名前付きVPNプロファイルが接続されている間だけ、サーバーの公開アドレスへのICMP echoを有効にするファイアウォール規則を想像してほしい。これは「トンネル経由のpingのみ」と読めてしまうが、その読みは重要な意味で誤りである。この規則は誰がホストに到達できるかを制限せず、別の接続がたまたま有効な間に公開インターフェースが何に応答するかを変えるだけだ。両者は別のポリシーであり、片方は静かに露出を広げる。

あなたが書いたと思っている規則

意図された要件はたいてい狭く、監視システムやVPN上の唯一の管理者がサーバーの生存を確認できることにある。文として書けばトンネル上のアクセス制御のように聞こえる。ファイアウォールのオブジェクトとして書くと公開プロファイル上の条件になり、echo要求が届くのはそこだからだ。

条件が送信元アドレスではなく接続状態になった時点で、許可される送信者の集合はVPNピアの集合ではなくなる。公開アドレスに到達できる者は誰でも、ゲートが開いている間はecho要求を送れる。トンネルは経路になったのではなく、スイッチになったのだ。

この考えを広める人々は、望んだ効果についてたいてい嘘をついていない。リンクが健全なときだけ応答する確認が必要で、リンクの健全性はVPN経由で観察するのが最も簡単だった。誤りは、可用性の信号をアクセス判断として扱い、その後で自動化してしまうことだ。

ゲートが実際に制御するもの

この設計は二つの独立したものを融合させており、それらを分離することが修正の大部分になる。一つ目は、どのローカルアドレス、どのリモートアドレス、どのプロトコル、どのICMP種別かという範囲である。二つ目は、規則オブジェクトが今この瞬間に有効かどうかという条件である。範囲はファイアウォールがパケットごとに評価するもので、条件はスクリプトがポリシーストアに書き込むものであり、両者はまったく別の時計で突き合わされる。

要件が本当にVPNピアだけであれば、範囲だけで接続状態のロジックなしに答えられ、規則をトンネルインターフェースかトンネルのアドレス範囲に結びつけ、リモートアドレスをクライアントプールに限定し、「ICMP」ではなくecho種別を指定すればよい。その規則はVPNが一つも上がっていなくても正しく、無関係なプロファイルで開くことはできない。

要件が本当に公開ゲートなのであれば、受け入れ基準が変わるから、ポリシーの文章にそう書くべきだ。公開ゲートは正確なプロファイルを名指しし、「接続済み」の意味を定義し、公開の送信者が設計上範囲内にあると明記しなければならない。誰かがその一文を書かざるを得ない瞬間に、混乱の大半は消える。

オブジェクトを一度作り、あとは切り替える

安定した識別子を持つ一つの規則を無効状態で事前に用意し、コントローラーには有効状態だけを変えさせる。実行のたびに表示名で規則を作るのが、ポリシーストアがほぼ同一の五つのオブジェクトを抱え、確実に削除する手段を失う経路である。

New-NetFirewallRule -Name "VpnGateEchoV4" -DisplayName "Public echo gated on VPN state" -Direction Inbound -Action Allow -Protocol ICMPv4 -IcmpType 8 -LocalAddress 203.0.113.10 -RemoteAddress Any -Enabled False
Set-NetFirewallRule -Name "VpnGateEchoV4" -Enabled True

名前は永続的な識別子であり、表示名は人間が編集してよい文書である。-Name で突き合わせれば、スクリプトは重複を作らなくなる。同じコマンドの形で IPv6 の場合は -Protocol ICMPv6 -IcmpType 128 を伴うが、echo種別の番号が二つのファミリーで異なるため、これは別の規則になる。

アドレスファミリーとICMP種別を明示する二つ目の理由は、-Protocol ICMPv4 が種別を欠くと、プロファイルが許すすべてのICMPv4メッセージを許可してしまい、受け入れるつもりのなかったものまで含まれることだ。種別8を名指しすれば規則はecho要求に絞られ、到達性の確認が送るのはそれだけである。

自動化が意図と矛盾する場所

数分おきにクライアントプロファイルを問い合わせても、即時の境界は作れない。接続が切れてから次の問い合わせまでの間、規則は公開アドレスで応答し続け、接続が上がってから次の問い合わせまでは応答しない。この遅れを認めるのは誠実だが、設計が厳密な不変条件を強制していると主張するのは誠実ではない。

状態確認そのものに範囲の罠がある。Get-VpnConnection はマシン上に構成されたクライアントプロファイルを、既定では現在のユーザー向けに、-AllUserConnection を付ければすべてのユーザー向けに報告するが、現在RRASサーバーにダイヤルインしているリモートユーザーは報告しない。それは別のコマンドレットによる別の観測だ。誤ったほうに基づいて作られたゲートは何にも接続されていない。

次に、前回の実行から規則がすでに有効なまま起動する場合、ゲートが開いている最中のコントローラーのクラッシュ、規則が生きているままプロファイルが削除される場合という、誰もスクリプトにしない状態を覆う。それぞれに定義された既定値が必要で、公開許可の安全な既定値は無効である。要件がどうしても問い合わせの窓を許せないなら、状態連動の規則は誤った道具であり、強制はトンネル側に属する。

最後に、公開の要求を二度、選択した接続が上がっている状態と下がっている状態で、VPN上にないホストから試す。トンネルの内側からのpingの成功はこのポリシーについて何も証明せず、それがほとんどの導入が飛ばしている測定である。

関連記事