pac文件写法 代理自动配置(英语:Proxy auto-config,简称PAC)

  |   392 |   Code |   WWW

火狐的autoproxy和Foxyproxy都开始出现这样那样的问题,于是我想到了.pac,没想到的是,这方法简单、有效,不但省了个扩展,还比扩展用起来舒服多了

一个PAC文件包含一个JavaScript形式的函数“FindProxyForURL(url, host)”。这个函数返回一个包含一个或多个访问规则的字符串。用户代理根据这些规则适用一个特定的代理其或者直接访问。当一个代理服务器无法响应的时候,多个访问规则提供了其他的后备访问方法。浏览器在访问其他页面以前,首先访问这个PAC文件。PAC文件中的URL可能是手工配置的,也可能是是通过网页的网络代理自发现协议(Web Proxy Autodiscovery Protocol)自动配置的。

网络代理自发现协议(WPAD):浏览器通过DHCP和DNS的查询来搜索PAC文件的位置。(与本文无关)

火狐可以打开浏览器控制台进行调试

PAC file installed from file:///C:/Users/XX/Dropbox/Documents/GitHub/rules-GM-stylish-UC/test.pac
PAC-alert: false

来源文档

既定参数

url:the full URL being accessed.
host:the hostname extracted from the URL. it is the exact same string as between :// and the first : or / after that. The port number is not included in this parameter. It can be extracted from the URL when necessary.
ret:(the return value) a string describing the configuration. The format of this string is defined below.

返回值

Instruction Meaning
DIRECT Fetch the object directly from the content HTTP server denoted by its URL
PROXY host:port Fetch the object via the proxy HTTP server at the given location (name and port)
SOCKS host:port Fetch the object via the SOCKS server at the given location (name and port)

SOCKS可以写SOCKS5或者SOCKS4的样子,写SOCKS就是SOCKS4。
区别在于用SOCKS4只支持TCP,而用SOCKS5支持UDP,还有支持各种身份验证机制。但用SOCKS5是远程代理解析DNS(FF是这样)。

Examples

PROXY w3proxy.netscape.com:8080; PROXY mozilla.netscape.com:8081
//Primary proxy is w3proxy:8080; if that goes down start using mozilla:8081 until the primary proxy comes up again.
PROXY w3proxy.netscape.com:8080; PROXY mozilla.netscape.com:8081; DIRECT
//Same as above, but if both proxies go down, automatically start making direct connections. 
PROXY w3proxy.netscape.com:8080; SOCKS socks:1080
//Use SOCKS if the primary proxy goes down.
//就个人来讲,喜欢只写一个值,这样好知道代理是不是挂了

函数

就是用看起来很吓唬人的函数名实现一个很简单的功能,除了url跟host,其他都是用来唬人的

dnsDomainIs(host, domain)

Evaluates hostnames and returns true if hostnames match. Used mainly to match and exception individual hostnames.
判断是否是同域名,但这个函数很奇葩,火狐里诸如if(dnsDomainIs("aaaa", "aa"))是返回true的(别的没测,个人猜测是通过判断第一个字符串是否包含第二个字符串来实现的)
Example:

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

shExpMatch(str, shexp)

Will attempt to match hostname or URL to a specified shell expression, and returns true if matched.
通过主机名或URL进行匹配,其实就是一个能用通配符(*)的检测
Example:

// Any requests with a hostname ending with the extension .local
// will be sent direct to the Internet.
 
if (shExpMatch(url, "*.local"))
    return "DIRECT";
// 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";

isInNet(host, pattern, mask)

This function evaluates the IP address of a hostname, and if within a specified subnet returns true. If a hostname is passed the function will resolve the hostname to an IP address.
判断IP是否在指定的网段内,dnsResolve这个函数的作用在下面有。最后个参数是子网掩码,如果不懂的话可以去查下子网掩码是做什么的。
Example:

if (isInNet(dnsResolve(host), "172.16.0.0", "255.240.0.0"))
    return "DIRECT";

myIpAddress()

Returns the IP address of the host machine.
返回你的当前IP地址,就是网卡获取的多少就是多少
Example:

// If the machine requesting a website falls within IP range,
// send traffic via proxy 10.10.5.1 running on port 8080.
 
if (isInNet(myIpAddress(), "10.10.1.0", "255.255.255.0"))
    return "PROXY 10.10.5.1:8080";
PAC file installed from file:///C:/Users/XX/Dropbox/Documents/GitHub/rules-GM-stylish-UC/test.pac
PAC-alert: 192.168.1.7

dnsResolve(host)

Resolves hostnames to an IP address. This function can be used to reduce the number of DNS lookups, e.g. below example.
按我的理解这就是把域名解析成IP的,上面的英文其实我觉得有点问题。通常配合isInNet使用。(在火狐上使用会影响页面加载)
Example:

// 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";

isPlainHostName(host)

This function will return true if the hostname contains no dots, e.g. http://intranet
Useful when applying exceptions for internal websites, e.g. may not require resolution of a hostname to IP address to determine if local.
主要保证没有".",通常这样的属于内网的主机名
Example:

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

localHostOrDomainIs(host, hostdom)

Evaluates hostname and only returns true if exact hostname match is found.
似乎是通过判断"."间隔的内容是否相同来实现的(可以没有,但不能不一样)
Example:

// If the Host requested is "www" or "www.google.com", send direct.
 
if (localHostOrDomainIs(host, "www.google.com"))
    return "DIRECT";
// If the Host requested is "google.com" or a subdomain of google.com, e.g. "example.google.com", send direct.
 
if (localHostOrDomainIs(host, ".google.com"))
    return "DIRECT";

isResolvable(host)

Attempts to resolve a hostname to an IP address and returns true if successful. WARNING – This may cause a browser to temporarily hang if a domain isn’t resolvable.
判断域名是否可以被解析
Example:

// If the host requested can be resolved by DNS, send via proxy1.example.com.
 
if (isResolvable(host))
    return "PROXY proxy1.example.com:8080";

dnsDomainLevels(host)

Allows rules to be time based, e.g. only return a proxy during specific days.
就是数下字符串里有几个".",例如dnsDomainLevels("www.netscape.com/www.www")会返回3
Example:

// If hostname contains any dots, send via proxy1.example.com, otherwise send direct.
 
if (dnsDomainLevels(host) > 0)
    return "PROXY proxy1.example.com:8080";
    else return "DIRECT";

weekdayRange(wd1, wd2, gmt)

Allows rules to be time based, e.g. only return a proxy during specific days.
wd1
and
wd2
are one of the weekday strings:

SUN MON TUE WED THU FRI SAT

gmt
is either the string: GMT or is left out.
在wd1到wd2时会返回true,gmt是格林尼治标准时间
Example:

// 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

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)

Allows rules to be time based, e.g. only return a proxy during specific months.

Example:

// If during the period of January to March, proxy1.example.com will be returned, otherwise
// users will go direct for any month outside this period.
 
if (dateRange("JAN", "MAR")) return "PROXY proxy1.example.com:8080";
    else return "DIRECT";

timeRange

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)

Allows rules to be time based, e.g. only return a proxy during specific hours.

Example:

// 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";

alert

The alert() function is not specified in the original PAC specification, although support for this is included in Internet Explorer and Firefox.The function can be used to output the value of a variable or result of a function in a manner that is viewable by the end-user. This can be useful for troubleshooting PAC file rule issues.

See debug PAC file article for an advanced example of using this function.
Example:

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

个人用代码

https://github.com/ted423/rules-GM-stylish-UC/blob/master/proxy-1080.pac

function FindProxyForURL(url, host)
{
    proxy = "PROXY 127.0.0.1:8080"
    if (isInNet(dnsResolve(host), "198.0.0.1", "255.0.0.0"))return proxy;
    if (isPlainHostName(host)) return "DIRECT";
    if (shExpMatch(host, "*.google.*" ))return proxy;
    if (shExpMatch(host, "*.googleapis.com" ))return proxy;
    if (shExpMatch(host, "*.google-analytics.com" ))return proxy;
    if (shExpMatch(host, "*.googleusercontent.com" ))return proxy;
    if (shExpMatch(host, "*.gstatic.com" ))return proxy;
    if (shExpMatch(host, "*.googlecode.com" ))return proxy;
    if (shExpMatch(host, "*.dropbox.com" ))return proxy;
    if (shExpMatch(host, "*.dropboxstatic.com" ))return proxy;
    if (shExpMatch(host, "*.iobit.com" ))return proxy;
    if (shExpMatch(host, "*.mediafire.com" ))return proxy;
    if (shExpMatch(host, "*.blogspot.com" ))return proxy;
    if (shExpMatch(host, "*.blogger.com" ))return proxy;
    return "DIRECT";
}

Other

MIME type

application/x-ns-proxy-autoconfig

Comments
Write a Comment