Chrome 拡張機能でのプロキシ検査には、応答を予測できる宛先が必要です。自分で制御する HTTPS エンドポイントを使います。たとえば、観測したアドレスを含む小さな JSON オブジェクトを返すものです。

リクエストは service worker や拡張機能ページなど拡張機能のコンテキストから実行し、エンドポイントを manifest の host permissions に含めます。

"host_permissions": ["https://probe.example/*"]

ホスト権限は content script に同じクロスオリジンの特権を与えるものではありません。注入されたスクリプトが同じリクエストを送れると仮定せず、検査は拡張機能のコンテキストに置いてください。

async function probe() {
  const controller = new AbortController();
  const timer = setTimeout(() => controller.abort(), 5000);
  try {
    const response = await fetch('https://probe.example/ip', {
      cache: 'no-store',
      signal: controller.signal,
    });
    if (!response.ok) throw new Error(`HTTP ${response.status}`);
    const result = await response.json();
    if (typeof result.ip !== 'string') throw new Error('Bad probe body');
    return result.ip;
  } finally {
    clearTimeout(timer);
  }
}

ホスト名はプレースホルダーです。サーバーとクライアントは応答の形式とキャッシュの方針について合意する必要があります。拒否されたリクエストや壊れた応答は拡張機能の呼び出し側で扱い、有効な出口アドレスとして表示しないでください。

観測結果を正確に名付ける

成功した結果が証明するのは、このリクエストがエンドポイントに到達し、想定どおりの形式の応答を得たことです。意味のある比較ができる場合は、観測したアドレスを意図した経路と比べてください。 設定されたプロキシの待ち受け IP は、その公開出口であるとは限りません。

PAC ルールやバイパスリストによって、別の宛先がプロキシを使う一方で検査が直接送られることがあります。 プロキシ設定を読むことは構成の証拠になります。リクエストはこの宛先についての証拠になります。どちらか一方だけでは、すべてのタブや URL が同じ経路を通ることを証明できません。

タイムアウト、HTTP エラー、想定外の本文を UI で区別してください。1 回のリクエストの後にマシン全体をオフラインと宣言するより、「この検査は失敗した」と示すほうが役に立ちます。

関連記事