Total Pageviews

Saturday, 23 January 2016

自动代理文件(PAC)/智能代理简介及设置方法

自动代理(PAC)/智能代理简介及设置方法

    自动代理(PAC)
        自动代理(PAC)由浏览器直接判断是否需要代理。一个PAC文件是一个至少定义了一个JavaScript函数的文本文件。这个函数FindProxyForURL(url, host)有2个参数:url是将要访问的网址,host是一个由这个网址所衍生的域名,例如url为“https://code.google.com/p/wallproxy/”时,host为“code.google.com”。按照惯例,这个文件名字一般是proxy.pac。一个非常简单的PAC文件内容如下:

        function FindProxyForURL(url, host) {
           if (url == 'http://www.baidu.com/') return 'DIRECT';
           if (host == 'twitter.com') return 'SOCKS 127.0.0.10:7070';
           if (dnsResolve(host) == '10.0.0.100') return 'PROXY 127.0.0.1:8086;DIRECT';
           return 'DIRECT';
        }

        首先看看“return”后面的那个字符串,它表示需要使用的代理,例如“ DIRECT ”为直连(即不使用代理),“ PROXY ip:port ”表示HTTP代理,“ SOCKS ip:port ”表示SOCKS代理(注意SOCKS代理有SOCKS4/SOCKS5两种,PAC中的SOCKS表示哪一种与浏览器有关,一般为SOCKS4,有些浏览器支持使用“ SOCKS5 ip:port ”来表示SOCKS5代理),“ PROXY ip1:port1; PROXY ip2:port2 ”表示如果前一个代理未工作则改走后一个备用代理。
        上面PAC的意思是:如果网址为http://www.baidu.com/则直连;如果域名为twitter.com则走SOCKS代理127.0.0.10:7070;如果通过dnsResolve函数解析域名得到的ip是10.0.0.100则尝试HTTP代理127.0.0.1:8086,若该代理当前未工作则直连;其他情况走默认代理,此处为直连。
        PAC本质上就是一个JavaScript文件,所以JavaScript支持的字符串、正则表达式等操作都可以应用于url和host参数来辅助进行判断,从而实现很强大的代理选择,但也因此要求编写者具有一定的JavaScript知识。
        wallproxy的PAC功能则使得一般人只需要简单的修改配置文件即可获得灵活高效完善的PAC。在proxy.ini中,有关PAC的内容为:

        [pac]
        enable = 3
        file = proxy.pac
        rulelist = https://autoproxy-gfwlist.googlecode.com/svn/trunk/gfwlist.txt|userlist.ini
        iplist =
        ;rulelist = !rulelist
        ;iplist = !iplist
        ;default = DIRECT|DIRECT|DIRECT

        [rulelist]
        PROXY *:8087;DIRECT = https://autoproxy-gfwlist.googlecode.com/svn/trunk/gfwlist.txt|userlist.ini
        PROXY 127.0.0.1:8088;DIRECT = paaslist.ini

        [iplist]
        PROXY *:8087;DIRECT = iplist.ini

        enable = 1,智能代理开启,不会自动更新file指定的pac;enable = 2,智能代理关闭,自动更新PAC;enable = 3,智能代理开启并自动更新PAC;enable = 0,智能代理关闭且不更新PAC。建议如果内存不紧张的话,就保持为“智能代理”模式;如果不需要使用智能代理功能或者运行在内存紧张的系统例如路由器/手机上,就关闭智能代理
        如果[pac]rulelist不以“!”开头,则表示后面的内容为以“|”分隔的代理规则列表,此时如果开启了[gae]则对满足规则的网址走GAE,否则如果开启了[paas]则对满足规则的网址走PAAS;如果以“!”开头,则查找去掉“!”后所指示的节,例如去掉“;rulelist = !rulelist”前面的分号取消注释后,就将根据[rulelist]节来确定代理和规则列表。很明显不开启[rulelist]节的话,就只能支持一个代理且不满足规则时必然走直连(如果在[proxy]设置了全局代理,当没有设置[pac]default参数时,PAC中将用该全局代理作为默认代理,否则按照default参数指示的代理更新PAC),只有开启后才能支持多个代理或者默认代理不是直连(或全局代理)的情况,但也将无法判断所指定的代理是否有效。
      
在[rulelist]中,等号左边为前面“return”字符串所描述的代理,右边为“|”分隔的代理规则列表。因为用户可能修改[listen]ip port参数来改变wallproxy监听的ip和端口,所以为了修改后不需要再修改[pac]的设置,可以用*:*和“*:”去自适配。例如设置wallproxy监听0.0.0.0:8086,本机用户给浏览器设置“http://127.0.0.1:8087/proxy.pac”,那么“*:*”相当于“127.0.0.1:8087”,“*:8086”相当于“127.0.0.1:8086”;非本机用户设置“http://192.168.1.100:8086/proxy.pac”,那么“*:*”相当于“192.168.1.100:8086”,“*:8086”相当于“192.168.1.100:8086”,也就是说只要能够访问到PAC文件,那么代理就能被正确替换,不会出现让非本机用户去使用“127.0.0.1:8086”这种不正确地址的情况。
        wallproxy的智能代理默认监听8086端口,所以可写为“PROXY *:8086;DIRECT”;GAE监听8087端口,可写为“PROXY *:8087;DIRECT”;如果浏览器不支持SOCKS代理远程DNS解析,可设置“PROXY *:8086:DIRECT”先让浏览器走智能代理,再由智能代理走需要的SOCKS代理;如果需要屏蔽某个网址,也是相同的方法,先让浏览器走智能代理,再由智能代理进行屏蔽。
        在[rulelist]中设置多个“代理 = 规则列表”后,会对满足右边规则列表的网址走左边的代理,所有规则都不满足的话走默认代理。默认代理在[pac]default设置,由两个“|”分隔3个代理,这3个代理分别用于“不匹配任何规则时|解析出的地址是IPv6时|解析IP失败时(后两种只在使用iplist时用到)”,每个代理仍然与前面描述的写法相同。
        iplist与rulelist类似,不同的是rulelist是根据autoproxy规则对url进行匹配,而iplist是将host解析后对ip进行匹配。
        rulelist编写规则如下,一行一条:

        ! 以!开头的行是注释,修改时建议保留以便参照
        ! 以/开头/结尾的规则是正则表达式,不作处理直接测试url是否匹配,例如/^https?:\/\/[^\/]+example\.com/
        ! 规则中的*匹配任意长度字符串,例如*.example.com匹配www.example.com、www.sub.example.com
        ! 规则前没有|、/表示规则为url关键词,例如example匹配url中任意位置出现的example
        ! 规则前有|表示url以该规则开头,例如|http://*.example.com/匹配example.com所有子域名的http协议
        ! 域名前有||表示匹配域名及子域名所有协议,例如||example.com匹配example.com所有域名所有协议
        ! 以上规则写好的情况下,如果再在前面加@@表示匹配规则的url不过代理,例如@@||example.com
        ! @@规则有高优先级,若你发现AutoProxy默认规则中某个url不应过代理,可自己写出相应规则并在前面加@@
        ! @规则有比@@更高的优先级,若发现在线规则中某个url应过代理却被@@,可自己写出相应规则并在前面加@

        ||example.com
        |http://ex.com/

        iplist编写规则如下,空白分隔:

        ip/mask: 表示由ip和掩码位数确定的ip段,例如192.168.1.101/30包括192.168.1.100~192.168.1.103四个ip
        ip|count: 表示由起始ip和个数确定的ip段,例如192.168.1.100|4包括192.168.1.100~192.168.1.103四个ip
        注意: iplist文件不支持注释,凡是符合上述两种格式的都会被认为是有效规则。

        10.0.0.0/24
        172.0.0.1|128

    智能代理
        智能代理是浏览器请求先转给wallproxy,再由wallproxy转给插件或其他代理。显然对于不需要代理的网址,自动代理是浏览器直接与目标网站通信,而智能代理是浏览器与wallproxy通信 + wallproxy与目标网站通信,有一些性能损失;再加上一些浏览器对于代理的处理不是很好,这种损失在某些时候就更明显。智能代理的好处是可以实现一些PAC无法实现的功能,以及为不支持PAC的浏览器提供代理选择功能。
        proxy.ini中与智能代理有关的内容为:

        [pac]
        enable = 3
        file = proxy.pac
        rulelist = https://autoproxy-gfwlist.googlecode.com/svn/trunk/gfwlist.txt|userlist.ini
        iplist =
        ;rulelist = !rulelist
        ;iplist = !iplist
        ;py_default = FORWARD|FORWARD|FORWARD

        [py_rulelist]
        GAE = https://autoproxy-gfwlist.googlecode.com/svn/trunk/gfwlist.txt|userlist.ini
        PAGE = forbid.ini

        [py_iplist]
        GAE = iplist.ini

        [forward]
        SSH = socks5://127.0.0.1:7070

        可以看到与“自动代理”基本差不多,区别是default、rulelist、iplist前面多了py_前缀,代理不是用PAC中“return”后字符串的格式而是一些变量名,以及多了[forward]节。
        wallproxy中有一些预定义变量名:
           * FORWARD:相当于PAC中的DIRECT,但如果设置了“[proxy]”,则相当于全局代理,另外如果转发失败的话,将自动改走GAE;
           * GAE:开启GAE后可用,相当于PAC中的PROXY *:8087;
           * PAAS:开启PAAS后可用,相当于PAC中的PROXY *:8088;
           * FORBID:返回403 Forbidden提示;
           * WEB:返回对应的WEB界面;
           * PAGE:返回misc目录下page.html作为模板渲染的内容,如果该文件不存在,返回空白;
        可以看到,PAC中能够通过“PROXY 111.111.111.111:8888”的方式定义一个第三方代理,如何在智能代理中实现类似的功能呢,答案就是[forward]小节,等号左边为变量名(注意不要与预定义变量冲突),右边为代理地址,这样定义后左边的变量名则可以用在[py_rulelist]和[py_iplist]了,满足规则的网址会自动走对应的代理。
        [forward]等号右边支持如下格式代理:

        ;定义一个socks5代理
        PROXY1 = socks5://127.0.0.1:7070
        ;定义一个socks4代理
        PROXY2 = socks4://127.0.0.1:7070
        ;定义一个https代理(对http也按https的方式处理)
        PROXY3 = https://127.0.0.1:7070
        ;定义一个http代理(也支持https)
        PROXY4 = http://127.0.0.1:7070
        ;定义一个hosts转发(以非代理方式把请求转给相应地址)
        PROXY5 = hosts://127.0.0.1:7070
        ;先走socks5代理再走http代理
        PROXY6 = "socks5://127.0.0.1:7070", "http://1111.111.111.111:8080"
        ;无代理(FORWARD是如果设置了全局代理就是全局代理,否则是无代理)
        DIRECT = ""

        PAC与智能代理并非互斥,可以在PAC中通过“PROXY *:8086”先走智能代理,再由智能代理走真正需要的代理或者屏蔽处理等;PAC与智能代理的规则列表也不是非得一一对应,可以在智能代理中只包含PAC中走“PROXY *:8086”的规则,但对这些规则再细分。


转自: https://code.google.com/p/wallproxy/wiki/PAC