アプリが表示するアドレスとサーバーが記録したアドレスが違う、どちらが嘘をついているのか、というサポートチケットが届きます。どちらも嘘ではなく、これは二つの異なるものの二つの観測です。インターフェースに結び付いたアドレス、ソケットに結び付いたアドレス、そしてリモートのサービスが見る送信元アドレスは、三つの別々の問いに答えます。VPN は電話にネットワークの文脈を加えるだけで、その三つを端末全体で一つの数字にまとめるわけではありません。アドレスを読む前に、チケットのフィールド名を読んでください。

チケットが通常説明していること

Wi-Fi につながり、トンネルが上がっている電話を想像してください。Wi-Fi インターフェースは LAN アドレスを持ち、トンネルのインターフェースは割り当てられた内部アドレスを持ち、トンネルから出ていく要求は、途中の変換を生き延びた送信元として公開サービスに届きます。内部アドレスを表示するアプリと、変換後の送信元を記録するサーバーは、どちらも正確に報告しており、この二つの値が一致することは決してありません。

三つの観測は、何を説明するかだけでなく、何を証明できるかでも異なります。

ObservationWhat it describesWhat it cannot prove
An address on a local interfaceOne configured attachment: Wi-Fi, cellular or a tunnelThe source a remote site receives
A socket's local endpointThe binding used by that one connectionThe address after translation further along
The peer address at a serviceWhat arrived at that observation pointAny other interface on the phone

ここでの混乱のほとんどは列の取り違えでありネットワークの障害ではないため、この表はこれらの値をチケットに埋めるコードのそばに置いてください。

ソケットの呼び出しが答えられること、答えられないこと

API のレベルでは、getsockname は現在特定のソケットに結び付いているローカルな端点を報告します。接続済みのソケットでは、それはカーネルがその接続のために選んだ送信元であり、どのインターフェース一覧よりもすでに具体的です。これは公開アドレスの検索ではなく、結び付いていないソケットで呼んでもほとんど何も分かりません。返す値は後で経路上で書き換えられる可能性があるため、サービスが何を受け取ったかについて権威があるのはサービス自身の観測だけです。

Apple のプラットフォームでは、インターフェース側に別の面があり、トンネルの設定はトンネルのインターフェースに割り当てられたアドレスを一覧します。それを読めばトンネルがどう構成されたかは分かりますが、どの要求がどの経路を通ったかは、経路制御とアプリごとの規則が接続ごとに決めるため分かりません。

分割トンネルはその隙間を目に見えるようにし、ある要求はトンネルから出ても、次の要求が別の宛先や別のアドレスファミリーに向かっていれば出ません。だから同じアプリの数秒違いの二つの結果が、正直でありながら異なることがあります。

問いに合う観測を選ぶ

すべてを計測するのではなく、意図して選んでください。バックエンドが見るものについては、バックエンド側で送信元を記録し、前にリバースプロキシがある場合は、クライアントのアドレスを、実際に配備が設定している転送ヘッダーから読み、クライアントが送ったものからは読みません。

トンネルが構成されているかどうかは、インターフェースを読んでください。このアプリの通信がそれを使ったかどうかは、そのアプリから自分が制御する宛先へ通信を送り、両端で送信元を比べてください。

アプリごとの規則には、それ自体の一文が必要です。ブラウザーの結果はそのブラウザーについての証拠であり、管理されたアプリごとのトンネルは、同じ電話の二つのアプリを同じ瞬間に別の経路に置くことがあります。適用範囲を確かめるとは、問題のアプリから、問題のアドレスファミリーで通信を送ることです。

インターフェース名は検出器ではない

インターフェース名を VPN の確認として使うのもやめてください。名前は公開された契約ではなく、電話が複数の接続を持ちながら、そのうち一つだけがあなたの要求を運ぶことがあります。

フィールドには、それが保持する観測の名前を付けてください。local_interface_address、socket_local_endpoint、service_observed_source は不格好で曖昧さがなく、一週間後に値がサポートチケットに載るときに欲しいのはその曖昧さのなさです。device IP という一つの列は三つすべてを集め、それを一つであるかのように信頼させてしまいます。

身元をアドレスの列から外に置く

共有された VPN の出口は利用者の身元ではなく、プライベートアドレスはアクセスの資格情報ではありません。どちらも人ではなく経路を説明しており、どちらかを認証として扱うと、経路制御の事故が認可の判断に変わってしまいます。

電話がどのアドレスを持っているかと聞かれたとき、役に立つ返事は、どの接続でどの観測者かという問いです。getsockname の定義は、ソケットの問いを決着させつつ残りの二つを決着させたふりをしないので、中間の場合に引用する価値があります。

そのうえで、三つのうち製品が実際に表示する必要があるのはどれかを書き出し、残りの二つは画面から削除してください。

関連記事