PAC文件写法

什么是PAC文件

代理自动配置(PAC)文件包含一组用JavaScript编码的规则,允许Web浏览器确定是将Web流量直接发送到Internet还是通过代理服务器发送。

PAC文件可以控制Web浏览器处理HTTP,HTTPS和FTP流量的方式。

当然! PAC文件以配置显式代理时当前不可能的方式提供灵活性和冗余。

使用PAC文件时可以利用许多好处:

  • 受所有主要操作系统和浏览器支持
  • 无论用户是输入域还是IP地址,都能够正确自动路由流量
  • 自动代理故障转移

到底PAC文件可以做什么

PAC文件可以具有利用以下信息来路由流量的规则:

  • 请求的网站的IP地址
  • 所请求网站的主机名
  • 用户IP地址
  • 日期/时间

此外,PAC文件可以路由:

  • Web浏览器中的HTTP,HTTPS和FTP流量
  • 直接或通过代理路由流量(主机名和端口可配置)

有什么限制

  • PAC文件在浏览器沙箱中运行,因此无法访问整个JavaScript编程语言环境。 相反,PAC文件功能是在具有自定义沙盒功能集的浏览器中实现的。
  • 无法访问计算机主机名
  • 没有可靠的方法来确定用户IP地址
  • 代理故障转移缺乏智能,只能通过发生的TCP超时进行操作

PAC文件样例

所有优秀PAC文件的基础都以清晰简洁的编码方法开始。 使用几种不同的方法可以实现相同的结果,包括可用的PAC文件功能和JavaScript语言的灵活性。

此页面包含一个PAC文件示例,该示例已被证明具有灵活性,易于更新,同时仍能提供准确的结果。

特点:

  • 专用IP网络,内部主机名和具有.local域扩展名的主机的代理绕过规则。
  • 示例主机名绕过规则。
  • 示例协议和URL绕过规则。
  • 示例基于机器的IP路由规则。
  • 默认代理规则,如果以上所有规则都不匹配。

    示例

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
     function FindProxyForURL(url, host) {

    // If the hostname matches, send direct.
    if (dnsDomainIs(host, "intranet.domain.com") ||
    shExpMatch(host, "(*.abcdomain.com|abcdomain.com)"))
    return "DIRECT";

    // If the protocol or URL matches, send direct.
    if (url.substring(0, 4)=="ftp:" ||
    shExpMatch(url, "http://abcdomain.com/folder/*"))
    return "DIRECT";

    // If the requested website is hosted within the internal network, send direct.
    if (isPlainHostName(host) ||
    shExpMatch(host, "*.local") ||
    isInNet(dnsResolve(host), "10.0.0.0", "255.0.0.0") ||
    isInNet(dnsResolve(host), "172.16.0.0", "255.240.0.0") ||
    isInNet(dnsResolve(host), "192.168.0.0", "255.255.0.0") ||
    isInNet(dnsResolve(host), "127.0.0.0", "255.255.255.0"))
    return "DIRECT";

    // If the IP address of the local machine is within a defined
    // subnet, send to a specific proxy.
    if (isInNet(myIpAddress(), "10.10.5.0", "255.255.255.0"))
    return "PROXY 1.2.3.4:8080";

    // DEFAULT RULE: All other traffic, use below proxies, in fail-over order.
    return "PROXY 4.5.6.7:8080; PROXY 7.8.9.10:8080";

    }

注意
以下代码是一个示例,由于对使用shExpMatch函数,通配符和主机名的广泛解释,可能会产生意想不到的后果。

警示样例

1
2
3
4
5
// Would send both of the following requests direct to the Internet:
// 1. www.hotmail.com 2. phishing-scam.com?email=someone@hotmail.com

if (shExpMatch(url, "*hotmail.com*"))
return "DIRECT";

安全的样例

1
2
if (shExpMatch(host, "*.hotmail.com"))
return "DIRECT";

示例2

1
2
3
4
5
6
function FindProxyForURL(url, host) {
if (shExpMatch(url, "*.google.com/*")) {
return "PROXY 127.0.0.1:1080";
}
return "DIRECT";
}

FindProxyForURL的返回格式

上面也可以看出来部分了,返回一个单个字符串
可以包含下面方式:

  • DIRECT
  • PROXY host:prot
  • SOCKS host:port
  • HTTP host:port
  • HTTPS host:port

主要函数

下面是浏览器沙箱面已经实现的可以调用的函数

  • dnsDomainIs
  • shExpMatch
  • isInNet
  • myIpAddress
  • dnsResolve
  • isPlainHostName
  • localHostOrDomainIs
  • isResolvable
  • dnsDomainLeveIs
  • weekdayRange
  • dateRange
  • alert

代码片段

本地网络匹配

1
2
3
4
5
6
7
8
if (isPlainHostName(host) ||
shExpMatch(host, "*.local") ||
isInNet(dnsResolve(host), "10.0.0.0", "255.0.0.0") ||
isInNet(dnsResolve(host), "172.16.0.0", "255.240.0.0") ||
isInNet(dnsResolve(host), "192.168.0.0", "255.255.0.0") ||
isInNet(dnsResolve(host), "173.37.0.0", "255.255.0.0") ||
isInNet(dnsResolve(host), "127.0.0.0", "255.255.255.0"))
return "DIRECT";

指定主机名匹配

1
2
if (dnsDomainIs(host, "abcdomain.com") || dnsDomainIs(host, "www.abcdomain.com"))
return "DIRECT";

URL匹配

1
2
if (shExpMatch(url, "http://abcdomain.com/folder/*"))
return "DIRECT";

指定协议匹配

1
2
3
4
5
6
// HTTP
if (url.substring(0,5)=="http:") return "DIRECT";
// HTTPS
if (url.substring(0,6)=="https:") return "DIRECT";
// FTP
if (url.substring(0,4)=="ftp:") return "DIRECT";

基于机器 IP的路由规则

1
2
if (isInNet(myIpAddress(), "10.10.5.0", "255.255.255.0"))
return "PROXY 1.2.3.4:8080";

总结

PAC文件就是一个系统HOOK,用js实现FindProxyForURL,可以决定地址的路由。但只能用沙箱中的指定函数。

相关参考