トンネルは自宅回線から接続し、ホテルやオフィスのネットワークで止まります。サーバーをポート 443 に移しても何も変わりませんでした。この結果はよくあることで、形があります。ポートは簡単な部分で、判断の残りはクライアントとサーバーの間に座っているすべてのものに属します。ほとんどの場合は二つの問いで決まり、どちらも暗号の話ではありません。ネットワークはそのアドレスへの TLS ハンドシェイクを受け入れるか、トンネルが上がっている間クライアントは自分のラッパーへの経路を保つか。

ハンドシェイクは番号より多くを明かす

TCP 443 上のネイティブな VPN リスナーは、最初のパケットから独自のプロトコルで話します。ClientHello にはバージョンフィールド、ランダム値、拡張のリストがあり、数百バイトを読む機器なら何も復号せずに違いを見分けられます。ポート番号は安く満たせますが、フィルターが実際に確認するのはプロトコルの形です。規則は通常プロトコルごとにも書かれるので、TLS を検査するポリシーは UDP について何も語りません。

有効な TLS セッションを要求する透過プロキシは、多くの場合 TCP ハンドシェイクが完了した後に、セットアップの途中で接続を落とします。この細部は後で効きます。ソケットが確立した後にクライアントのログが止まるからです。

ストリームを包むと二つの故障点ができる

stunnel のような TLS ラッパーは期待される形を戻します。クライアントはローカルのリスナーに接続し、ラッパーが 443 でサーバーへの本物の TLS セッションを開き、サーバー側の二つ目のラッパーが復号したバイトを VPN デーモンへ転送します。外側のセッションは今や他のどの HTTPS 接続にも見えます。サーバーの VPN デーモンは loopback だけで待ち受けるべきです。ラッパーの外側から到達する必要は何もないからです。

この設計には三つの別々のことが揃わなければなりません。クライアントプロファイルがローカルのリスナーを指し、サーバー証明書がクライアントの検証する名前と一致し、サーバー側の転送がデーモンの実際に使うポートを狙っていることです。どれか一つでも誤れば、VPN 層に届く前に接続は死にます。すると証明書の不一致は VPN のエラーではなくラッパーのエラーとして現れます。だからこそ両方のログを並べて読む価値があります。

ラッパーへの経路が罠になる

トンネルが上がると既定ルートはその中を指し、外側の TLS セッションには自分が運ぶトンネルに入らない経路が必要です。通常の VPN クライアントは自分が発信するアドレスを保護しますが、ラップされたクライアントは自分の loopback に発信するので、ラッパーの宛先アドレスはその保護から見えません。

sudo ip route add 198.51.100.20 via 192.168.0.1
sudo openvpn --config client.ovpn
sudo ip route del 198.51.100.20

正確なアドレスは自分で埋めてください。経路は起動時だけでなく、接続の存続中ずっと存在しなければなりません。クライアントの前に経路を追加し、後で削除する小さなラッパースクリプトのほうが、覚えたコマンドより確実です。

Android では、その例外に相当するのはアプリごとの設定です。ラッパーのアプリをトンネルから除外し、自身の通信がモバイル接続から出るようにします。除外しなければ、ラッパーは自分が作ろうとしているトンネルへ経路付けされ、再接続のループはサーバーの問題のように見えます。

何かを変える前にタイミングを読む

毎回同じ間隔で死ぬセッションは暗号の失敗ではなくポリシーの署名であり、長時間のフロー制限はまさにそのパターンを生みます。ハンドシェイクの直後にリセットされる接続は、証明書チェーンを好まなかったプロキシを示唆します。

両方のネットワークから、普通の HTTPS サイトの証明書の発行者を比べてください。制限されたネットワークで発行者が違うなら、何かが途中で TLS を終端しています。その傍受を変えずに生き延びるラッパーはありません。同じ比較で、遮断があなたのサーバー名を狙うのか、そのアドレスのすべての TLS セッションを狙うのかが分かります。

観察した挙動を書き留めてください。セッションがどれだけ続いたか、ソケットが開いたか、ラッパーがハンドシェイクを記録したか。どれも次のテストを狭めます。

一度に一つの変数だけ試す

まず UDP を確認してください。一部のネットワークはそれを完全に落とし、UDP の失敗は 443 について何も語らないからです。次にラッパーなしの TCP 443、その次に 443 上のラッパーを試します。各段階でクライアントのログを読み、挙動が変わったらすぐ止めてください。

一度に一つの要素だけ変えてください。新しいポート、新しいラッパー、新しい暗号を同じ実行で試すと、三つのどれが効いたのか言えなくなります。

関連記事