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 错误和意外响应体区分开。一次请求之后就宣称整台机器离线,不如提示“本次探测失败”有用。

相关文章