ひとつのSSHセッション、ひとつのWebアプリ、ひとつの名前解決は、ポートを奪い合うことなくひとつのVPN接続を共有できます。クライアントはゲートウェイへの暗号化されたフローをひとつだけ構築し、アプリケーションの会話はすべてその中を流れます。外側では、トンネル自身のトランスポートとポートだけが見えます。内側では、各サービスが自分のポートを保ち、なおかつ自分の許可を必要とします。

外側のフローが運ぶものと、隠すもの

クライアントは、パケットがマシンを離れる前に、トンネルのトランスポートで包みます。その外側のフローには宛先ポートがひとつだけあり、VPNの設定時に固定されます。包みの内側では、元の各パケットが対象サービスのアドレスとポートを保ちます。ゲートウェイは包みを外して内側のヘッダーでルーティングするため、宛先にはネットワークから到着する普通のクライアントが見えます。

したがって、WANインターフェースでのキャプチャには会話がひとつだけ映り、三つではありません。内側のポートはカプセル化を解除した後にだけ現れます。だからこそ、ファイアウォールの開口部がひとつあれば、SSH、HTTPS、DNSを同時に運べます。

# WAN side: one outer tuple, whatever the inner services are
tcpdump -ni wan0 'udp port 443'
# tunnel side: the inner tuples appear after decapsulation
tcpdump -ni tun0

TUN/TAPのドキュメント は、ルーティングされたTUNデバイスがカーネルとユーザー空間のプロセスの間でIPパケットを受け渡す仕組みを説明しています。この受け渡しがあるからこそ、内側のヘッダーがゲートウェイのルーティングとファイアウォールのコードから見えるのです。また、外側のポートがどのサービスを許可しているかを何も語らない理由も説明しています。

NATの転送はリスナーに属し、アプリケーションには属しません

IPv4のNATの背後にある自己ホスト型ゲートウェイには、内向きの変換がひとつ必要です。公開アドレスとポートをVPNリスナーにマッピングします。トンネルの利用者が到達するからという理由だけで、SSH、HTTPS、DNSにルールが必要になるわけではありません。それらのポートを公開すれば、トンネルがすでに保護しているサービスを露出させてしまいます。転送ルールが表すのはリスナーの到達性であり、内側の何かに対する許可ではありません。

逆も成り立ちます。トンネルのポートを開いても他の何も露出しないため、トンネル経由でしか届かないサービスは公開表面を閉じたままにできます。この分離こそが、そもそもサービスを非公開に保つ理由です。

アクセスを実際に決めるのは内側のポリシーです

暗号化は経路を守りますが、宛先を許可するものではありません。クライアントのルートはどのプレフィックスがトンネルに入るかを選び、ゲートウェイの転送ポリシーはパケットがトンネルを出られるかを決め、宛先のファイアウォールとログインがサービスが応答するかを決めます。DNSが最も分かりやすい例です。問い合わせを運んでも、リゾルバーがあなたのクライアントプールからの問い合わせを受け入れるようになるわけではありません。各層は独立に「いいえ」と言えます。

トンネル経由で各サービスを個別に試してください。解決に成功してもWebポートについては何も分からず、Webリクエストに成功してもSSHについては何も分かりません。

dig @10.40.0.53 app.corp.example
nc -vz 10.40.0.10 8443
ssh -p 2222 [email protected]

トンネルが上がっているのにすべて失敗するときは、まずクライアントのルートテーブルを読んでください。ひとつのサービスだけ失敗して他が動くときは、障害はその宛先にあります。この二つの観察は別々の担当者を指しており、混ぜると時間を浪費します。

WireGuardも同じ線を引いています

WireGuardは外側のリスナーを ListenPort という名前で呼び、内側のアプリケーションは必要などんなサービスポートでも使います。 AllowedIPs はルーティングされたプレフィックスの集合であり、許可されたサービスポートの一覧ではありません。これをポートの許可リストとして読むと、トンネルの実際の動作と合わないルールが生まれます。名前は違いますが、層の分け方は同じです。

サービスがエンドポイント自体で動く場合はローカル入力ポリシーで、そのエンドポイントの背後にある場合は転送ポリシーで許可してください。この区別が、どのルールセットがパケットを見るかを決めます。

一般的な形は、ひとつの外側トランスポートと多数の内側の会話です。複数の外側のやり取りや別のIPプロトコルを必要とする製品は、単一公開ポートというパターンがこの設計を表すのであって、すべてのVPNを表すのではないことを思い出させてくれます。

関連記事