VPN をオンにすると localhost が動かない:名前か、プロキシか、バインドか
検索サフィックスやプロキシが介入すると、localhost は自分のマシンを指さなくなります。名前、次にルート、最後にツールの接続文字列の順に直します。
開発サーバーはほんの少し前まで応答していたのに、トンネルが上がった今では、一度も入力していないホスト名でリクエストがタイムアウトします。ほぼすべてのケースは二つの仕組みで説明でき、外から見ると両者は同じに見えます。検索サフィックスは短い名前を社内名に変え、プロキシは loopback の通信を到達できないホストへ送ります。この二つを切り分けるにはクエリ一回で足り、書きかけのファイアウォール規則を無駄にせずに済みます。
localhost が社内ゾーンに解決されるとき
トンネルが上がっている間に名前がどこへ解決されるかを調べ、次にトンネルを下ろして同じクエリを実行し、二つの答えを比べます。手がかりは、127.0.0.1 を期待した場所で社内レンジのアドレスが返ることです。localhost.mycompany.corp のようなレコードは、クライアントがそのサフィックスを検索リストに加えた時点で loopback の項目に勝ち、リクエストはそのポートで何も待ち受けていないプライベートなホストへ流れます。検索リストは推測せずに読み取ってください、クライアントは複数のドメインを追加でき、順序がどの候補を先に試すかを決めるからです:
getent hosts localhost
resolvectl domain
ss -ltnp | grep 8080
ホスト名を、アプリケーション、データベースクライアント、ノートブックの URL にあるリテラルアドレスへ置き換え、もう一度リクエストします。失敗が消えれば命名の問題で、トンネルは引き金にすぎませんでした。失敗が続くなら、待ち受け側かルートが次の容疑者で、名前は偽の手がかりでした。
loopback を横取りするプロキシ設定
トンネルが上がるときに適用されるシステムプロキシは、127.0.0.1 へのリクエストを受け取り、意図を理解していない遠隔プロキシへ転送します。除外リストが空だとローカルのリクエストが遠隔扱いになり、エラーメッセージがそう告げることはほとんどありません。loopback のアドレスを、単一のコマンドではなくセッション全体の除外リストに追加し、ネットワークについて結論を出す前にツールがそれに従うことを確認してください。
アプリケーションフレームワークは独自の環境変数や、時には独自の設定ファイルを読むため、一つのツールで機能する除外は次のツールでは何も証明しません。ブラウザーには癖があり、Chromium 系のブラウザーは loopback に対して暗黙にプロキシを迂回し、除外トークンがあるとその挙動が失われます。OS の設定がすべてだと決めつけず、実際のプロキシ判定を確認してください。シェルから起動したものについては、二つのコマンドで決着します:
curl --noproxy '*' http://127.0.0.1:8080/health
NO_PROXY=localhost,127.0.0.1,::1 your-tool
接続できる相手はバインドアドレスで決まる
127.0.0.1 で起動したサーバーはそのマシンからの接続しか受け付けず、開発ではたいていこれが正しい既定です。0.0.0.0 のサーバーは VPN アダプターを含むすべてのインターフェースで応答し、多くの人が意図するより広く露出します。リテラルの loopback アドレスが失敗するときは、まずバインドを確認してください。
待ち受けているソケットを見て、ポートだけでなく、どのアドレスに束縛されているかを記録します。別の端末やコンテナがトンネル越しにサービスへ届く必要があるなら、それが使う特定のインターフェースに束縛し、そのポートを意図的に許可します。自分のマシンだけが必要とするなら、狭いバインドを保ち、サーバーを広げるのではなくクライアントを直します。ポート転送やトンネルの層は両者を橋渡しできますが、どちらも後で個別のデバッグが要る部品を増やします。
デバッグツールが LAN を期待する場面
デバッグツールは、トンネルが静かに壊す前提を抱えています。スマートフォンのデバッグブリッジは、VPN が端末のサブネットを捕まえると端末を見失うため、LAN のアドレスやケーブルでつなぎ直せば衝突を避けられます。ブラウザー自動化のハブは、ハブがプロキシ経由でしか届かない場合や、ローカルのファイアウォールが制御ポートを落とす場合にタイムアウトします。リモートデバッガーは、クライアントがルートを書き換えた場所で昇格と loopback アドレスを要求することがあります。
制御ポートとデータポートは別々に特定してください、片方が生き残り、もう片方が死ぬことがよくあるからです。次に、修正がツールの設定に属するのか、そのサブネットのルートに属するのか、それとも スプリットトンネリングの規則 に属するのかを決めます。開発者ごとのマシンで hosts ファイルを編集するのは最もスケールせず、最初に忘れられます。プロファイルとともに生き、トンネルを持つ誰でも見直せる設定を選んでください。
最初に失敗した段階で止める
三段階を順にたどります、名前を解決し、リテラルアドレスへソケットを開き、最後にツール自身に接続させます。各段階が一層を排除するので、最初の失敗が直すべき層を名指しし、それ以降は未検証のまま残ります。何かを変える前に結果を書き留めてください、測定前に当てた修正は幸運と区別できないからです。最初の試行が失敗して再試行が通るなら、ツールの起動時にトンネルがまだ準備できていなかったのでしょう。
固定のスリープを、ルートを待つ上限付きの準備確認に置き換え、失敗した段階をログに残して、次に読む人がどこで止まったか分かるようにします。ひとりでに復旧するツールは直っていません、運が良かっただけで、その運は誰かのマシンで尽きます。トンネルは最後に、しかも実際に失敗した段階のためだけに変えてください。その順序は動くビルドへ戻る最短の道でもあります、関係していなかった部品を作り直さずに済むからです。