结论先说: 不需要让整台电脑的所有网页都走静态住宅IP时,可以用 PAC(Proxy Auto-Configuration)按域名决定“走代理还是直连”。PAC 的核心是 FindProxyForURL(url, host):返回 PROXY host:port、SOCKS host:port 或 DIRECT。真正关键的不是会写一段 JavaScript,而是先确定敏感业务应“代理失败就阻断”还是“代理失败可直连”,并用测试矩阵证明规则没有泄漏。
什么场景适合 PAC 分流
- 海外业务后台走固定出口,国内办公、打印机和内网系统直连。
- 团队有多个业务域名,需要统一配置而不是逐台手工切换。
- 主代理维护时切到备用代理,但不希望用户自行修改网络设置。
- 希望减少不必要的代理带宽,并保留本地服务的正常访问。
PAC 主要为浏览器和遵循系统代理的应用决定 HTTP/HTTPS 等请求路径,不是全设备 VPN,也不会接管所有 TCP/UDP 流量。游戏、命令行、自带网络栈的应用可能不读取 PAC,必须单独验证。
PAC 最小可用结构
下面只让两个示例业务域名走代理,其他请求直连。把域名和代理地址替换成自己的合法业务信息,PAC 文件中不要写用户名和密码。
function FindProxyForURL(url, host) {
if (
host === "portal.example.com" ||
dnsDomainIs(host, ".portal.example.com") ||
host === "api.example.net" ||
dnsDomainIs(host, ".api.example.net")
) {
return "PROXY proxy.example.net:3128";
}
return "DIRECT";
}
host === "example.com" 用于匹配根域名,dnsDomainIs(host, ".example.com") 用于匹配子域。两者一起写可以避免只匹配子域、漏掉根域。
MDN 文档说明,PAC 对 HTTPS URL 通常不能依赖路径和查询参数;现代 Chromium 会剥离 HTTPS URL 的 path/query 后再交给 PAC。换句话说,“同一域名的 /admin 走代理,/public 直连”不是可靠的跨浏览器方案,应该按主机名设计分流。
直连白名单怎么写才不会过宽
内部主机、回环地址和明确的公司域名可以直连:
function FindProxyForURL(url, host) {
if (
isPlainHostName(host) ||
host === "localhost" ||
shExpMatch(host, "127.*") ||
host === "intranet.example.local" ||
dnsDomainIs(host, ".intranet.example.local")
) {
return "DIRECT";
}
if (
host === "portal.example.com" ||
dnsDomainIs(host, ".portal.example.com")
) {
return "PROXY proxy.example.net:3128";
}
return "DIRECT";
}
不要为了省事写一个能匹配大量无关域名的通配符。域名后缀规则要包含前导点并单独处理根域,避免 badexample.com 误匹配 example.com。修改前列出预期走代理和预期直连的域名清单,规则才有验收依据。
PAC 中的 dnsResolve()、isResolvable()、isInNet() 会触发 DNS 查询,MDN 也提醒应谨慎使用。能用字符串匹配解决时,优先使用 host、dnsDomainIs() 和 shExpMatch(),减少额外 DNS 依赖和性能开销。
主备代理与两种故障策略
允许失败后直连(fail open)
return "PROXY primary.example.net:3128; " +
"PROXY backup.example.net:3128; DIRECT";
浏览器会依次尝试主代理、备用代理,最后直连。优点是代理全部故障时网页仍可能打开;风险是原本要求固定出口的业务会直接暴露本地出口。只适合对出口没有强制要求的低敏感网页。
代理失败就阻断(fail closed)
return "PROXY primary.example.net:3128; " +
"PROXY backup.example.net:3128";
不提供 DIRECT,两个代理都失败时请求失败。对必须保持固定出口、不能意外直连的业务,这通常更符合设计目标。代价是可用性依赖主备节点和告警,不能只配置后就不监控。
主备代理不应只是同一台机器的两个端口。若希望真正容灾,应确认两者的入口、出口、机房、上游和鉴权是否具有独立性,并在切换后重新核对出口 IP 与业务许可。
HTTP、SOCKS 与鉴权注意点
PAC 常见返回值包括:
PROXY proxy.example.net:3128
SOCKS proxy.example.net:1080
DIRECT
不同浏览器对 SOCKS、SOCKS4、SOCKS5、HTTPS 等扩展写法的支持并不完全一致。团队部署应以目标浏览器的官方文档和实测为准,避免把某个浏览器可用的写法当作通用标准。
PAC 文件只负责选择代理,不应该包含 user:password@host。用户名密码由浏览器的代理鉴权流程、操作系统凭据存储或企业身份系统处理;源 IP 白名单则在供应商侧配置。鉴权失败可查看代理IP白名单与账号密码鉴权对比和407错误排查指南。
如何部署 PAC
文件与响应头
- 文件名使用
.pac,内容只包含FindProxyForURL()等所需脚本。 - 通过受控的 HTTPS 地址发布,避免中途被篡改。
- Web 服务器返回
application/x-ns-proxy-autoconfigMIME 类型。 - 设定清晰的版本、变更记录和适度缓存策略。
- 不在 PAC 中嵌入密码、Token、客户 ID 或内部敏感说明。
Windows 11
进入“设置” →“网络和 Internet” →“代理”,在“使用设置脚本”中填写 PAC URL。保存后重启目标浏览器并验证。Microsoft 支持文档确认 Windows 可以通过设置脚本使用自动代理配置。
macOS
进入“系统设置” →“网络” → 当前网络服务 →“详细信息” →“代理”,选择“自动代理配置”,填写 PAC URL。Apple 文档也提供 HTTP、HTTPS、SOCKS 和绕过列表设置。
如果设备由企业策略管理,应通过受控策略统一下发,而不是让每位成员从聊天记录复制 URL。撤销访问权限时也要同步清理策略、凭据和白名单。
还没有完成单机代理设置的团队,可先按Windows 11、macOS 与浏览器静态住宅IP配置指南完成基础连接,再引入 PAC 分流;否则很难区分是代理本身不可用,还是 PAC 规则没有命中。
上线前的验证矩阵
至少准备下表,并在 Edge、Chrome、Firefox 和关键业务应用中分别执行:
| 测试对象 | 预期路径 | 代理正常时 | 主代理故障时 | 主备均故障时 |
|---|---|---|---|---|
| 海外业务域名 | 代理 | 固定出口 A | 固定出口 B | 阻断或按批准策略直连 |
| 公司内网 | 直连 | 正常 | 正常 | 正常 |
| 普通公开网站 | 直连 | 本地出口 | 本地出口 | 本地出口 |
| 未列出的业务子域 | 明确指定 | 不允许“未知” | 不允许“未知” | 不允许“未知” |
验证方法包括:
- 在自有回显端点记录请求来源 IP。
- 在代理日志中确认目标域名有请求,直连域名没有请求。
- 暂停主代理,观察是否切换到备用节点。
- 暂停主备代理,确认 fail-open/fail-closed 与设计一致。
- 重启浏览器、切换 Wi‑Fi 后复测,排除旧连接和缓存影响。
只访问一次 IP 查询网站无法证明分流正确,因为不同域名可能匹配不同规则。必须按域名矩阵逐项验证。
常见配置错误
| 错误 | 结果 | 修复 |
|---|---|---|
| 只写子域规则,漏掉根域 | example.com 意外直连 |
根域和 .example.com 分开匹配 |
敏感业务末尾加 DIRECT |
代理故障时泄漏本地出口 | 改为 fail closed 或书面接受风险 |
| 在 PAC 中写明文密码 | 文件获取者得到凭据 | 从 PAC 删除,使用鉴权机制 |
| 按 HTTPS 路径分流 | Chromium 中规则不可靠 | 改为独立子域或主机名 |
| 使用大量 DNS 函数 | 变慢、增加 DNS 依赖 | 优先字符串与域名后缀匹配 |
| 只在一个浏览器测试 | 其他应用路径未知 | 建立应用×域名验证矩阵 |
变更与回滚清单
- 每次修改前保存旧 PAC 和文件哈希。
- 新版本先在一台测试设备验证,再分批发布。
- PAC 内写版本注释,外部维护变更单和负责人。
- 保留上一版本 URL 或可恢复副本,但不要长期公开历史凭据。
- 发现异常时立即恢复旧 PAC,重启浏览器,重新核对出口。
- 主备节点切换、鉴权变化和直连策略都应单独审批。
常见问题(FAQ)
PAC 能让所有软件都按规则走代理吗?
不能。只有读取系统或浏览器 PAC 的应用会遵循;自带网络栈、命令行、游戏和部分客户端可能忽略。
PAC 里可以写用户名和密码吗?
不建议也不应这样部署。PAC 可能被终端下载和缓存,凭据应交给浏览器鉴权、系统凭据或源 IP 白名单处理。
PROXY A; PROXY B; DIRECT 安全吗?
它能提高可用性,但两个代理都失败时会直连。对必须保持固定出口的业务,这属于泄漏风险,应去掉 DIRECT。
为什么不能按 HTTPS 的具体路径分流?
现代浏览器出于隐私原因通常不会把 HTTPS 的 path/query 完整交给 PAC。跨浏览器可靠方案应按域名或子域设计。
