PAC文件:智能代理配置的瑞士军刀
在日常上网和企业网络环境中,我们经常需要配置代理服务器来访问特定资源、增强安全性或管理网络流量。Windows和macOS系统自带的代理配置通常提供全局代理或简单的排除列表,这在某些复杂场景下显得不够灵活。例如,我们可能只想代理某个特定的IP网段,而其他所有流量都直接连接。这时,PAC (Proxy Auto-Configuration) 文件 就派上了大用场。
什么是PAC文件?
PAC文件本质上是一个包含特定JavaScript函数的文本文件。这个核心函数通常命名为 FindProxyForURL(url, host)
。当浏览器或操作系统配置为使用PAC文件时,每当需要发起一个网络请求(例如,访问一个网页或API),系统会首先调用这个 FindProxyForURL
函数,并将目标URL和主机名作为参数传递给它。
函数执行后,会根据其内部的逻辑返回一个字符串,告诉系统应该如何处理这个请求:
- 是通过某个特定的代理服务器?
- 是通过多个代理服务器(用于故障转移或负载均衡)?
- 还是直接连接,不经过任何代理?
PAC文件是如何工作的?
- 配置: 用户在操作系统或浏览器的网络设置中,指定一个PAC文件的URL地址。这个URL可以是指向本地文件系统中的文件 (如
file:///C:/path/to/proxy.pac
),也可以是指向一个网络服务器上的文件 (如http://internal.server/proxy.pac
)。 - 请求触发: 当应用程序(如浏览器)尝试访问一个URL时,它会将该URL和从中提取的主机名传递给
FindProxyForURL
函数。 - JavaScript逻辑执行: PAC文件中的JavaScript代码被执行。开发者可以在这个函数内部编写各种条件判断逻辑,例如:
- 判断目标主机名是否属于某个域名 (e.g.,
*.example.com
) - 判断目标主机的IP地址是否属于某个IP网段 (e.g.,
192.168.1.0/24
) - 判断目标URL是否包含特定路径或协议 (e.g.,
https://*
,*admin*
) - 判断当前时间或日期 (e.g., 只在工作时间使用代理)
- 判断目标主机名是否属于某个域名 (e.g.,
- 返回代理指令:
FindProxyForURL
函数必须返回一个特定格式的字符串,指示代理行为。
FindProxyForURL(url, host)
函数详解
url
: 完整的目标URL,例如 “http://www.example.com/index.html”。host
: 从URL中提取的主机名,例如 “www.example.com”。如果URL直接使用IP地址,则host就是该IP地址。
常见的返回值格式:
"DIRECT"
:
表示直接连接到目标服务器,不使用任何代理。return "DIRECT";
"PROXY proxy_host:proxy_port"
:
表示通过指定的HTTP代理服务器连接。例如:return "PROXY 192.168.1.100:8080";
"SOCKS proxy_host:proxy_port"
或"SOCKS5 proxy_host:proxy_port"
:
表示通过指定的SOCKS代理服务器连接。SOCKS5是更常用的版本。例如:return "SOCKS5 10.0.0.5:1080";
- 多个代理 (故障转移/负载均衡):
可以返回一个由分号分隔的代理列表。系统会尝试第一个,如果失败则尝试第二个,以此类推。DIRECT
也可以作为列表中的最后一项。return "PROXY proxy1.example.com:8080; PROXY proxy2.example.com:8081; DIRECT";
PAC文件中的实用JavaScript辅助函数
为了方便编写判断逻辑,PAC规范提供了一些内置的JavaScript辅助函数,可以在 FindProxyForURL
中使用:
isInNet(host, pattern, mask)
:
判断host
(可以是主机名或IP地址) 解析后的IP地址是否在由pattern
(网络地址) 和mask
(子网掩码) 定义的IP网段内。
例如:isInNet(host, "172.31.0.0", "255.255.0.0")
判断主机是否在172.31.0.0/16
网段。dnsResolve(host)
:
将主机名解析为其IP地址。如果解析失败,返回null
。
例如:var ip = dnsResolve("www.example.com");
shExpMatch(str, shexp)
:
判断字符串str
是否匹配shexp
(shell表达式,类似通配符)。
例如:shExpMatch(url, "*.example.com/*")
或shExpMatch(host, "intranet.*")
。isPlainHostName(host)
:
判断主机名是否为简单主机名 (即不包含任何点.
,例如 “localhost”, “mycomputer”)。dnsDomainIs(host, domain)
:
判断host
是否属于指定的domain
。
例如:dnsDomainIs("www.example.com", ".example.com")
返回true
。isResolvable(host)
:
判断主机名是否可以被DNS解析。weekdayRange()
,dateRange()
,timeRange()
:
用于基于日期和时间的条件判断。
创建PAC文件:一个实例(只代理特定网段)
回到最初的问题:只代理 172.31.0.0/16
网段,其他都不走代理。
下面是实现这个需求的PAC文件 (proxy.pac
) 内容:
function FindProxyForURL(url, host) {// 替换为代理服务器IP地址和端口var proxy_server = "YOUR_PROXY_IP_OR_HOSTNAME:YOUR_PROXY_PORT";// 判断目标主机是否在 172.31.0.0/16 网段// "172.31.0.0/16" 的网络地址是 "172.31.0.0",子网掩码是 "255.255.0.0"if (isInNet(host, "172.31.0.0", "255.255.0.0")) {// 如果目标在指定网段,则通过代理服务器return "PROXY " + proxy_server;}// 对于其他所有流量,都直接连接return "DIRECT";
}
使用步骤:
-
将上述代码保存到一个文本文件中,例如
proxy.pac
。 务必将YOUR_PROXY_IP_OR_HOSTNAME:YOUR_PROXY_PORT
替换成实际的代理服务器地址和端口 (例如10.0.0.1:8888
或myproxy.internal:3128
)。 -
在Windows上配置使用PAC文件:
- 打开 “设置” -> “网络和 Internet” -> “代理”。
- 关闭 “自动检测设置”。
- 打开 “使用设置脚本”。
- 在 “脚本地址” 处填入PAC文件的本地路径,格式为
file:///C:/path/to/your/proxy.pac
(请将C:/path/to/your/proxy.pac
替换为实际的文件路径,注意是三个斜杠///
和正斜杠/
)。 - 点击 “保存”。
-
在macOS上配置使用PAC文件:
- 打开 “系统设置” (System Settings) -> “网络” (Network)。
- 选择正在使用的网络连接(例如 Wi-Fi 或以太网)。
- 点击右下角的 “详细信息…” (Details…) 按钮。
- 在左侧选择 “代理” (Proxies)。
- 选择 “自动代理配置” (Automatic Proxy Configuration)。
- 在 “URL” 字段中填入PAC文件的本地路径,格式为
file:///Users/yourusername/path/to/your/proxy.pac
(请将/Users/yourusername/path/to/your/proxy.pac
替换为实际的文件路径,注意是三个斜杠///
)。 - 点击 “好” (OK),然后点击 “应用” (Apply)。
PAC文件的优势
- 灵活性高: 可以通过JavaScript编写复杂的逻辑,实现非常精细的代理规则。
- 集中管理: 如果将PAC文件部署在Web服务器上,所有客户端可以指向同一个URL。修改PAC文件即可统一更新所有客户端的代理行为,无需逐个修改客户端配置。
- 跨平台: Windows, macOS, Linux以及主流浏览器都支持PAC文件。
- 无需额外软件: 这是操作系统和浏览器内置的功能。
注意事项和调试技巧
- 语法错误: PAC文件是JavaScript,任何语法错误都会导致其失效。仔细检查括号、分号、引号等。
- 路径问题: 使用本地PAC文件时,
file:///
协议和正确的路径格式非常重要。 - 路径格式: file:/// 后面跟的是文件的绝对路径。Windows下盘符后的冒号要去掉,或者直接用正斜杠。例如 C:\Users\MyUser\Documents\proxy.pac 应该写成 file:///C:/Users/MyUser/Documents/proxy.pac。
- DNS依赖: 很多判断(如
isInNet
)依赖于DNS解析。如果DNS解析有问题,PAC规则可能不会按预期工作。 - 缓存: 浏览器和操作系统可能会缓存PAC文件。修改后,可能需要清除缓存、重启浏览器或网络服务,甚至重启系统才能使更改生效。
- 调试:
- 在PAC文件中使用
alert()
函数 (例如alert("Host: " + host + " is going DIRECT");
) 可以帮助调试。但请注意,这些弹窗会打断正常浏览,调试完成后务必移除。 - 某些浏览器开发者工具(如Firefox)提供PAC文件调试功能。
- 检查代理服务器的日志,看请求是否如预期那样通过代理。
- 在PAC文件中使用
总结
PAC文件是一个强大而灵活的工具,它通过简单的JavaScript脚本实现了智能化的代理路由决策。对于需要根据目标URL、主机名、IP网段等条件动态选择代理方式的场景,PAC文件提供了一个轻量级且无需额外软件的解决方案。理解了它的基本原理和常用函数后,就可以根据自己的需求定制出各种复杂的代理规则了。