ブラウザが HTTPS ページを読み込み、SSH クライアントが別のサーバーに到達し、リゾルバーが問い合わせに答える——そのすべてが一つの OpenVPN セッションを通る様子を想像してください。物理インターフェースでは対話が一つ見え、トンネルの内側では三つ見えます。どちらの見方も正しく、なぜそうなるかを知ることが、役に立つキャプチャと混乱するキャプチャの分かれ目です。内側のフローを一つ、ソケットから回線まで追えば、階層は抽象論ではなくなります。

外側の対話は一つ、内側のフローは多数

各アプリケーションは自分のソケットを開き、カーネルは送信元アドレス、送信元ポート、宛先アドレス、宛先ポート、プロトコルという五つの要素からなる組を与えます。この組は、どのトンネルが関与するよりも前から存在します。次にルーティングが、それらはすべてトンネルデバイスから出ると決めるので、OpenVPN に渡されるパケットは今も元のヘッダーを内側に抱いています。OpenVPN はその内側のパケットを暗号化し、結果をピアとの単一の外側 UDP または TCP 対話に包みます。したがって外側の対話は一つであり、その内側のフローはアプリケーションが開いた数だけあります。

何も潰れません。内側の組は端から端まで残り、だからこそ遠い側は今も三つのフローを見分けられます。

固定されたままのポート

一定なのは外側の組で、それはあなたのアドレス、クライアントが束ねたローカルポート、ピアのアドレス、そして設定されたサービスポートです。経路上のファイアウォールや NAT が許可しなければならないのはこの組であり、上りリンクでのキャプチャが示すのもこれです。再接続やネットワーク切り替えの後に変わるのもこの組で、クライアントは別のローカルポートを束ねることがあります。トンネルが一つあるからといって、送信元ポートが永久に一つに固定されるわけではありません。

端点が気にするのは内側のポートです。HTTPS のフローは、外側のトランスポートが運用者の設定したポートに座っていても、トンネルの内側では宛先ポート 443 を保ちます。アプリケーションの端点は外側のポートを決して知りません。

遠端でのカプセル化解除が変えるもの

ピアでは外側の層が外れ、残るのは内側のパケットです。そこから先は、転送とアクセス方針が内側の宛先とプロトコルに適用されます。ウェブサーバーは今も HTTPS 接続を受け取り、SSH デーモンは今も SSH を受け取り、リゾルバーは今も問い合わせを受け取ります。

だからこそ、外側のトランスポートを許可する規則と、内部サービスを許可する規則は同じではありません。前者は経路を述べ、後者は認可を述べています。

外側が TCP なら流れは一つ、接続は一つではない

外側のトランスポートが UDP のとき、内側の各フローの運命は独立していて、失われたデータグラムはそれ自身の再送までの一つの転送に影響します。外側のトランスポートが TCP のとき、内側のすべてのフローは一つの信頼できるバイトストリームを共有します。

その共有ストリームこそが見落とされる部分です。回復はすべてに対して一度だけ起きるので、セグメントが一つ失われるだけで、内側で多重化されたすべてのアプリの通信が遅れます。端点では依然として多数の接続があり、回線の上では一つの接続があり、その回線の上に頭詰まりの効果が住んでいます。待ち受けポートの数はこのことについて何も語らず、だからこそポートを数えるのはトンネルの性能を考える方法としては貧弱です。

自分の構成を正確に説明する

機械がすべてを一つのポートから送ると言うのではなく、選んだ内側の通信と、それを運ぶ具体的な外側のトランスポートを名指ししてください。ローカルサービス、二つ目のトンネル、もう一方のアドレスファミリーはいずれも、この対話に入らないフローを作ります。上りリンクのキャプチャは外側の組を示し、トンネル内のキャプチャは内側の組を示します。

両方を取り、タイムスタンプを並べてください。どのアプリがどの内側フローを生んだかを示す必要があるなら、ポートをプロセスに直接対応づけるホストのソケット表のほうが優れた道具です。そのうえで、再接続後の次のキャプチャが別の数値を示すのは正当なことなので、観測した外側の組と観測した瞬間を書き留めてください。

関連記事