文章目录
代理自动配置文件(PAC)文件
自动代理是平时一些场景会使用到的技术,如访问内网资源仅能通过某一台主机访问,那么就需要用到这个功能。自动配置可以让我们减少很多工作量,同时也会减少服务器转发的负载。
代理自动配置(PAC)文件是一个 JavaScript 脚本,其核心是一个 JavaScript 函数,用来决定网页浏览请求(HTTP、HTTPS,和 FTP)应当直连目标地址,还是被转发给一个网页代理服务器并通过代理连接。PAC 文件中的核心 JavaScript 函数通常是这样定义的:
function FindProxyForURL(url, host) {
// ...
}
语法
function FindProxyForURL(url, host)
参数
url
要访问的 URL。URL 中类似 https:// 这样的的路径和查询组件已被去除。在 Chrome 浏览器(版本 52 至 73)中,你可以通过设置 PacHttpsUrlStrippingEnabled 为 false 来禁止这种行为,或者以 –unsafe-pac-url 命令行参数启动(自 Chrome 74 起,仅命令行参数有效,且在 Chrome 75 及之后的版本中无法禁用这种行为;至于 Chrome 81,路径剥离对 HTTP URL 不适用,但有意改变这一行为以适应 HTTPS);在 Firefox 浏览器中,对应的选项是 network.proxy.autoconfig_url.include_path。
host
从 URL 中提取得到的主机名。这只是为了方便;它与 : / / 之后到第一个 : 或 / 之前的字符串相同。端口号不包括在此参数中,必要时可以自行从 URL 中提取。
描述
返回一个描述了代理设置的字符串。字符串的格式按照返回值格式进行定义。
返回值格式
FindProxyForURL() 函数返回一个字符串
如果那个字符串为空,则不使用任何代理
字符串中可以包含如下任意数量的“代理配置块”(building blocks),用分号分隔:
直连,不经过任何代理
DIRECT
HTTP 代理
PROXY host:port
SOCKS 代理
SOCKS host:port
最近版本的 Firefox 同时还支持:
HTTP 代理
HTTP host:port
HTTPS 代理
HTTPS host:port
SOCKS 代理(同时指定 SOCKS 版本)
SOCKS4 host:port
SOCKS5 host:port
如果有多个使用分号分隔的代理配置,将使用最左边的配置,除非 Firefox 无法与其中指定的代理服务器建立连接。在这种情况下,将使用下一个配置,等等。
30 分钟后,浏览器将自动重试之前没有响应的代理。下一次尝试则将在一小时后开始,再下一次是一个半小时。每次尝试后,间隔会增加 30 分钟。
如果所有代理都挂了,并且最后没有指定直连配置项(DIRECT),浏览器将询问是否应该暂时忽略代理,并尝试直接连接。20 分钟后,浏览器会再次询问是否应该重试代理,40 分钟后会再问一次。每次询问后,间隔会增加 20 分钟。
例子
PROXY 192.168.18.35:8080; PROXY 192.168.18.35:8081
主代理是 192.168.18.35:8080;如果它出现故障,则使用 192.168.18.35:8081,直到主代理恢复。
PROXY 192.168.18.35:8080; PROXY 192.168.18.35:8081; DIRECT
和上面的基本一样,但如果两个代理都挂了,则自动改为直连。
(在上面的例子中,Netscape 浏览器将询问用户是否要改用直接连接;在本例中,则不需要用户干预。)
PROXY 192.168.18.35:8080; SOCKS 192.168.18.35:808;
```shell
如果主代理出现问题,则使用 SOCKS 连接。
自动配置文件应当被保存为一个以 .pac 作为文件拓展名的文件,比如:
```shell
proxy.pac
其 MIME 类型应被设置为:
application/x-ns-proxy-autoconfig
接下来,你应当配置你的服务器,让文件拓展名 .pac 映射到如上所示的 MIME 类型。
备注: PAC 文件的 JavaScript 代码应该总是单独保存到 .pac 文件中,而不是嵌入到 HTML 文件或是任何其他文件之中。
本文档末尾的示例都是完整的,使用时不需要增加任何其它代码,直接保存应用即可。(当然,你需要改成你自己的域名/子域)
预定义的函数与环境
示例1 对关键域名进行代理
function FindProxyForURL(url, host) {
var proxy1 = "PROXY 192.168.18.60:808";
var proxy2 = "SOCKS 192.168.18.60:808";
var hostlist = "*google*";
var hostlist2 = "*youtube*";
// 本地地址直接连接
if (isPlainHostName(host)) {
return "DIRECT";
}
// Http
if (shExpMatch(url, hostlist)) {
return proxy1;
}
if (shExpMatch(url, hostlist2)) {
return proxy1;
}
// Socket
if (shExpMatch(url, hostlist)) {
return proxy2;
}
if (shExpMatch(url, hostlist2)) {
return proxy2;
}
return "DIRECT";
}
示例2 对除本地主机以外的所有连接使用代理
所有并非完全限定的主机名,以及在本地域内的主机名,都将直接连接。其他的会通过 xxx.xxx.xxx.xxx:8080 连接。如果代理不可用,则自动回退到直连。
function FindProxyForURL(url, host) {
if (isPlainHostName(host) || dnsDomainIs(host, ".aaronyang.cc")) {
return "DIRECT";
} else {
return "PROXY xxx.xxx.xxx.xxx:8080 ; DIRECT";
}
}
示例3 和例2一样,但是对防火墙外的本地服务器使用代理
如果有主机(例如生产环境中的 Web 服务器)属于本地域但在防火墙外,仅可通过代理访问,可以通过 localHostOrDomainIs() 来为上述主机添加例外:
function FindProxyForURL(url, host) {
if (
(isPlainHostName(host) || dnsDomainIs(host, "aaronyang.cc")) &&
!localHostOrDomainIs(host, "aaronyang.bb") &&
!localHostOrDoaminIs(host, "aaronyang.aa")
) {
return "DIRECT";
} else {
return "PROXY xxx.xxx.xxx.xxx:8080; DIRECT";
}
}
以上示例为 aaronyang.cc 域外所有主机使用代理,同时添加了例外使 aaronyang.bb 和 aaronyang.aa 也使用代理。
示例4 如果无法解析域名,则使用代理
这个示例可用于网络中的 DNS 服务器只解析内部主机名的情况,其功能是只对不能成功解析的域名使用代理。
function FindProxyForURL(url, host) {
if (isResolvable(host))
return "DIRECT";
else
return "PROXY xxx.xxx.xxx.xxx:8080";
}
以上代码每一次均会进行 DNS 查询,这可以通过添加其他一些规则,只在其他规则不能给出结果时进行 DNS 查询来解决:
function FindProxyForURL(url, host) {
if (
isPlainHostName(host) ||
dnsDomainIs(host, "114.114.114.114") ||
isResolvable(host)
) {
return "DIRECT";
} else {
return "PROXY xxx.xxx.xxx.xxx:8080";
}
}
加载pac文件
将上述改好的pac文件放在你的网站中,确保可以访问
https://xxx.xxx.xx.xx/proxy.pac
本文来自签署作者原创,站点有权对文章执行产权保护,转载请与作者沟通,并注明出处:http://61.174.243.28:13541/AY-knowledg-hub/%e9%80%9a%e8%bf%87pac%e6%96%87%e4%bb%b6%e9%85%8d%e7%bd%ae%e8%87%aa%e5%8a%a8%e4%bb%a3%e7%90%86/