社内サービスへの到達方法を三人のエンジニアに尋ねれば、Webプロキシ、SSHトンネル、あるいは完全なVPNという三つの設計が出てきます。どれも遠隔のサービスを手の届く場所に置けますし、どれも通信が別の場所から来たように見せられます。違いが表れるのは後になって、使っているプロトコルが選んだ道具の想定と違うときです。ブラウザでの簡単な確認を通過した設計が、その要求のきっかけとなったアプリケーションで日常的に失敗します。

決め手は二つの事実です。通過すべきプロトコルと、関係する名前を解決できる主体で、残りは好みです。

プロキシは理解できるものだけを運ぶ

Webプロキシは、自分のために作られたプロトコルを解析します。クライアントが要求を渡し、プロキシがそれを先へ渡すので、プロキシ設定のないアプリケーションはまったく関与しません。HTTPSではクライアントに不透明な経路が必要で、プロキシは要求を読むのではなくCONNECTを通じてそれを提供します。

SSHの動的転送はSOCKSを話すローカルポートを開き、そのポートがTCPストリームをクライアントの指定する任意の宛先へ中継します。TCP上のプロトコルはたいていこれで動きます。UDPは、道具が明示的に支援を加えない限り動きません。ローカル転送はさらに狭く、一つのローカルポートを一つの固定したホストとポートに写すもので、既知の単一サービスだけに役立ちます。

ssh -D 1080 user@bastion
ssh -L 8443:fileserver.internal:443 user@bastion

VPNはパケットを運びます。クライアントがトンネルへ向けたものはすべてそこを通り、UDPもICMPも含まれるので、単一の接続ではなくネットワークの要件に向いています。

誰かが名前を解決しなければならない

対象の名前が遠隔ネットワークのDNSにしか存在しない場合、問い合わせを行う機械がそのゾーンを見られなければなりません。Webプロキシは自分で問い合わせるので、ノートPCが名前をまったく解決できなくても、内部の名前はプロキシ経由で機能します。SOCKSも同じように振る舞えますが、クライアントが、すでに解決したアドレスへ接続するのではなく、名前をそのまま転送する場合に限ります。その選択はサーバーではなくクライアントにあります。

curlはこの分離を明確に示します。あるフラグはホスト名をプロキシへ渡し、別のフラグはまずローカルで解決するので、ローカル解決では内部にしかない名前がどのトンネルにも触れる前に失敗し、そのエラーは本当はDNSの判断だったものをプロキシのせいにします。

VPNは第三の道を取り、経路の隣に専用のリゾルバーと検索ドメインを設置します。それは便利で、応答しないリゾルバーとともに存在する経路が、パケットが向こう側に届いていても死んだトンネルとまったく同じに見えるという、見慣れた錯覚を生みます。

ネットワークが出口を一つしか許さないとき

多くの企業ネットワークは、外向きの接続を認証済みのWebプロキシ経由でしか許しません。 OpenVPNOpenVPNとSSHはどちらもそこで動かせ、前者は自身の輸送をプロキシ経由でトンネルし、後者は小さなCONNECT補助を走らせるプロキシコマンドを使います。

TCP上のトンネルはこの制約を生き延び、UDPベースのVPNは生き延びないので、自宅では動きオフィスでは失敗する設定が非常に多く生まれます。二つ目のコストは見落としやすく、プロキシ経由のTCP接続の中に運ばれるTCPトンネルは再送する層を二つ持つことになり、損失の下ではその組み合わせがどちらの層も単独では生まない形で止まります。

仲介者を連鎖させることは、層を選ぶこととは別の問いです。二つ目のプロキシやTorを加えると誰が何を観察するかが変わり、連鎖の中の位置がどのホップが暗号文を見るかを決めます。

順序はホップの数より重要です。外側のホップは暗号化された流れを見ますが、内側のホップはそれが運ぶ平文を見ます。だから連鎖は、最も不注意な環と同じだけしか私的ではありません。ホップをまたいでプロトコルを混ぜても自動的に良くなるわけではなく、たいていは障害の様式を考えにくくするだけです。

偽造したアドレスは選択肢の一つではない

他人の送信元アドレスでパケットを作っても役には立ちません。応答は本当の所有者へ向かい、ほとんどのネットワークはその通信をそのまま捨てるので、仲介者が必要なのは送信元をでっち上げられないからであり、それが三つの設計すべての正直な根拠です。

それは、どれが何を主張できるかの限界にもなります。特定のアドレスから発しているように見えるかは、そのアドレスがどこで正当に割り当てられ、誰が経路制御できるかという問いであって、どの道具がヘッダーを偽造できるかという問いではありません。設計が逆を前提にしていれば、その前提は最初にそれを絞り込む事業者で破綻します。前提を書き留めておけば、破綻が来たときに見分けられます。

プロトコルと名前で決める

一つのWebクライアントが一つのWebサービスを必要とし、プロキシ設定を持っているならプロキシを選びます。既知のTCPサービスがいくつかあれば足り、SSHアクセスがすでにあるならSSHトンネルを選びます。複数のアプリケーション、TCP以外の通信、専用DNS、再利用できる経路が要件の一部ならVPNを選びます。

そのうえで実際のクライアントと実際の名前で検証します。プロキシ経由でページを読み込んでもUDPについては何も分かりませんし、一つの道具をSOCKSで動かしてもシステムのリゾルバーについては何も分かりません。プロセスがどのローカルアドレスに結び付いたか、どのリゾルバーが答えたかを読み取ってください。それが、機能する経路と、一度だけ偶然機能した経路の違いです。

関連記事