企業VPNの内側でアプリのリクエストだけが失敗し、ブラウザは動く
ブラウザはサイトを読み込むのに、アプリは壊れる。継承されたプロキシ、ポートポリシー、生のTCPリセット、ペイロードのサイズ上限の順にたどる。
ブラウザで社内ポータルを開くと読み込める。同じホストを呼ぶアプリを実行すると失敗し、どの層の話かも示さないメッセージが出る。トンネルはブラウザを運んでいるのだから、トンネルが最初の容疑者ではない。リクエストとサービスの間には四つのものが挟まり、それぞれ違う痕跡を残す。ここでは、VPNクライアントの設定画面ではなく、アプリが実際に送るリクエストから順にたどる。
アプリが実際に送るリクエストを見る
設定に触る前に、アプリに何をしているか言わせる。プロキシを明示的に切った状態での一回分の取得と、単純なポート疎通試験で、後の手順と比べる二本の基準線ができる。プロキシを切って成功するなら、四層のうち三層はもう片付いている。
env | grep -i proxy # Linux/macOS
netsh winhttp show proxy # Windows, machine-wide
curl -sv --noproxy '*' https://svc.internal/
nc -vz svc.internal 8080最後の二つを同じ宛先に対して実行し、どこで食い違うかを見る。動くブラウザと、動くcurlと、動かないアプリがそろえば、問題はアプリが付け加えるもの、つまりプロキシ、トランスポート、メッセージサイズのどれかに絞られる。
アプリは誰も設定していないプロキシを継承していた
ほとんどのHTTPスタックは、既定でOSからプロキシ設定を読む。企業のVPNクライアントはアクセスプロファイルの一部としてプロキシを入れることが多く、開発者がコードで一言も触れていないプロキシからリクエストが出ていく。.NETでは既定のハンドラがIE/WinHTTPの設定を読み、Javaは-Dhttp.proxyHostを読み、Nodeはライブラリが足すまでプロキシを内蔵しない。失敗はきれいな拒否になることは少なく、だから人はサーバーを見始める。
試験の費用は一回のリクエストだ。一つのハンドラでプロキシを明示的に切り、比べる。
var handler = new HttpClientHandler { UseProxy = false };
using var client = new HttpClient(handler);それで通るなら、直すべきはトンネルではなくアプリの設定だ。プロジェクト内の実行環境ごとに監査を繰り返す。それぞれ別の出所を読み、壊れているのは一つだけかもしれない。
選んだポートはポリシーが許すポートではない
経路のあるホストは、許可されたサービスではない。企業ポリシーは通常、外向きのウェブポートだけを許して残りを落とすので、8080や1883のサービスには届かないが、443は問題なく通る。ブラウザはここで何も証明しない。定義上443を使うからだ。
同じサービスを443の背後で公開し、例外を願い出る前に名前で到達する。例外が本当に必要なら、一つの送信元範囲と一つの宛先に限定し、誰かの個人的な抜け道ではなくサービスの定義の一部として扱う。
経路がリセットする生のTCP
長く生きる生のTCP接続は、最も不可解な形で失敗する層だ。ウェブの通信を許す経路でも、珍しい外向きTCPをリセットしたり書き換えたりでき、クライアントは障害のように読めるソケットエラーを報告する。メッセージングやイベントのサービスは、まさにこうした網のためにWebSocketのトランスポートを用意しており、切り替えはトンネルの変更ではなくクライアントの選択肢だ。
トランスポートを替え、もう一度試し、同じ実行の中で他は何も変えない。その一変数の試験が、リセットが経路から来たのかサービスから来たのかを教える。
大きなペイロードでだけ切れる接続
成功した直後、およそ一秒後に死ぬが、本文が大きいときだけ死ぬリクエストは、途中のどこかにあるサイズ上限を指している。メッセージのバイト数を数える中間装置は転送の途中で接続を落とせ、クライアントはタイムアウトではなく異常終了として報告する。
ペイロードをアプリ側で分割する。これはMTUの作業とは分けて考える。トンネルのパケットサイズを下げるのは、普通のTCPセッションが一定のバイト数で止まるときに効くが、中間装置が大きすぎるとみなすメッセージには何の効果もない。
四つを一度で見分ける方法
三つの観察でほとんどの場合は片付く。失敗は即座に起きるのか、大きな本文のときだけか。プロキシを切れば同じリクエストは通るか。ポートやトランスポートを替えると結果は変わるか。次の変更の前に答えを書いておく。企業VPNと継承したプロキシとアプリの既定値が重なれば、もっともらしい原因が三つ同時にそろう。
試験ごとに変数を一つに保ち、使った宛先ホストを記録する。その基準線がなければ、次に担当する人がまた四つの手順を最初から繰り返す。