「ホストがこの PAC ファイルを使っているので、同じ URL を VM に入れた」というのはもっともな文であり、不完全な計画である。PAC URL が指すのはポリシースクリプトであり、プロキシではない。ゲストがそのスクリプトを取得し、ゲスト自身のアドレスで評価し、スクリプトが名指しするプロキシに到達できるようになるまで、URL は設定欄の文字列にすぎない。仮想マシンのプロキシポリシーをめぐる混乱の多くは、その一行を構成全体とみなすことから生じる。

PAC URL はスクリプトであり、プロキシではない

ファイルには、URL とホストを受け取り、プロキシの記述または DIRECT という語を返す関数が含まれている。URL のどこにも、アプリケーションにトラフィックをどこへ送るかを伝えるものはなく、その判断は実行時に、スクリプトの内部で、スクリプトがプラットフォームに要求するデータを使って行われる。PAC URL を受け付ける設定ダイアログは、判断手続きへのポインタを受け付けているのである。

この区別があるため、URL をコピーすると成功したように見えることがある。欄は埋まり、設定は保存され、失敗はあとになって、スクリプトを取得できないときや、ゲストが到達できないプロキシを返したときに初めて現れる。

四つの手順はそれぞれ違う形で失敗する

ゲストの内部では四つのことが順番に起こる必要があり、それぞれに独自のエラーの痕跡がある。ゲストが PAC ファイルを取得する。アプリケーションがローカル情報を使って、要求された URL に対するスクリプトを評価する。選択されたプロキシが解決され、到達される。プロキシが要求する場合は認証が行われる。

まず取得を証明することから始め、それがなければ後続のすべては無意味である。プライベートサーバー上の PAC ファイルは、どのルールも役立つ前にそのサーバーへの許可された経路を必要とし、到達不能なスクリプトの内部でのプロキシ選択は、それを取得する経路を作り出せない:

curl -sS -o /dev/null -w '%{http_code}\n' http://pac.corp.example/proxy.pac
getent hosts pac.corp.example

その要求がゲストからは失敗し、ホストからは成功するなら、問題はスクリプトの内容ではなく、ゲストから PAC サーバーへの経路にある。JavaScript ファイルが返ってくるなら、二番目の手順に進み、スクリプトがゲストの状況に対して何を判断するのかを突き止める。

同じスクリプトが VM の内部では違う判断をする

PAC 関数は、要求されたホストと、評価を実行しているマシンに関する情報を調べることができる。クライアント自身のアドレスに基づくルール、たとえばインターフェースアドレスやサブネットへの所属を確認するルールは、物理ホストのアドレスではなくゲストのアドレスを見ることになる。ホスト側 NAT の背後では両者は別のアドレスであり、したがって同じスクリプトが VM の内部で別のプロキシを選んだり、DIRECT に戻ったりしうる。

これはスクリプトの不具合ではない。スクリプトは書かれたとおりのことを、別の入力で行っているだけであり、それこそがホストはプロキシを使いゲストは直接接続するという不可解な報告を説明する。判断について論じるのではなく、アドレスと URL を受け取る PAC 評価器がディストリビューションに含まれていれば、それで再現して一つのコマンドで決着させる。そうでなければ、実際に使われるアプリケーションで試し、推測する代わりにそのプロキシログを読むこと。

ゲストがホストのプロキシ設定を引き継いだと結論してはいけない。ネットワーク変換はパケットを転送するだけで、アプリケーションの構成をコピーせず、システムプロキシはアプリケーションの構成である。

PAC をまったく読まないツール

コマンドラインツールは別の境界であり、ここで多くの時間が失われる。curl は PAC ファイルを実行しない、とプロキシのドキュメントが明言しているとおりである。プロキシ変数を PAC のダウンロード URL に向けても、スクリプトがプロキシの端点になるわけではなく、ツールは JavaScript ファイルと HTTP で話そうとして、ネットワークの問題のように見える形で失敗する。

同じことは、明示的なプロキシ変数または独自の構成だけを尊重する、多くのパッケージマネージャー、言語ランタイム、ビルドツールにも当てはまる。気にしているテストが CLI ツールなら、PAC スクリプトが選んだはずの具体的なプロキシで設定し、その選択をどう導いたかを記録して、次の人が再現できるようにする。

Linux のデスクトップアプリケーションでは、システム設定を自動モードにし、さらに URL も与える必要がある。モードが手動のまま保存された URL は何もしないので、両方をゲストの内部で確認する:

gsettings get org.gnome.system.proxy mode
gsettings get org.gnome.system.proxy autoconfig-url

DIRECT も判断である

PAC の結果が DIRECT であるというのは、アプリケーションが HTTP プロキシを迂回するという意味であり、ネットワークから抜け出したという意味ではない。出来上がった接続は、トンネルを通るオペレーティングシステムの経路に従うことも、プロキシの使用とは何の関係もない理由で失敗することもある。逆に、プロキシという結果は一つのアプリケーションの要求を表すものであり、ゲストのすべてのプロセスを表すものではない。

だから要件が書かれた方向で検証すること。要件が「このアプリケーションが社内サイトに到達する」であれば、そのアプリケーションが到達することを証明し、どのプロキシまたは経路が運んだのかを記録する。要件が「VM が社内ネットワーク上にある」であれば、選択されたプロキシ経由で動作するブラウザーはそのブラウザーの証拠であり、それ以上ではない。

テストを通すためにホストのトンネルを切ったり転送ポリシーを緩めたりするのではなく、ゲストの内部で連鎖を直すこと。連鎖には四つの環があり、その一つを飛ばす変更は、次にスクリプトが更新されるかゲストのアドレスが変わるまでしかもたない。

関連記事