今天和一个朋友聊到了chrome的自动代理功能,很多人感觉这个功能非常方便,但大家或许不知道这个功能其实是继承自IE浏览器,而且在“遥远”的Windows 98时代IE就已经具有了这个功能。这个功能在IE中被称作Proxy Automatic Configuration简称PAC,这个功能在1996年由Netscape公司开发,随着被IE支持后成为一个业内统一标准。
那么我们在什么情况下需要用到PAC呢?简单的说就是我们需要对一部分网站需要用到特定的代理服务,比如我们公司的内部办公系统就需要用到一个公司的内部代理去访问,而这个代理又不能连接外网,这时候如果我们在访问这些网站时再手动设置代理就会非常麻烦。用PAC就会轻松得多。
PAC的配置方法非常简单,不需要安装任何软件或插件,只需用记事本建立一个脚步文件即可,我们可以把这个文件保存在硬盘的任何位置,也可以保存在服务器上,然后打开Internet选项 - 进入 连接 选项卡 - 点击局域网选项 - 选中 使用自动配置脚本 选项 - 在地址里面填入你的文件位置,比如files://d:/goagent.pac ,即可完成配置。
那么PAC文件中应该写些什么呢?其实这个文件只是一个在配置一个叫做FindProxyForURL(url, host)的JScript函数。比如这个文件的内容可以是:
function FindProxyForURL(url, host) { return "PROXY DIRECT; PROXY 192.168.0.1:8080; SOCKS 192.168.1.1:1080 "; } 这是一个最简单的PAC脚本,意思就是让对于所有网站都直接进行连接,如果不能连接就尝试使用http代理192.168.0.1进行连接,如果仍然无法连接就尝试SOCKS代理192.168.1.1。
通过上面的示例大家不难看出IE在调用这个函数的时候会传入两个变量来,一个是地址URL全路经,另一个是URL中的主机名部分。而函数在返回的时候可以是三种值,DIRECT代表直接连接,PROXY代表HTTP代理,SOCKS代表SOCKS类型代理。
根据URL判断是否需要代理
function FindProxyForURL(url, host) {
if (shExpMatch(url,"*.facebook.com/*")) {
return "PROXY 127.0.0.1:8087";
}
return "DIRECT";
}
shExpMatch这个函数可能是写PAC脚本中最常用到的了,在本示例中的作用实现对于facebook 域名下的页面调用127.0.0.1:8087这个代理,而其他URL直接访问。
代理不能解析的主机
function FindProxyForURL(url, host)
{
if (isResolvable(host))
return "DIRECT";
else
return "PROXY 127.0.0.1:8087";
}
这个isResolvable函数实现的功能就是当某个主机域名不能被正常解析的时候就尝试代理访问,比如公司内部如果有独立的DNS而这台DNS又只解析内部地址,就可以利用这个函数自由的切换内外网了,当然也可以用来对付某些ISP的域名劫持。
在家庭和公司之间自动切换
function FindProxyForURL(url, host)
{
if (myIpAddress() == "192.168.0.254") {
return “PROXY 127.0.0.1:80″;
}
else {
return “DIRECT”;
}
}
如果你习惯在下班后将笔记本带回家中的话myIpAddress函数将会十分有用,示例中实现的作用是当本机ip为192.168.0.254的时候就使用127.0.0.1:80这个代理,否则直接连接。
随机选择代理
function FindProxyForURL(url,host)
{
return randomProxy();
}
function randomProxy()
{
switch( Math.floor( Math.random() * 5 ) )
{
case 0:
return “PROXY proxy1:80″;
break;
case 1:
return “PROXY proxy2:80″;
break;
case 2:
return “PROXY proxy3:80″;
break;
case 3:
return “PROXY proxy4:80″;
break;
case 4:
return “PROXY proxy5:80″;
break;
}
}
这个示例中用了一个js中常见的随机数选择方法实现了在5个代理服务器中随机选择,这条函数的作者用意大概是平衡服务器使用量,但更重要是的是给我们打开了一个思路,让一些常见的js函数加入到PAC文件中或许能写出一些精彩有趣的函数来。
以下列举的是可用于FindProxyForURL()函数体中的条件函数,这些函数的具体用法如果大家感兴趣请查阅互联网,这里就不详细介绍了:
基于主机名的函数:
isPlainHostName() dnsDomainIs() localHostOrDomainIs() isResolvable() isInNet()
相关的实用程序函数:
dnsResolve() myIpAddress() dnsDomainLevels()
基于URL/主机名的条件:
shExpMatch()
基于时间的条件:
weekdayRange() dateRange() timeRange() isPlainHostName(host)
-----另外一篇文章-----
因为工作需要,经常需要在家里和办公场所使用同一台电脑,由于家里不需要设置浏览器的代理,而在办公场所就需要设置。所以每次都需要修改,换WINDOWS7之前一直使用IBM版本的Access Connections(以下简称AC)来切换网络设置,很强大,很方便,但遗憾的是IBM版本的AC不支持WIN7,而ThinkpAdvantage系列的AC是有名的臭名昭著——会导致开机缓慢。下了几个IP切换软件,却都少有IE代理切换功能,IPHELPER倒是提供IE代理配置,但公司网中使用的是“IE自动配置脚本”,设定了对内网访问时不使用代理,连接外网时才使用代理。无奈之下深入研究了一下这个IE自动配置脚本的原理,发现原来它就可以实现我所需要的功能(当然IP地址切换功能除外,但提供这个功能的小软件海了去了~),使用IE自动配置脚本,就可以不用每次在单位和家之间手动设置IE代理了~只需要加上一行代码即可~(当然这行代码来之不易,其实学过计算机二级考过了C语言的童鞋们只要静下心来看一看下面的介绍,应该就对IE自动配置脚本一清二楚了~)
1. 什么是IE自动配置脚本
IE自动配置脚本起的作用就是,当IE访问网页的时候会根据脚本文件里面界定的内容来访问。比方说,你在脚本文件里面限定了访问某些IP使用某个代理的时候,访问另外一些IP使用另外的代理,这就很方便通过脚本文件来完成。
2. 如何创建、编辑IE自动配置脚本
1)创建:打开WINDOWS自带的记事本,编辑好代码后另存为“.PAC”格式
2)编辑:使用WINDOWS自带的记事本即可。
3. 如何编写IE自动配置脚本
最简单的格式就是包含一个叫FindProxyForURL的JScript函数,IE通过传入两个变量来调用这个函数,一个是用户浏览的地址URL全路经,一个是这个URL中的主机名部分(host)。
这个FindProxyForURL函数有三种可能的字符串返回值,一是"DIRECT",就是直接连接,不通过代理;二是"PROXY proxyaddr:port",其中proxyaddr和port分别是代理的地址和代理的端口;三是"SOCKS socksaddr:port",其中socksaddr和port分别是socks代理的地址和端口,一个自动代理文件可以是多个选择的组合,其中用分号(;)隔开,如:
function FindProxyForURL(url,host)
{
if (host == "www.mydomain.com")
return "DIRECT";
return "PROXY myproxy:80;
PROXY myotherproxy:8080;
DIRECT";
}
把以上代码另存为proxy.pac的文件,如:c:/proxy.pac,然后在IE的菜单里"工具"->"INTEL选项"->"连接"->局域网设置->把使用自动配置脚本选上,然后在地址栏填入file://c:/proxy.pac,注意file后是两斜杠,要使设置生效,需要关闭IE再重新打开.
现在我们介绍下这个proxy.pac脚本文件,脚本的语法是js语法,js的内置函数可以使用,要实现自动配置代理,需要实现FindProxyForURL这个函数,其参数url代表要访问的连接,host代表要访问连接的主机名,该函数有三个返回参数( direct:直接连接,proxy IP:PORT,socket IP:PORT), 返回结果大小写不敏感.
PAC脚本另外一个重要的应用是多台代理服务器并存的情况下,通过pac脚本的控制,可以实现如下目标:
使用户随机选择使用多台代理服务器中的任意一台来达到流量负载均衡的目的;
使管理员通过PAC脚本控制用户使用和不使用某台代理服务器,这样可以空出时间对代理服务器进行维护;
让服务器工作在主备模式,当主服务器宕机时,会自动切换到其它备用服务器而不会中断服务;
根据访问目的地的不同,自动选择最佳代理服务器。
下面我们介绍几个常用的PAC函数,并举便说明:
<1 isPlainHostName(host),判断是否为本地主机,例如以http://myservername/的方式访问,则是直接连接,否则使用代理
function FindProxyForURL(url, host)
{
if (isPlainHostName(host))
return "DIRECT";
else
return "PROXY proxy:80";
}
<2 dnsDomainIs(host, "")、localHostOrDomainIs(host, ""),判断所访问主机是否属于某个域和某个域名,例如属于.company.com域的主机名,www.company.com和home.company.com的直接连接,否则使用代理访问。
function FindProxyForURL(url, host)
{
if ((isPlainHostName(host) ||
dnsDomainIs(host, ".company.com")) &&
!localHostOrDomainIs(host, "www.company.com") &&
!localHostOrDomainIs(host, "home.company.com"))
return "DIRECT";
else
return "PROXY proxy:80";
}
<3 isResolvable(host),判断被访问主机名能否被解析.例子演示主机名能否被dns服务器解析,如果能直接访问,否则就通过代理访问。
function FindProxyForURL(url, host)
{
if (isResolvable(host))
return "DIRECT";
else
return "PROXY proxy:80";
}
<4 isInNet(host, "", ""),判断IP是否在某个子网内.例子演示访问IP段的主页不使用代理。
function FindProxyForURL(url, host)
{
if (isInNet(host, "10.0.0.0", "255.255.0.0"))
return "DIRECT";
else
return "PROXY proxy:80";
}
<5 shExpMatch(host, ""),判断被访问主机名是否符合某一正则表达式.本例演示根据主机域名来改变连接类型,本地主机、*.edu、*.com分别用不同的连接方式。
function FindProxyForURL(url, host)
{
if (isPlainHostName(host))
return "DIRECT";
else if (shExpMatch(host, "*.com"))
return "PROXY comproxy:80";
else if (shExpMatch(host, "*.edu"))
return "PROXY eduproxy:80";
else
return "PROXY proxy:80";
}
<6 url.substring(),取URL字符串的子串.本例演示根据不同的协议来选择不同的代理,http、https、ftp、gopher分别使用不同的代理。
function FindProxyForURL(url, host)
{
if (url.substring(0, 5) == "http:") {
return "PROXY proxy:80";
}
else if (url.substring(0, 4) == "ftp:") {
return "PROXY fproxy:80";
}
else if (url.substring(0, 7) == "gopher:") {
return "PROXY gproxy";
}
else if (url.substring(0, 6) == "https:") {
return "PROXY secproxy:8080";
}
else {
return "DIRECT";
}
}
<7 dnsResolve(host),解析地址.本例演示判断访问主机是否某个IP,如果是就使用代理,否则直接连接。
function FindProxyForURL(url, host)
{
if (dnsResolve(host) == "166.111.8.237") {
return "PROXY secproxy:8080";
}
else {
return "PROXY proxy:80";
}
}
<8 myIpAddress(),返回自己的IP地址.本例演示判断本地IP是否某个IP,如果是就使用代理,否则直接使用连接。
function FindProxyForURL(url, host)
{
if (myIpAddress() == "10.1.1.1") {
return "PROXY proxy:80";
}
else {
return "DIRECT";
}
}
<9 dnsDomainLevels(host),返回被访问主机域名级数.本例演示访问主机的域名级数是几级,就是域名有几个点,如果域名中有点,就通过代理访问,否则直接连接。
function FindProxyForURL(url, host)
{
if (dnsDomainLevels(host) > 0) { // if number of dots in host > 0
return "PROXY proxy:80";
}
return "DIRECT";
}
<10 weekdayRange(),判断当前日期日否在某一星期段.本例演示当前日期的范围来改变使用代理,如果是GMT时间周三到周六,使用代理连接,否则直接连接。
function FindProxyForURL(url, host)
{
if(weekdayRange("WED", "SAT", "GMT"))
return "PROXY proxy:80";
else
return "DIRECT";
}
<11 最后一个例子是演示随机使用代理,这样可以好好利用代理服务器。
function FindProxyForURL(url,host)
{
return randomProxy();
}
function randomProxy()
{
switch( Math.floor( Math.random() * 5 ) )
{
case 0:
return "PROXY proxy1:80";
break;
case 1:
return "PROXY proxy2:80";
break;
case 2:
return "PROXY proxy3:80";
break;
case 3:
return "PROXY proxy4:80";
break;
case 4:
return "PROXY proxy5:80";
break;
}
}
最后,我解决开篇问题的方法如下:(家里的网段IP地址为192.168.1.101,不设代理,单位需要使用代理TEST.PROXY.COM:8080,但对公司内网除外)
function FindProxyForURL(url,host)
{
if (myIpAddress() == "192.168.1.101") return "DIRECT";
else if ( isInNet(host, "XX.0.0.0", "255.0.0.0" ) ) return "DIRECT";
else if ( dnsDomainIs(host,"company") || dnsDomainIs(host,"XXXX.com") ) return "DIRECT";
else if ( dnsDomainIs(host,".CLIENT") || dnsDomainIs(host,".XXXX") ) return "DIRECT";
else return "PROXY XXX.proxy.com:8080";
}
注:红色粗体字均为个人设置,按需求修改。
将这些内容存为c:/myproxy.pac然后在IE属性->连接->局域网设置->勾选使用自动配置脚本->填入file://c:/myproxy.pac->确定,即可实现自动判断场所上网了,当然,这个文件也可以存在网站上,当然,这时地址就应该为类似http://x.x.x.x/......../proxy.pac的格式了。如果你是一个域管理员,你也可以通过更改组策略的方式把这个地址设置成IE的自动配置脚本.