代理是个好东西,帮你节省时间,减少麻烦。今天讲一个自动代理文件格式-PAC,它是微软发明的,1999年就提交到了IETF标准化组织,但后来就没有下文了,好在常见的浏览器(Firefox,IE,Safari)都实现了对PAC支持。利用PAC我们可以对某些特定站点或移动到特定的网络时选择特定的代理服务器来浏览网页,这解决了很多时候的不便利。
PAC的语法很简单,下面就是一个例子:
function FindProxyForURL(url, host) {
if (
shExpMatch(url,"*.mitbbs.com*") ||
shExpMatch(url,"*.pandora.com*") ||
shExpMatch(url,"*.popyard.org*") ||
shExpMatch(url,"*.wordpress.com*") ||
shExpMatch(url,"*.bullogger.com*")
)
{
return "SOCKS localhost:1080";
}
return "DIRECT";
}
把上面的代码保存成一个文本文件,然后配置浏览器使用这个文件,IE的详细设置教程请看:http://www.microsoft.com/technet/prodtechnol/ie/reskit/6/part6/c26ie6rk.mspx?mfr=true
Proxy Auto Config
什么是 Proxy Auto Config ?
首先,我们一定要知道什么是 Proxy?他的功用是什么?如果还不知道,可以参照这份文件。
而 PAC(Proxy Auto Config) 又是什么呢?它实际上是一个 Script;经由编写这个 Script,我们可以让系统判断在怎么样的情形下,要利用哪一台 Proxy 来进行联机。这样做主要的好处有:
1. 分散 Proxy 的流量,避免 Proxy Server 负载过高
2. 针对个别条件设定、加快浏览速度
3. 设定要求顺序,在某台 Proxy 无法联机时,可自动尝试别种联机方式
Proxy Auto Config File 的格式
基本上 Proxy Auto Config File(以下简称 PAC)是一个纯文字文件,他的语法采用 JavaScript;所以建议要学习编写 PAC 的人,最好先学习基本的 JavaScript。一个 PAC 档必需是单独的 JavaScript,其中不能包含任何 HTML 标签。
在 PAC 档中,一定要定义 Function FindProxyForURL 如下:
function FindProxyForURL( url, host )
{
...
}
如果使用了 PAC 档,则浏览器在接受我们要求的网址后,会去执行
ret = FindProxyForURL( url, host );
这样的指令。其中,url 是所要求网址的完整路径,host 是对方的计算机名称(就是在 :// 和 / 之中的部份);而 return 值 ret 则是 Proxy 的组态,它的格式有下列三种:
· DIRECT 直接联机而不透过 Proxy
· PROXY host:port 使用指定的 Proxy 伺服机
· SOCKS host:port 使用指定的 Socks 伺服机
比如说当浏览器得到的是 Proxy proxy.ncu.edu.tw:3128; Proxy proxy.csie.ncu.edu.tw:3128; DIRECT 的话,那浏览器会先尝试透过 proxy.ncu.edu.tw 来开启网页,如果无法使用,则尝试 proxy.csie.ncu.edu.tw,还是不行的话,就直接联机。
PAC 中特别的 Function
在 PAC 中,除了可以使用一般 JavaScript 的 Function 外,它还定义了一些特别的 Function 可以使用:
· isPlainHostName()
· dnsDomainIs()
· localHostOrDomainIs()
· isResolvable()
· isInNet()
· dnsResolve()
· myIpAddress()
· dnsDomainLevels()
· shExpMatch()
· weekdayRange()
· dateRange()
· timeRange()
isPlainHostName( host )
host 由网址取得的主机名称。
此 Function 会判断 host 是否为不包含网域 (Domain)。如果是,则 return true;如果包含,则 return false。
范例:
1. isPlainHostName("www") 会 return true
2. isPlainHostName("www.netscape.com") 会 return false
dnsDomainIs( host, domain )
host 由网址取得的主机名称。
domain 指定的网域。
此 Function 会判断 host 是否属于网域 domain。如果是,则 return true;否,则 return false。
范例:
1. dnsDomainIs("www.netscape.com", ".netscape.com") 会 return true
2. dnsDomainIs("www", ".netscape.com") 会 return false
3. dnsDomainIs("www.mcom.com", ".netscape.com") 会 return false
localHostOrDomainIs( host, hostdom )
host 由网址取得的主机名称。
hostdom 完整的网域名称。
此 Function 会判断 host 是否为 hostdom,或 host 是否为 hostdom 的主机名称。如果是,则 return true;否,则 return false。
范例:
1. localHostOrDomainIs("www.netscape.com", "www.netscape.com") 会 return true (完全相同)
2. localHostOrDomainIs("www", "www.netscape.com") 会 return true (主机名称相同)
3. localHostOrDomainIs("www.mcom.com", "www.netscape.com") 会 return false (网域不同)
4. localHostOrDomainIs("home.netscape.com", "www.netscape.com") 会 return false (主机名称不同)
isResolvable( host )
host 由网址取得的主机名称。
此 Function 会尝试透过 DNS 去解析 host,如果解析成功,则 return true;否则 return false。
范例:
1. isResolvable("www.netscape.com") 会 return true (除非 DNS 无法正常运作)
2. isResolvable("bogus.domain.foobar") 会 return false (除非真的冒出这个 domain 出来…)
isInNet( host, pattern, mask )
host 主机名称,可以是 Domain Name 或 IP。如果是 Domain Name,则会透过 DNS 查出 IP。
pattern IP。
mask对应于 pattern 的屏蔽。
此 Function 会 host 是否在指定的 IP 范围内,如果是,则 return true;否则 return false。
范例:
1. isInNet(host, "198.95.249.79", "255.255.255.255") 当 host 为 198.95.249.79 时,会 return true。
2. isInNet(host, "140.115.0.0", "255.255.0.0") 当 host 为 140.115.*.* 时,会 return true。
dnsResolve( host )
host 要透过 DNS 解晰的主机名称。
此 Function 会透过 DNS 去解析 host,return 值即为解析之结果。
范例:
1. dnsResolve("www.math.ncu.edu.tw") 会 return "140.115.25.9"。
myIpAddress()
此 Function 会 return 浏览器所在计算机之 IP 地址。
dnsDomainLevels( host )
host 由网址取得的主机名称。
此 Function 会 return host 的 Domain 层数(点的数目)。
范例:
1. dnsDomainLevels("www") 会 return 0。
2. dnsDomainLevels("www.netscape.com") 会 return 2。
shExpMatch( str, shexp )
str 要进行比对的字符串。
shexp 比对的条件。
此 Function 会比对 str 是否符合 shexp 的表示式(此表示式为 shell expression 而非 regular expressions)。如果是,则 return true;否则 return false。
范例:
1. shExpMatch("http://home.netscape.com/people/ari/index.html", "*/ari/*") 会 return true
2. shExpMatch("http://home.netscape.com/people/montulli/index.html", "*/ari/*") 会 return false
weekdayRange()、dateRange()、timeRange()
这三个 Function 的功用都是检查线在时间是否在指定范围内,用这些 Function 就可以设定分时段使用 Proxy Server。但由于较为繁琐,如有兴趣或需要,请参考原始文件。
范例
1.中央大学数学系之设定
2. function FindProxyForURL( url, host ){
3. if ( dnsDomainIs( host, "locahost" ) || dnsDomainIs( host, ".edu.tw" ) || isInNet( host, "140.0.0.0", "255.0.0.0" ) || isPlainHostName( host ) )
4. {
5. return "DIRECT; PROXY proxy.csie.ncu.edu.tw:3128;" + " PROXY cache.math.ncu.edu.tw:3128";
6. //localhost、 domain 是 .edu.tw、IP 为 140.*.*.* 或只有 Host Name
7. //则直接联机;如果直接联机不行,则尝试使用 proxy.csie 和 cache.math
8. }else if ( dnsDomainIs( host, ".tw" ) )
9. {
10. return "PROXY proxy.csie.ncu.edu.tw:3128;" + " PROXY cache.math.ncu.edu.tw:3128;" + " DIRECT";
11. //如果网域是 .tw,则依序尝试 proxy.csie、cache.math、直接联机
12. }else
13. return "PROXY cache.math.ncu.edu.tw:3128;" + " PROXY proxy.csie.ncu.edu.tw:3128;" + " DIRECT";
14. //其它:依序尝试 cache.math、proxy.csie、直接联机
15. }
16. 中央大学计算器中心提供之设定
17. function FindProxyForURL(url,host)
18. {
19. var RFC="1234567890-_qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM.";
20. for(var i=0;i < host.length;i++)
21. {
22. var c=host.charAt(i);
23. if(RFC.indexOf(c)==-1 && !(dnsDomainIs(host, ".cc") || dnsDomainIs(host,".tw"))) {
24. // alert(url+"--"+host);
25. return "PROXY dnsrelay.twnic.net.tw:3127";
26. }
27. }
28. if(host == 'auto.search.msn.com')
29. return "PROXY keyword.twnic.net.tw:80";
30.
31. if(dnsDomainIs(host, ".tw"))
32. {
33. return "DIRECT";
34. }
35. return "PROXY proxy.ncu.edu.tw:3128; PROXY cache.ncu.edu.tw:3128; DIRECT";
36. }
参考数据
· Navigator Proxy Auto-Config File Format
· Using the Client Autoconfiguration File
172.16.82.0 网段的客户端通过A代理走。
172.16.83.0 网段的客户端也通过A代理走。
172.16.84.0 网段的客户端通过B代理走。
不属于以上三个网段的地址,以上的代理设置不生效。
我们假定A代理的IP地址为172.16.1.1 B代理的IP地址为172.16.1.2。
function FindProxyForURL(url host)
{
if (shExpMatch(url "http://* ")) && (((isInNet(myIpAddress()"172.16.82.0""255.255.255.0")) || (isInNet(myIpAddress()"172.16.83.0""255.255.255.0"))))
return "PROXY 172.16.1.1:80";
else
if (shExpMatch(url "http://* ")) && (isInNet(myIpAddress()"172.16.84.0""255.255.255.0"))
return "PROXY 172.16.1.2:80";
else
{
if (shExpMatch(url "https://* ")) && (((isInNet(myIpAddress()"172.16.82.0""255.255.255.0")) || (isInNet(myIpAddress()"172.16.83.0""255.255.255.0"))))
return "PROXY 172.16.1.1:443";
else
if (shExpMatch(url "https://* ")) && (isInNet(myIpAddress()"172.16.84.0""255.255.255.0"))
return "PROXY 172.16.1.2:443";
else
return "DIRECT";
}
}
以上的script仅供您参考。
其中isInNet(myIpAddress()"172.16.84.0""255.255.255.0")指的是主机IP地址是172.16.84.0网段,shExpMatch(url "http://* ")指的是以http://结尾的网站。
squid 做HTTPS代理
使用iptbales+squid很容易实现http透明代理
如果要https的透明代理也只需要下面两个步骤就行了
1.生成测试用的证书:
openssl req -new -keyout /etc/squid/key.pem -nodes -x509 -days 365 -out /etc/squid/cert.pem
(如果要生成一个证书请求用于申请正式证书请用下面两个命令:
生成私钥 openssl genrsa -out key.pem 1024
生成待签名证书 openssl req -new -out req.csr -key key.pem
然后将req.csr文件中的内容提交给证书颁发机构。)
2. 在squid.conf相应地方添加
https_port 443 cert=/etc/squid/cert.pem /etc/squid/key.pem
如果出现下面的错误
The following error was encountered:
Invalid Request
Some aspect of the HTTP Request is invalid. Possible problems:
Missing or unknown request method
Missing URL
Missing HTTP Identifier (HTTP/1.0)
Request is too large
Content-Length missing for POST or PUT requests
Illegal character in hostname; underscores are not allowed
只需要在https_port 后面在加transparent
https_port 443 cert=/etc/squid/cert.pem /etc/squid/key.pem transparent