PAC⽂件详解
PAC⽂件详解
PAC⽂件是纯⽂本⽂件,其实质为javascript脚本,其“.pac”后缀(proxy auto config)只是为了指定⼀个特定的程序来解析。 PAC⽂件中必须包含⼀个函数,FindProxyForURL(url, host)。其中的url是⽤户输⼊的url,参数host是url中的主机名。⽐如url为 ⼀个简单的PAC⽂件内容如下:
function FindProxyForURL(url, host)
{
return "DIRECT";
}
这个PAC⽂件实际上什么也没做,对任何URL,都将"DIRECT"(直接连⽹)。
当然,PAC⽂件除了可以return "DIRECT"以外,还有两种常⽤⽅式:
PROXY proxysample:8080
//HTTP代理的主机和端⼝,主机也可以⽤IP表⽰
SOCKS5 socks5sample:1080
//SOCKS5代理的主机和端⼝,主机也可以⽤IP表⽰。
那么,我们可以猜测到,⽤pac指定⼀个HTTP代理应该这样写:
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:1080";
}
这段脚本的意思是:
STEP1. 对所有URL,都直接连接;
STEP2. 如果不能直接连接,那么就使⽤192.168.1.1:3128这个HTTP代理连接;
STEP3. 如果还是不能连接,则使⽤lilinux:1080这个SOCKS5代理连接。
也许你明确知道哪些⽹站不能直连,必须⽤PROXY或者SOCKS5连接,那么可以对站点分别指定代理配置:
function FindProxyForURL(url, host)
{
if (shExpMatch(url,"*.google/*"))
{
return "PROXY 192.168.1.1:3128";
}
if (shExpMatch(url, "*.wikipedia:*/*"))
{
return "SOCKS5 lilinux:1080";
}
if (isInNet(host, "10.0.0.0", "255.0.0.0"))
{
return "DIRECT";
}
return "DIRECT; PROXY 192.168.1.1:3128; SOCKS5 lilinux:1080";
}
这个PAC⽂件中引⼊了两个新的函数,但从字⾯意思上,我们也可以猜出代码的⼤概意思:
STEP1. 当url是*.google/* 时,⾃动使⽤PROXY代理;
STEP2. 当url是*./*时,⾃动使⽤SOCKS5代理;
STEP3. 当host是10.0.0.0 /255.0.0.0的⼦⽹内时,⾃动直连;
STEP4. 如果都不匹配,则依次按DIRECT、PROXY、SOCKS5的次序尝试。
非法请求
shExpMatch函数⽤来匹配url或者host,匹配的⽅式和DOS的通配符相似。例如前⾯⽤到
的"*.google/*"可以匹配任包含
".google/"的字符串。
isInNet函数⽤来返回请求的host是否在指定的域内。值得注意的是,isInNet的第⼆个参数必须 是 IP,不能是主机名。因此需要把主机名
声波识别
转换成IP。⽐如"isInNet(host, le), "255.255.255.0")"讲到这⾥,应该可以解决你的问题了吧。
当然,PAC⽂件远不⽌这么简单,关于更详细的内容请看这篇:
PAC⽂件可以使⽤的JavaScript函数
下⾯是可⽤于FindProxyForURL()函数体中的条件函数:
基于主机名的函数:
isPlainHostName()
dnsDomainIs()
d2x说明书localHostOrDomainIs()
isResolvable()
isInNet()
相关的实⽤程序函数:
dnsResolve()
myIpAddress()
dnsDomainLevels()
基于 URL/主机名 的条件:
shExpMatch()
weekdayRange()
混凝土包管dateRange()
timeRange()
isPlainHostName(host)
host 即上⽂所述不包含端⼝号的,url中的主机名,下同,不再赘述。如果主机名中不包含域名则返回true。参考如下:
isPlainHostName("www") 返回 true.
isPlainHostName("le") 返回 false.
dnsDomainIs(host, domain)
domain ⽤于和hostname进⾏⽐较的域名。如果hostname的域名和domain的值相匹配则返回true。参考如下:
dnsDomainIs("le", ".google") 返回 true.
dnsDomainIs("www", ".google") 返回 false.
dnsDomainIs("www.apple", ".google") 返回 false.
localHostOrDomainIs(host, hostdom)
hostdom 是要进⾏匹配的指定的主机名。如果hostname和指定的hostdom相匹配,或者在hostname中没有指定要进⾏匹配的域名部分,函数返回 true。参考如下:
localHostOrDomainIs("www. google", "www. google") 返回 true (exact match). localHostOrDomainIs("www", "www. google") 返回 true (hostname match, domain not specified).
localHostOrDomainIs("www.apple", "www. google") 返回 false (domain name mismatch). localHostOrDomainIs("adc.apple", "www. google") 返回 false (hostname mismatch). isResolvable(host)
制作智能卡如果成功解析主机名则返回true。参考如下:
isResolvable("le") 返回 true (除⾮由于防⽕墙或某些其他原因导致DNS⽆法解析). isResolvable("bogus.domain.foobar") 返回 false.
isInNet(host, pattern, mask)
host 在这⾥可以是DNS主机名,⽐如le,也可以是IP地址。如果传递的是主机名,此函数会将其解析成 IP 地址。 pattern 是点分隔格式的 IP 地址模式。
mask 是IP地址模式掩码,⽤于确定应对IP地址的哪些部分进⾏匹配。值为0表⽰忽略;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("le") 返回IP地址 "64.233.189.104".
myIpAddress()
此函数将以点分隔格式的字符串形式返回运⾏浏览器的那台计算机的IP地址。装备偏移
dnsDomainLevels(host)
返回url主机名中的DNS层数(圆点数)。参考如下:
dnsDomainLevels("www") 返回 0
dnsDomainLevels("le") 返回 2
shExpMatch(str, shexp)
str 是要⽐较的任何字符串(例如,url或主机名)。
shexp 是⽤以进⾏⽐较的shell表达式。如果字符串与指定的 shell 表达式匹配,则此表达式为 true。参考如下:
shExpMatch("www.apple/downloads/macosx/index.html", "*/macosx/*") 返回 true. shExpMatch("www.apple/downloads/support/index.html", "*/macosx/*") 返回 false. weekdayRange(wd1, wd2, gmt)
wd1 和 wd2 为以下任意⼀个星期⽇期字符串: SUN MON TUE WED THU FRI SAT, gmt 或者是字串GMT 或者省略,前者表⽰格林威治标准时间,后者表⽰当地时间。 只有第⼀个参数wd1是强制性的。
wd2、gmt 中的任⼀个或两者皆可省略。如果只有⼀个参数,则此函数将在该参数所表⽰的星期⽇期
返回true。如果指定字符串GMT作为第⼆个参数,则采⽤GMT时 间,否则采⽤当地时区的时间。如果wd1和wd2均被定义,则该条件在当前星期⽇期介于这两个星期⽇期之间时为true。⾸末⽇期包括在内。参数顺序很重 要;"MON," "WED" 指星期⼀到星期三,⽽ "WED," "MON" 是从星期三到下周的星期⼀。weekdayRange("MON", "FRI") 从星期⼀到星期五(当地时区)为 true.
weekdayRange("MON", "FRI", "GMT") 从格林威治标准时间星期⼀到星期五为 true.
weekdayRange("SAT") 当地时间星期六为 true.
weekdayRange("SAT", "GMT") 格林威治标准时间星期六为 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, 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个任⼀调⽤配置⽂件中指定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.
dateRange(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年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, gmt)
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.
timerange(0, 0, 0, 0, 0, 30)午夜0点到其后的30秒内为 true.