1、我想通过代理自动配置脚本 Proxy Auto-Config File 来控制用户访问 internet,代理服务器只发布 80 和 443 端口(客户端只能使用 http 和 https 两种方式访问 internet), 具体的要求是1:比如说 172.16.82.0 网段的客户端通过 A 代理走2:比如说 172.16.83.0 网段的客户端也通过 A 代理走3: 比如说 172.16.84.0 网段的客户端通过 B 代理走4: 不属于以上三个网段的地址,以上的代理设置不生效。需求:1:请问该 pac 文件怎么写?2:另外有了这个文件后,整个设置该如何部署生效呢?回答:根据您的描述,我对
2、这个问题的理解是:您想使用 Proxy Auto-Config 文件来控制用户访问互联网。如果我的理解有误,请告诉我。Proxy Auto-Config 使用的是 JavaScript,对于 coding 的问题,我们建议您与 MSDN 联系。由于 MSDN 的相关支持不是由我们新闻组负责的,请您直接拨打该免费电话:8008203800 ,以便于更好的沟通和交流。在此我列出一些 Proxy Auto-Config 文件的编写,供您参考:172.16.82.0 网段的客户端通过 A 代理走。172.16.83.0 网段的客户端也通过 A 代理走。172.16.84.0 网段的客户端通过 B 代理
3、走。不属于以上三个网段的地址,以上的代理设置不生效。我们假定 A 代理的 IP 地址为 172.16.1.1, B 代理的 IP 地址为 172.16.1.2。function FindProxyForURL(url, host)if (shExpMatch(url, “http:/* “) elseif (shExpMatch(url, “http:/* “) elseif (shExpMatch(url, “https:/* “) elseif (shExpMatch(url, “https:/* “) elsereturn “DIRECT“;以上的 script 仅供您参考。其中 isI
4、nNet(myIpAddress(),“172.16.84.0“,“255.255.255.0“)指的是主机 IP 地址是 172.16.84.0网段,shExpMatch(url, “http:/* “)指的是以 http:/开头的网站。如果您的 PAC 文件已经没有错误,您可以在 IE 中设置来使用该 PAC 文件。具体做法如下:1. 打开 IE,选择 “Internet 选项 ”。2. 点击“连接”,“局域网设置”。3. 选择“使用自动配置脚本”,并输入脚本的位置,比如 file:/ C:/WINDOWS/system32/drivers/etc。您也可以通过组策略来配置:1. 打开组策
5、略编辑器,选择“用户配置”“Windows 设置”“Internet Expleror 维护”“ 连接”。2. 双击“自动配置”,选择“启用自动配置”,在自动代理选项中中设置该 pac 文件的路径。如何编写 PAC (Proxy Auto-Config) 文件2009-06-29 16:30PAC 文件,就是 Proxy Auto-Config 文件的简称,事实上是一个 javascript 脚本。这个文件定义了如何根据浏览器访问 url 的不同,自动选取适当的代理(proxy)。如何编写 PAC 文件呢,首先必须定义一个主函数 FindProxyForURL,格式如下:function Fi
6、ndProxyForURL(url, host).浏览器在访问每个 url 的时候都会调用该函数:ret = FindProxyForURL(url, host);函数参数中url 是浏览器访问的完整 url 地址,例如http:/openattitude.irixs.org/http:/ 是从完整 url 中截取的子字串,内容是从:/开始到下面第一个/或者:中间的部分,以上面 url 为例分别为192.168.1.1我们来仔细看一下第三个例子,host 字段中不包含端口 8000。如果有需要,端口号可以从 url 字段中提取。ret 是字符串变量,根据 FindProxyForURL()返回
7、值返回单个字符串。如果返回 NULL,即返回空字符串,则浏览器不会使用任何代理,这样浏览器将无法打开网页。返回值可以是下列三种结构块的任意组合,每个不同的块之间用分号分割。DIRECT - 不调用代理,直接连接PROXY host:port - 调用指定代理(host:port)SOCKS host:port - 调用指定 SOCKS代理(host:port)如果是选用由分号分割的多块设置,按照从左向右,最左边的代理会被最优先调用,除非浏览器无法成功和 proxy 建立连接,那么下一个配置就会被调用。如果浏览器遇到不可用的代理服务器,浏览器将在 30 分钟后自动重试先前无响应的代理服务器,一个
8、小时后会再次进行尝试,依此类推,每次间隔时间为 30 分钟。这意味着,如果暂时关闭代理服务器,客户机至多在其重新启动后 30 分钟便会重新开始使用该代理服务器。如果所有代理服务器均停用且未指定DIRECT 返回值,浏览器将询问用户是否暂时忽略代理服务器而尝试直接进行连接。Navigator 将询问是否应在 20 分钟后重试代理服务器,接着过 20 分钟会再次询问,依此类推,每次间隔时间为 20 分钟。举例PROXY :8080; PROXY :8081; DIRECT下面是可用于 FindProxyForURL()函数体中的条件函数:基于主机名的函数:isPlainHostName()dnsD
9、omainIs()localHostOrDomainIs()isResolvable()isInNet()相关的实用程序函数:dnsResolve()myIpAddress()dnsDomainLevels()基于 URL/主机名 的条件:shExpMatch()基于时间的条件:weekdayRange()dateRange()timeRange()isPlainHostName(host)host 即上文所述不包含端口号的,url 中的主机名,下同,不再赘述。如果主机名中不包含域名则返回 true。参考如下:isPlainHostName(“www“) 返回 true.isPlainHost
10、Name(““) 返回 false.dnsDomainIs(host, domain)domain 用于和 hostname 进行比较的域名。如果 hostname 的域名和 domain 的值相匹配则返回 true。参考如下:dnsDomainIs(““, ““) 返回 true.dnsDomainIs(“www“, ““) 返回 false.dnsDomainIs(““, ““) 返回 false.localHostOrDomainIs(host, hostdom)hostdom 是要进行匹配的指定的主机名。如果 hostname 和指定的 hostdom 相匹配,或者在 hostname
11、 中没有指定要进行匹配的域名部分,函数返回 true。参考如下:localHostOrDomainIs(“www. “, “www. “) 返回 true (exact match).localHostOrDomainIs(“www“, “www. “) 返回 true (hostname match, domain not specified).localHostOrDomainIs(““, “www. “) 返回 false (domain name mismatch).localHostOrDomainIs(““, “www. “) 返回 false (hostname mismatch
12、).isResolvable(host)如果成功解析主机名则返回 true。参考如下:isResolvable(““) 返回 true (除非由于防火墙或某些其他原因导致 DNS无法解析).isResolvable(“bogus.domain.foobar“) 返回 false.isInNet(host, pattern, mask)host 在这里可以是 DNS 主机名,比如 ,也可以是 IP 地址。如果传递的是主机名,此函数会将其解析成 IP 地址。 pattern 是点分隔格式的 IP 地址模式。mask 是 IP 地址模式掩码,用于确定应对 IP 地址的哪些部分进行匹配。值为 0表示忽
13、略;255 表示匹配。如果主机的 IP 地址与指定的 IP 地址模式匹配,则返回 true。参考如下:isInNet(host, “198.95.249.79“, “255.255.255.255“) 如果 host的 IP地址为 198.95.249.79则返回 true.isInNet(host, “198.95.0.0“, “255.255.0.0“) 如果 host的 IP地址为198.95.*.*则返回 true.dnsResolve(host)host 是要解析的主机名。将给定 DNS 主机名解析成 IP 地址,并以点分隔格式的字符串形式将其返回。参考如下:dnsResolve(“
14、“) 返回 IP地址 “64.233.189.104“.myIpAddress()此函数将以点分隔格式的字符串形式返回运行浏览器的那台计算机的 IP 地址。dnsDomainLevels(host)返回 url 主机名中的 DNS 层数(圆点数)。参考如下:dnsDomainLevels(“www“) 返回 0dnsDomainLevels(““) 返回 2shExpMatch(str, shexp)str 是要比较的任何字符串(例如,url 或主机名)。shexp 是用以进行比较的 shell 表达式。如果字符串与指定的 shell 表达式匹配,则此表达式为 true。参考如下:shExpM
15、atch(“http:/ “*/macosx/*“) 返回 true.shExpMatch(“http:/ “*/macosx/*“) 返回 false.weekdayRange(wd1, wd2, gmt)wd1 和 wd2 为以下任意一个星期日期字符串: SUN MON TUE WED THU FRI SAT, gmt 或者是字串 GMT 或者省略,前者表示格林威治标准时间,后者表示当地时间。 只有第一个参数 wd1 是强制性的。wd2、gmt 中的任一个或两者皆可省略。如果只有一个参数,则此函数将在该参数所表示的星期日期返回true。如果指定字符串 GMT 作为第二个参数,则采用 GMT
16、 时间,否则采用当地时区的时间。如果 wd1 和 wd2 均被定义,则该条件在当前星期日期介于这两个星期日期之间时为 true。首末日期包括在内。参数顺序很重要;”MON,” “WED” 指星期一到星期三,而 “WED,” “MON” 是从星期三到下周的星期一。weekdayRange(“MON“, “FRI“) 从星期一到星期五(当地时区)为 true.weekdayRange(“MON“, “FRI“, “GMT“) 从格林威治标准时间星期一到星期五为 true.weekdayRange(“SAT“) 当地时间星期六为 true.weekdayRange(“SAT“, “GMT“) 格林威
17、治标准时间星期六为 true.weekdayRange(“FRI“, “MON“) 从星期五到下星期一为 true (注意,顺序很重要).dateRange(day)dateRange(day1, day2)dateRange(mon)dateRange(month1, month2)dateRange(year)dateRange(year1, year2)dateRange(day1, month1, day2, month2)dateRange(month1, year1, month2, year2)dateRange(day1, month1, year1, day2, month2
18、, year2)dateRange(day1, month1, year1, day2, month2, year2, gmt)day 每月 1 到 31 号中的任意一天(整数类型).month 是如下表示月份的字符串中的一个:JAN FEB MAR APR MAY JUN JUL AUG SEP OCT NOV DEC, year 是表示年份的完整数字,例如 1995(而不是 95)。整数类型。gmt 或者为字符串 GMT,或者保留为空,前者将以格林威治标准时间进行时间比较,后者假定时间处于当地时区。尽管上面表示的函数语法不是每一个都包含 gmt 参数,事实上可以在上述 9 个任一调用配置文
19、件中指定 gmt 参数,不过,它始终都要作为最后一个参数。如果只指定了单个值(对于每个类别:day、month、year),则此函数仅在与指定值匹配的日子才会返回 true。如果指定了两个值,则从指定的第一个时间到指定的第二个时间,结果均为truee。首末日期包括在内。参考如下:dateRange(1) 在当地时区每月的第一天为 true.dateRange(1, “GMT“) 在 GMT时间每月的第一天为 true.dateRange(1, 15) 在当地时区每月的 1号到 15号为 true.dateRange(24, “DEC“) 在当地时区每年 12月 24号为 true.dateRa
20、nge(24, “DEC“, 1995) 在当地时区 1995年 12月 24号为 true.dateRange(“JAN“, “MAR“) 在当地时区每年第一季度(1 月到 3月)为 true.dateRange(1, “JUN“, 15, “AUG“) 在当地时区每年 6月 1号到 8月 15号为 true, 首末日期包括在内.dateRange(1, “JUN“, 15, 1995, “AUG“, 1995) 在当地时区 1995年 6月 1号到 8月 15号为 true, 首末日期包括在内.dateRange(“OCT“, 1995, “MAR“, 1996) 在当地时区 1995年
21、10月到 1996年 3月为 true.dateRange(1995) 在当地时区 1995年为 true.dateRange(1995, 1997) 在当地时区 1995年 1月 1号到 1997年 12月 31号(1995年初到 1997年底)为 true.timeRange(hour)timeRange(hour1, hour2)timeRange(hour1, min1, hour2, min2)timeRange(hour1, min1, sec1, hour2, min2, sec2)timeRange(hour1, min1, sec1, hour2, min2, sec2, g
22、mt)hour 是 0 点(午夜 12 点)到 23 点(晚上 11 点)表示小时的数值中的一个。min 是表示分钟的 0 到 59 中的一个值。sec 是表示秒钟的 0 到 59 中的一个值。gmt 同上文所述。timerange(12)中午 12点到下午 1点之间为 true.timerange(12, 13)同上例.timerange(12, “GMT“)在 GMT时间中午 12点到下午 1点之间为 true.timerange(9, 17)上午 9点到下午 5点之间为 true.timerange(8, 30, 17, 00)上午 8点 30分到下午 5点之间为 true.timera
23、nge(0, 0, 0, 0, 0, 30)午夜 0点到其后的 30秒内为 true.用本本上网时,往返家里和单位,因为单位是用的代理上网,家里是直接连接.因此每次都要修改 IE 的代理设置,虽然是个小事,但是每次都要修改总是有点烦,于是参考 GOOGLE,写了一个自动配置代理的脚本.这样无论在家和在公司,只要连上局域网就可以上网了.function FindProxyForURL(url,host)if(isPlainHostName(host)|shExpMatch(url,“http:/127.0.0.1/*“)|isInNet(host,“192.168.0.0“, “255.255.
24、255.0“)return “direct“; else if(myIpAddress()=“192.168.0.49“)return “PROXY 192.168.0.6:808“;elsereturn “direct“;把以上代码另存为 proxy.pac 的文件,如:c:proxy.pac,然后在 IE 的菜单里“工具“-“INTEL 选项“-“连接“-局域网设置把使用自动配置脚本选上,然后在地址栏填入 file:/c:/proxy.pac,注意 file 后是两斜杠,要使设置生效,需要关闭 IE 再重新打开.现在我们介绍下这个 proxy.pac 脚本文件,脚本的语法是 js 语法,j
25、s 的内置函数可以使用,要实现自动配置代理,需要实现 FindProxyForURL 这个函数,其参数 url 代表要访问的连接,host 代表要访问连接的主机名,该函数有三个返回参数direct:直接连接proxy IP:PORTsocket IP:PORT返回结果大小写不敏感PAC 的其他内置语法见 http:/ 脚本另外一个重要的应用是多台代理服务器并存的情况下,通过 pac 脚本的控制:用户随机选择使用多台代理服务器中的任意一台来达到流量负载均衡的目的;管理员通过 PAC 脚本控制用户使用和不使用某台代理服务器,这样可以空出时间对代理服务器进行维护;让服务器工作在主备模式,当主服务器宕
26、机时,会自动切换到其它备用服务器而不会中断服务;根据访问目的地的不同,自动选择最佳代理服务器。下面列举几个 PAC 的实例,顺便学习下它的语法a、isPlainHostName(host),本例演示判断是否为本地主机,如 http:/myservername/的方式访问,如果是直接连接,否则使用代理function FindProxyForURL(url, host)if (isPlainHostName(host)return “DIRECT“;elsereturn “PROXY proxy:80“;b、dnsDomainIs(host, “)、localHostOrDomainIs(hos
27、t, “),本例演示判断访问主机是否属于某个域和某个域名,如果属于 域的主机名,而域名不是 和 的直接连接,否则使用代理访问。function FindProxyForURL(url, host)if (isPlainHostName(host) |dnsDomainIs(host, ““) elsereturn “PROXY proxy:80“;c、isResolvable(host),本例演示主机名能否被 dns 服务器解析,如果能直接访问,否则就通过代理访问。function FindProxyForURL(url, host)if (isResolvable(host)return
28、“DIRECT“;elsereturn “PROXY proxy:80“;d、isInNet(host, “, “),本例演示访问 IP 是否在某个子网内,如果是就直接访问,否则就通过代理,例子演示访问清华 IP 段的主页不用代理。function FindProxyForURL(url, host)if (isInNet(host, “166.111.0.0“, “255.255.0.0“)return “DIRECT“;elsereturn “PROXY proxy:80“;e、shExpMatch(host, “),本例演示根据主机域名来改变连接类型,本地主机、*.edu、*.com 分
29、别用不同的连接方式。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“;elsereturn “PROXY proxy:80“;f、url.substring(),本例演示根据不同的协议来选择不同的代理,http、https、ftp、gopher 分别使用
30、不同的代理。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“;el
31、se return “DIRECT“;g、dnsResolve(host),本例演示判断访问主机是否某个 IP,如果是就使用代理,否则直接连接。h、myIpAddress(),本例演示判断本地 IP 是否某个 IP,如果是就使用代理,否则直接使用连接。function FindProxyForURL(url, host)if (myIpAddress() = “166.111.8.238“) return “PROXY proxy:80“;else return “DIRECT“;i、dnsDomainLevels(host),本例演示访问主机的域名级数是几级,就是域名有几个点如果域名中有点,
32、就通过代理访问,否则直接连接。function FindProxyForURL(url, host)if (dnsDomainLevels(host) 0) / if number of dots in host 0return “PROXY proxy:80“;return “DIRECT“;j、weekdayRange(),本例演示当前日期的范围来改变使用代理,如果是 GMT 时间周三到周六,使用代理连接,否则直接连接。function FindProxyForURL(url, host)if(weekdayRange(“WED“, “SAT“, “GMT“)return “PROXY p
33、roxy:80“;elsereturn “DIRECT“;k、最后一个例子是演示随机使用代理,这样可以好好利用代理服务器。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;