当前位置: 首页 > news >正文

多代理混战?用 PAC(Proxy Auto-Config) 优雅切换代理场景

作者:龙际妙
标签:PAC / Whistle / VPN / 网络代理 / 开发效率

一、多代理的日常

作为一名前端/后端/测试工程师,你是否也面临这样的场景?

  • 科学上网需要开启 VPN(如 ClashX)
  • 开发联调时需要使用 Whistle 本地代理前后端环境
  • 抓包调试时习惯用 Charles、Fiddler、mimtproxy等其他代理工具
  • 浏览器插件(如 SwitchyOmega):按需切换代理配置

这些代理工具往往都通过“设置为系统代理”提供服务,虽然提升了使用便利性,但问题也随之而来:

👉 系统同一时间只能生效一个代理设置,多个代理同时开启时就容易互相“打架”。

笔者之前就遇到过这样的场景:

::: block-1
本地起了 Whistle(监听 8899 端口)进行工作开发,同时 ClashX 设置为系统代理科学上网。
在Chrome 里通过 SwitchyOmega 插件使网络请求走 Whistle,但是发现在Chrome浏览器里就无法再使用谷歌搜索,遇到这种问题大家也是八仙过海:

  • 1.Chrome只用来开发,再开一个浏览器(Edge)进行搜索

    这种方式多个浏览器互相切换成本高,多窗口来回切换极其浪费时间

  • 2.通过切换 SwitchyOmega 情景代理模式

    这种手动切换繁琐,容易忘记,给自己创造心智负担

  • 3.使用 SwitchyOmega 里的auto switch模式

    • 公司内网域名 → 走Whistle
    • 其他 → VPN

无需频繁切换,规则灵活,能满足大部分人的需求,但是SwitchyOmega 仅限当前浏览器生效,无法作用于其他浏览器和应用。

有没有更通用、统一且优雅的解决方案?有,那就是本篇的主角 —— PAC(Proxy Auto-Config)
:::

二、什么是 PAC?

PAC 全称是 Proxy Auto-Config,是浏览器和操作系统支持的一种自动代理规则机制。

就是一个 .pac 文件

其核心是一个 JavaScript 函数,用来决定网页浏览请求(HTTP、HTTPS,和 FTP)应当直连目标地址,还是被转发给一个代理服务器通过代理连接。

PAC 文件中的核心 JavaScript 函数通常是这样定义的:

function FindProxyForURL(url, host) {if (shExpMatch(host, "*.zhuanzhuan.com"))return "PROXY 127.0.0.1:8899"; // Whistleif (shExpMatch(host, "*.google.com"))return "PROXY 127.0.0.1:7890"; // Clashreturn "DIRECT";
}

每次访问网站时,浏览器或操作系统会调用这个函数,根据你访问的 URL 和 域名,返回一个指令:

是走某个代理(PROXY),还是直连(DIRECT)。

这就意味着:你可以根据目标网站,灵活指定走哪一个代理服务,而不用频繁切换配置。


谁支持 PAC?

SwitchyOmega可以直接通过新建PAC模式,通过网络地址加载文件或者本地编写脚本。

但是之前提到SwitchyOmega作为一个浏览器插件,它的代理作用域只有当前浏览器,像在其他的浏览器内和应用内的请求或者都是不起作用的。要想让 PAC 文件在系统级别生效,我们需要将它配置在操作系统的网络代理设置中:

以macOS为例:系统设置->Wi-Fi(当前连接WI-FI)->详细信息->代理

macOS只支持从服务器加载配置,Windows支持从本地加载和服务器远程加载文件。

三、实战案例:用 PAC 管理多个代理服务

下面这个示例,可以根据请求的域名自动选择合适的代理,而且PAC提供了容灾兜底机制,若无法与其中指定的代理服务器建立连接。在这种情况下,将使用下一个代理配置。

const DIRECT = 'DIRECT'; // 直接连接,不使用代理
const DEFAULT = 'PROXY 127.0.0.1:7890; DIRECT'; // 默认策略,走 ClashX 代理,若ClashX代理无法响应则自动改为直连
const WHISTLE = 'PROXY 127.0.0.1:8899'; // Web 开发用 Whistle 代理// 域名匹配规则(按顺序匹配,先匹配先生效)
const config = [{ proxy: DIRECT, pattern: /^::1$/ },              // 本地地址,不走代理{ proxy: DIRECT, pattern: /^127\.0\.0\.1$/ },      { proxy: DIRECT, pattern: /^localhost$/ },         { proxy: WHISTLE, pattern: /\.caihuoxia\.com$/ },   // 业务域名,走Whistle代理{ proxy: WHISTLE, pattern: /\.zhuanzhuan\.com$/ },{ proxy: WHISTLE, pattern: /\.example\.com$/ }
];function FindProxyForURL(url, host) {for (let i = 0; i < config.length; i++) {if (config[i].pattern.test(host)) {return config[i].proxy;}}return DEFAULT; // 未命中规则时走默认策略
}

如果你本地还启用了其他代理工具,也可以在 PAC 文件中为它们添加对应规则。你也可以根据自己的实际需求自由扩展配置,编写出适合自己开发环境的专属 PAC 文件。

此外,PAC 文件内置了一些实用方法(如 dnsDomainIs、shExpMatch、isInNet 等),可以帮助你实现更灵活的匹配逻辑,具体可参考官方文档。

📚 官方文档地址(复制打开):
https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Guides/Proxy_servers_and_tunneling/Proxy_Auto-Configuration_PAC_file#预定义的函数与环境

四、搭建本地服务器托管 PAC (支持热更新)

现在我们已经有了一个完善的 PAC 文件,接下来我们需要让它在 macOS 上“动”起来 —— 也就是将它托管在一个可访问的地址中。最简单的方式是本地搭建服务器,设置支持热更新,便于我们在开发中随时修改规则。当然也可以托管到远程服务器上访问。

在这里通过创建一个本地服务器来托管 .pac 文件。

✅ 示例代码(Node.js 实现)

const http = require('http');
const fs = require('fs');
const path = require('path');// === 配置 ===
const PAC_PATH = path.resolve(__dirname, './proxy.pac'); // PAC 文件的绝对路径
const PORT = 6001; // 本地服务器监听端口
const HOST = '127.0.0.1'; // 监听地址(仅本地)let pacContent = ''; // 缓存当前的 PAC 文件内容// === 初始化加载 PAC 文件 ===
function loadPACFile() {try {pacContent = fs.readFileSync(PAC_PATH, 'utf8'); // 读取 PAC 文件内容console.log(`[PAC] 已加载 PAC 文件:${PAC_PATH}`);} catch (err) {console.error('[PAC] 加载 PAC 文件失败:', err.message);}
}// === 监听 PAC 文件变更,实现热更新 ===
function watchPACFile() {fs.watch(PAC_PATH, (eventType) => {if (eventType === 'change') {console.log('[PAC] 检测到文件变化,重新加载...');loadPACFile();}});
}// === 启动 HTTP 服务,提供 PAC 文件 ===
function startServer() {http.createServer((req, res) => {if (req.url === '/proxy.pac') {// 请求路径为 /proxy.pac 时返回 PAC 内容res.writeHead(200, {'Content-Type': 'application/x-ns-proxy-autoconfig'});res.end(pacContent);console.log(`[PAC] 已响应 PAC 请求:${req.connection.remoteAddress}`);} else {// 其他路径返回 404res.writeHead(404, { 'Content-Type': 'text/plain' });res.end('Not Found');}}).listen(PORT, HOST, () => {console.log(`[PAC] 本地服务器已启动:http://${HOST}:${PORT}/proxy.pac`);});
}// === 主程序入口 ===
loadPACFile(); // 加载初始 PAC 内容
watchPACFile(); // 启动监听文件变化
startServer(); // 启动本地 HTTP 服务

这样,我们就完成了一个支持热更新的本地 PAC 服务,方便在开发过程中灵活修改和使用。如果有多个设备或需要远程共享,也可以将它托管到内网或公网服务器上,根据实际需求灵活调整即可。

五、总结

最终,我们通过编写 PAC 文件,配合本地 HTTP 服务进行托管,实现了按域名精确控制代理走向,不仅解决了多代理冲突的问题,也让代理配置更集中、统一、高效。

通过这种方式使用 PAC 的优雅之处:

  • 无需频繁手动切换:规则自动匹配,专注工作内容。
  • 系统级生效:不仅浏览器,连Postman以及其他等应用都能统一使用。
  • 动态返回代理地址:内部逻辑完全可控,可使用 JS 判断域名、路径甚至时间段。
  • 避免代理冲突:通过统一规则自动分流,多个代理工具协同工作更稳定。
  • 跨平台支持:macOS、Windows 都原生支持。

使用 PAC 不是简单的代理方式替换,更是一次开发效率和体验的提升。

http://www.lryc.cn/news/583091.html

相关文章:

  • 选哪个数据恢复软件?六款深度数据恢复软件介绍
  • 数据基础练习
  • 【Linux】权限的概念及理解
  • 进程于线程-3
  • 代码审计-springel表达式注入
  • JSP动态网页开发基础
  • 前后端集合如何传递
  • 主流大模型Agent框架 AutoGPT详解
  • thinkphp使用redis抢单实例
  • 如何将华为手机中的照片传输到电脑
  • 超越公有云:在裸金属服务器上构建低成本、高性能的静态资源服务
  • 【RK3568+PG2L50H开发板实验例程】FPGA部分 | Pango 的时钟资源——锁相环
  • 川翔云电脑:突破硬件极限,重构设计生产力范式
  • 使用DDR4控制器实现多通道数据读写(十九)
  • Amazon S3 对象存储服务深度解析:存储原理、应用场景与实战指南
  • 1.1 ARMv8/ARMv9安全扩展
  • ReactNative【实战】轮播图(含组件封装 ImageSlider)
  • 洛谷P1044 栈(学习向)
  • react16-react19都更新哪些内容?
  • clickhouse 各个引擎适用的场景
  • 【TCP/IP】2. 计算机网络与因特网体系结构
  • 手机文件夹隐藏工具,一键保护隐私
  • 数据库性能优化指南:解决ORDER BY导致的查询性能问题( SQL Server )
  • Dify 文本语意识别与自动补全工作流
  • MyBatisPlus-03-扩展功能
  • C#基础篇(11)泛型类与泛型方法详解
  • 1068.产品销售分析Ⅰ
  • huggingface 笔记: Trainer
  • 打造自己的组件库(二)CSS工程化方案
  • 跨服务sqlplus连接oracle数据库