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 时,
url
取值: http://www.baidu.com/some/path/file.html ;host
取值: www.baidu.com 。
直接访问
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";
}