proxy pac intro - downgoon/hello-world GitHub Wiki

FindProxyForURL 回调函数

PAC (Proxy Auto Configure) 文件本质上是一段 javascript 代码。浏览器在访问一个URL时,会“回调”一个函数,这个函数就是 FindProxyForURL(url, host)

所以PAC文件至少得有FindProxyForURL(url, host)函数。

当浏览器访问 http://www.baidu.com/some/path/file.html 时,

直接访问

function FindProxyForURL(url, host) { return "DIRECT"; }

一个代理

function FindProxyForURL(url, host) { return "PROXY 192.168.1.1:3128"; }

多个代理与不同类型代理

function FindProxyForURL(url, host)  { 
     return "DIRECT; PROXY 192.168.1.1:3128; SOCKS5 lilinux.net:1080"; 
}

注意

  • 形如 PROXY 192.168.1.1:3128 的是HTTP代理;
  • 形如 SOCKS5 lilinux.net:1080 的是SOCK5代理。

内置工具函数

参考文档:http://findproxyforurl.com/pac-functions/

为什么需要内置一些函数呢 ? 设计PAC文件的人非常聪明,思考非常完备。他思考了下,我们平时什么情况下走代理,什么情况下不走,什么情况下走哪个代理,他概括了3个维度:

  • 时间:比如上班时间,走公司代理;下班时间走家里的代理或者不走代理。

  • 空间:当我在公司办公室时,走公司代理;当我在家时,不走代码。如何判断我在家里,还是在公司呢?myIpAddress() 函数,一般公司的网络是 10.X.X.X 的,家里的网络是 192.168.X.X 的。

  • 站点:当我访问国内站点,则不走代理;当我访问国外站点,比如github时,就走代理。

用于调试的函数 alert

alert The alert() function is not specified in the original PAC specification, although support was previously supported in several browsers, useful for outputting the value of a variable or result of a function in a manner that is viewable by the end-user and leveraged for troubleshooting PAC file rule issues.

// Outputs the resolved IP address of the host in the browser
// to end-user or error console. 
 
resolved_host = dnsResolve(host);
alert(resolved_host);

dnsDomainIs

Evaluates hostnames and returns true if hostnames match. Used mainly to match and exception individual hostnames.

// If the hostname matches google.com or www.google.com
// send direct to the Internet.
 
if (dnsDomainIs(host, "google.com") || dnsDomainIs(host, "www.google.com"))
    return "DIRECT";

shExpMatch

Will attempt to match hostname or URL to a specified shell expression (Linux Regex NOT PERL), and returns true if matched.

  • Example 1
// Any requests with a hostname ending with the extension .local
// will be sent direct to the Internet.
 
if (shExpMatch(host, "*.local")) {
  return "DIRECT";
}
  • Example 2
// A request for the host vpn.domain.com or any request for a file or folder in the
// location http://abcdomain.com/folder/ will be sent direct to the Internet.
 
if (shExpMatch(host, "vpn.domain.com") ||
    shExpMatch(url, "http://abcdomain.com/folder/*")) {
  return "DIRECT";
}

IP相关的三个函数:myIpAddress, dnsResolve 和 isInNet

  • myIpAddress: PAC文件运行所在的机器

  • dnsResolve: 依据host反解出IP

  • isInNet: 判断给定IP参数是否落于某个IP段

  • 内网直接访问


// If IP of the requested host falls within any of the ranges specified, send direct.
 
if (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";

内网IP段,直接访问,几乎是“翻墙软件的标配”。

isPlainHostName


// If user requests plain hostnames, e.g. http://intranet/, 
// http://webserver-name01/, send direct.
 
if (isPlainHostName(host)) {
	return "DIRECT";
}

时间相关函数

  • weekdayRange

// If during the period of Monday to Friday, proxy1.example.com will be returned, otherwise
// users will go direct for any day outside this period.
 
if (weekdayRange("MON", "FRI"))  {
   return "PROXY proxy1.example.com:8080";
} else {
  return "DIRECT";
}
  • dateRange

if (dateRange("JAN", "MAR")) {
  return "PROXY proxy1.example.com:8080";
} else {
  return "DIRECT";
}
     
  • timeRange

// If during the period 8am to 6pm, proxy1.example.com will be returned, otherwise
// users will go direct for any time outside this period.
 
if (timeRange(8, 18)) return "PROXY proxy1.example.com:8080";
    else return "DIRECT";

样例

http://findproxyforurl.com/example-pac-file/

其他判断逻辑

当然我们也完全可以写JS普通语法来做判断:


if(/\.?blogspot\.\w{2}$/.test(h)||/\.google\.com\.\w{2}$/.test(h)
					|| /(google\.\w{2}$|google\.co\.\w{2}$)/.test(h)
					|| /rdio[^\.]*\.akamaihd\.net/.test(h)
					|| /.*rdio.com/.test(h)) {

		return "PROXY 188.77.9.1:10094";
}