1.squid 访问控制

1.1.基本的访问控制元素

ACL元素是Squid的访问控制的基础。这里告诉你如何指定包括IP地址,端口号,主机名,和URL匹配等变量。每个ACL元素有个名字,在编写访问控制规则时需要引用它们。基本的ACL元素语法如下:

acl name type value1 value2 ...

例如:

acl Workstations src 10.0.0.0/16

#如果源地址是 10.0.0.0/16 的地址,将其定义为Workstations


在多数情况下,你能对一个ACL元素列举多个值。你也可以有多个ACL行使用同一个名字。例如,下列两行配置是等价的:

acl Http_ports port 80 8000 8080

等于:

acl Http_ports port 80

acl Http_ports port 8000

acl Http_ports port 8080

#定义一个Http_ports的名称,匹配端口号80 8000 8080


1.2.基本的ACL类型

1.2.1.ip地址

使用对象:src,dst,myip

squid在ACL里指定IP地址时,拥有强有力的语法。你能以子网,地址范围,域名等形式编写地址。squid支持标准IP地址写法(由”.”连接的4个小于256的数字)和无类域间路由规范。另外,假如你忽略掩码,squid会自动计算相应的掩码。例如,下例中的每组是相等的:

acl Foo src 172.16.44.21/255.255.255.255

acl Foo src 172.16.44.21/32

acl Foo src 172.16.44.21


acl Xyz src 172.16.55.32/255.255.255.248

acl Xyz src 172.16.55.32/28


acl Bar src 172.16.66.0/255.255.255.0

acl Bar src 172.16.66.0/24

acl Bar src 172.16.66.0


有时候你可能想列举多个相邻子网,在这样的情况下,通过指定地址范围很容易做到。例如:

acl Bar src 172.16.10.0-172.16.19.0/24

这等价但高效于下面的行:

acl Foo src 172.16.10.0/24

acl Foo src 172.16.11.0/24

acl Foo src 172.16.12.0/24

acl Foo src 172.16.13.0/24

acl Foo src 172.16.14.0/24

acl Foo src 172.16.15.0/24

acl Foo src 172.16.16.0/24

acl Foo src 172.16.18.0/24

acl Foo src 172.16.19.0/24


1.2.2 使用对象:srcdomain,dstdomain,和cache_host_domain指令

域名简单的就是DNS名字或区域。例如,下面是有效的域名:

www.squid-cache.org

squid-cache.org

org

域名ACL有点深奥,因为相对于匹配域名和子域有点微妙的差别。当ACL域名以"."开头,squid将它作为通配符,它匹配在该域的任何主机名,甚至域名自身。相反的,如果ACL域名不以"."开头,squid使用精确的字符串比较,主机名同样必须被严格检查。

域名匹配可能让人迷惑,所以请看第二个例子以便你能真正理解它。如下是两个稍微不同的ACL:

acl A dstdomain foo.com

acl B dstdomain .foo.com

用户对http://www.foo.com/的请求匹配ACL B,但不匹配A。ACL A要求严格的字符串匹配,然而ACL B里领头的点就像通配符。

另外,用户对http://foo.com/的请求同时匹配A和B。尽管在URL主机名里的foo.com前面没有字符,但ACL B里领头的点仍然导致一个匹配。


1.2.3.正则表达式

使用对象:srcdom_regex, dstdom_regex, url_regex, urlpath_regex, browser, referer_regex, ident_regex, proxy_auth_regex, req_mime_type, rep_mime_type

大量的ACL使用正则表达式来匹配字符串(完整的正则表达式参考,请见O'Reilly的Mastering Regular Expressions一书)。对squid来说,最常使用的正则表达式功能用以匹配字符串的开头或结尾。例如,^字符是特殊元字符,它匹配行或字符串的开头:

^http://

该正则表达式匹配任意以http://开头的URL。$也是特殊的元字符,因为它匹配行或字符串的结尾:

.jpg$

实际上,该示例也有些错误,因为.字符也是特殊元字符。它是匹配任意单个字符的通配符。我们实际想要的应该是:

\.jpg$

反斜杠对这个"."进行转义。该正则表达式匹配以.jpg结尾的任意字符串。假如你不使用^或$字符,正则表达式的行为就象标准子串搜索。它们匹配在字符串里任何位置出现的单词或词组。

对所有的squid正则表达式类,你可以使用大小写敏感的选项。匹配是默认大小写敏感的。为了大小写不敏感,在ACL类型后面使用-i选项。例如:

acl Foo url_regex -i ^http://www


1.2.4.TCP端口

使用对象:port,myport

该类型是相对的。值是个别的端口号或端口范围。回想一下TCP端口号是16位值,这样它的值必须大于0和小于65536。如下是一些示例:

acl Foo port 123

acl Bar port 1-1024


1.3.ACL类型

1.3.1.src

IP地址在访问控制元素里是最普遍使用的。大部分站点使用IP地址来控制客户允许或不允许访问Squid。src类型指客户源IP地址。也就是说,当src ACL出现在访问控制列表里时,squid将它与发布请求的客户IP地址进行比较。

正常情况下你允许来自内网中主机的请求,并阻塞其他的。例如,假如你的单位使用192.168.0.0子网,你可以这样指定ACL:

acl MyNetwork src 192.168.0.0

假如你有许多子网,你能在同一个acl行里面列举它们:

acl MyNetwork src 192.168.0.0 10.0.1.0/24 10.0.5.0/24 172.16.0.0/12

squid有许多其他ACL类型用以检查客户地址。srcdomain类型比较客户的完整可验证域名。它要求反向DNS查询,这可能会延缓处理该请求。srcdom_regex ACL是类似的,但它允许你使用正则表达式来匹配域名。最后,src_as类型比较客户的AS号。


1.3.2.dst

dst类型指向原始服务器(目标)IP地址。在某些情况下,你能使用该类型来阻止你的用户访问特定web站点。然而,在使用dst ACL时你须谨慎。大部分squid接受到的请求有原始服务器主机名。例如:

GET http://www.web-cache.com/ HTTP/1.0

这里,www.web-cache.com是主机名。当访问列表规则包含了dst元素时,squid必须找到该主机名的IP地址。假如squid的IP缓存包含了该主机名的有效接口,这条ACL被立即检测。否则,在DNS查询忙碌时,squid会延缓处理该请求。这对某些请求来说会造成延时。为了避免延时,你该尽可能的使用dstdomain ACL类型来代替dst。

如下是简单的dst ACL示例:

acl AdServers dst 1.2.3.0/24


1.3.3.dstdomain

在某些情况下,你发现基于名字的访问控制非常有用。你可以使用它们去阻塞对某些站点的访问,去控制squid如何转发请求,以及让某些响应不可缓存。dstdomain之所以非常有用,是因为它检查请求url里的主机名。

然而首先我想申明如下两行的不同:

acl A dst www.squid-cache.org

acl B dstdomain www.squid-cache.org

A实际上是IP地址ACL。当Squid解析配置文件时,它查询www.squid-cache.org的IP地址,并将它们存在内存里。它不保存名字。假如在squid运行时IP地址改变了,squid会继续使用旧的地址。

然而dstdomain ACL以域名形式存储,并非IP地址。当squid检查ACL B时,它对URL的主机名部分使用字符串比较功能。在该情形下,它并不真正关心是否www.squid-cache.org的IP地址改变了。

使用dstdomain ACL的主要问题是某些URL使用IP地址代替主机名。假如你的目标是使用dstdomain ACL来阻塞对某些站点的访问,聪明的用户能手工查询站点的IP地址,然后将它们放在URL里。例如,下面的2行URL带来同样的页面:

http://www.squid-cache.org/docs/FAQ/

http://206.168.0.9/docs/FAQ/

第一行能被dstdomain ACL轻易匹配,但第二行不能。这样,假如你依靠dstdomain ACL,你也该同样阻塞所有使用IP地址代替主机名的请求。


1.3.4.srcdomain

srcdomain ACL也有点麻烦。它要求对每个客户IP地址进行所谓的反向DNS查询。技术上,squid请求对该地址的DNS PTR记录。DNS的响应--完整可验证域名(FQDN)--是squid匹配ACL值的东西。(请参考O'Reilly's DNS and BIND找到更多关于DNS PTR记录的信息)

使用dst ACL,FQDN查询会导致延时。请求会被延缓处理直到FQDN响应返回。FQDN响应被缓存下来,所以srcdomain查询通常仅在客户首次请求时延时。

不幸的是,srcdomain查询有时不能工作。许多组织并没有保持他们的反向查询数据库与日更新。假如某地址没有PTR记录,ACL检查失败。在该情形下,请求可能会延时非常长时间(例如2分钟)直到DNS查询超时。假如你使用srcdomain ACL,请确认你自己的DNS in-addr.arpa区域配置正确并且在工作中。假如这样,你可以使用如下的ACL:

acl LocalHosts srcdomain .users.example.com


1.3.5.port

你很可能想使用port ACL来限制对某些原始服务器端口号的访问。就像我即将讲到的,squid其实不连接到某些服务,例如email和IRC服务。port ACL允许你定义单独的端口或端口范围。例如:

acl HTTPports port 80 8000-8010 8080

HTTP在设计上与其他协议类似,例如SMTP。这意味着聪明的用户通过转发email消息到SMTP服务器能欺骗squid。Email转发是垃圾邮件的主要原因之一,我们必须处理它们。历史上,垃圾邮件有真正的邮件服务器。然而近来,越来越多的垃圾邮件制造者使用开放HTTP代理来隐藏他们的踪迹。你肯定不想Squid被当成垃圾邮件转发器。假如是这样,你的IP地址很可能被许多邮件转发黑名单冻结(MAPS,ORDB,spamhaus等)。除email之外,还有其他许多TCP/IP服务是squid不与其通信的。这些包括IRC,Telnet,POP,和NNTP。你的针对端口的策略必须被配置成拒绝已知危险端口,并允许剩下的;或者允许已知安全端口,并拒绝剩下的。

我的态度比较保守,仅仅允许安全的端口。默认的squid.conf包含了下面的安全端口ACL:

acl Safe_ports port 80 # http

acl Safe_ports port 21 # ftp

acl Safe_ports port 443 563 # https, snews

acl Safe_ports port 70 # gopher

acl Safe_ports port 210 # wais

acl Safe_ports port 1025-65535 # unregistered ports

acl Safe_ports port 280 # http-mgmt

acl Safe_ports port 488 # gss-http

acl Safe_ports port 591 # filemaker

acl Safe_ports port 777 # multiling http

http_access deny !Safe_ports

这是个较明智的配置。它允许用户连接到任何非特权端口(1025-65535),但仅仅指定的特权端口可以被连接。假如你的用户试图访问某个URL如下:http://www.lrrr.org:123/,squid会返回访问拒绝错误消息。在某些情形下,为了让你的用户满意,你可能需要增加另外的端口号。

宽松的做法是,拒绝对特别危险的端口的访问。Squid FAQ包括了如下示例:

acl Dangerous_ports 7 9 19 22 23 25 53 109 110 119

http_access deny Dangerous_ports


使用Dangerous_ports的弊端是squid对几乎每个请求都要搜索整个列表。这对CPU造成了额外的负担。大多数情况下,99%到达squid的请求是对80端口的,它不出现在危险端口列表里。所有请求对该表的搜索不会导致匹配。当然,整数比较是快速的操作,不会显然影响性能


1.3.6.method

method ACL指HTTP请求方法。GET是典型的最常用方法,接下来是POST,PUT,和其他。下例说明如何使用method ACL:

acl Uploads method PUT POST

Squid知道下列标准HTTP方法:GET, POST, PUT, HEAD, CONNECT, TRACE, OPTIONS和DELETE。另外,squid了解下列来自WEBDAV规范,RFC 2518的方法:PROPFIND, PROPPATCH, MKCOL, COPY, MOVE, LOCK, UNLOCK。某些Microsoft产品使用非标准的WEBDAV方法,所以squid也了解它们:BMOVE, BDELETE, BPROPFIND。最后,你可以在extension_methods指令里配置squid去理解其他的请求方法。请见附录A。

注意CONNECT方法非常特殊。它是用于通过HTTP代理来封装某种请求的方法(请见RFC 2817:Upgrading to TLS Within HTTP/1.1)。在处理CONNECT方法和远程服务器的端口号时应特别谨慎。就像前面章节讲过的一样,你不希望squid连接到某些远程服务。你该限制CONNECT方法仅仅能连接到HTTPS/SSL或NNTPS端口(443和563)。默认的squid.conf这样做:

acl CONNECT method CONNECT

acl SSL_ports 443 563

http_access allow CONNECT SSL_ports

http_access deny CONNECT


在该配置里,squid仅仅允许加密请求到端口443(HTTPS/SSL)和563(NNTPS)。CONNECT方法对其他端口的请求都被拒绝。

PURGE是另一个特殊的请求方法。它是Squid的专有方法,没有在任何RFC里定义。它让管理员能强制删除缓存对象。既然该方法有些危险,squid默认拒绝PURGE请求,除非你定义了ACL引用了该方法。否则,任何能访问cache者也许能够删除任意缓存对象。我推荐仅仅允许来自localhost的PURGE:

acl Purge method PURGEacl Localhost src 127.0.0.1

http_access allow Purge Localhost

http_access deny Purge


1.3.7.proto

该类型指URI访问(或传输)协议。如下是有效值:http, https (same as HTTP/TLS), ftp, gopher, urn, whois, 和cache_object。也就是说,这些是被squid支持的URL机制名字。例如,假如你想拒绝所有的FTP请求,你可以使用下列指令:

acl FTP proto FTP

http_access deny FTP

cache_object机制是squid的特性。它用于访问squid的缓存管理接口,我将在14.2章讨论它。不幸的是,它并非好名字,可能会被改变。

默认的squid.conf文件有许多行限制缓存管理访问:

acl Manager proto cache_object

acl Localhost src 127.0.0.1

http_access allow Manager Localhost

http_access deny Manager

这些配置行仅允许来自本机地址的缓存管理请求,所有其他的缓存管理请求被拒绝。这意味着在squid机器上有帐号的人,能访问到潜在的敏感缓存管理信息。你也许想修改缓存管理访问控制,或对某些页面使用密码保护


1.3.8.time

time ACL允许你控制基于时间的访问,时间为每天中的具体时间,和每周中的每天。日期以单字母来表示,见如下表。时间以24小时制来表示。开始时间必须小于结束时间,这样在编写跨越0点的time ACL时可能有点麻烦。

Code Day

-----------------

S Sunday

M Monday

T Tuesday

W Wednesday

H Thursday

F Friday

A Saturday

D All weekdays (M-F)


-----------------

日期和时间由localtime()函数来产生。请确认你的计算机位于正确的时区,你也该让你的时钟与标准时间同步。

为了编写time ACL来匹配你的工作时间,你可以这样写:

acl Working_hours MTWHF 08:00-17:00

or:

acl Working_hours D 08:00-17:00

让我们看一个麻烦的例子。也许你是某个ISP,在下午8点到早上4点这段不忙的时间内放松访问。既然该时间跨越子夜,你不能编写“20:00-04:00”。代替的,你需要把它们分成两个ACL来写,或者使用否定机制来定义非忙时。例如:

acl Offpeak1 20:00-23:59

acl Offpeak2 00:00-04:00

http_access allow Offpeak1 ...

http_access allow Offpeak2 ...

另外,你可以这样写:

acl Peak 04:00-20:00

http_access allow !Peak ...

尽管squid允许,你也不应该在同一个time ACL里放置多个日期和时间范围列表。对这些ACL的解析不一定是你想象的那样。例如,假如你输入:

acl Blah time M 08:00-10:00 W 09:00-11:00

实际能做到的是:

acl Blah time MW 09:00-11:00

解析仅仅使用最后一个时间范围。正确的写法是,将它们写进两行:

acl Blah time M 08:00-10:00

acl Blah time W 09:00-11:00


1.3.9.maxconn

maxconn ACL指来自客户IP地址的大量同时连接。某些squid管理员发现这是个有用的方法,用以阻止用户滥用代理或者消耗过多资源。

maxconn ACL在请求超过指定的数量时,会匹配这个请求。因为这个理由,你应该仅仅在deny规则里使用maxconn。考虑如下例子:

acl OverConnLimit maxconn 4

http_access deny OverConnLimit

在该情况中,squid允许来自每个IP地址的同时连接数最大为4个。当某个客户发起第五个连接时,OverConnLimit ACL被匹配,http_access规则拒绝该请求。



1.3.10.srcdom_regex

srcdom_regex ACL允许你使用正则表达式匹配客户域名。这与srcdomain ACL相似,它使用改进的的子串匹配。相同的限制是:某些客户地址不能反向解析到域名。作为示例,下面的ACL匹配以dhcp开头的主机名:

acl DHCPUser srcdom_regex -i ^dhcp

因为领头的^符号,该ACL匹配主机名dhcp12.example.com,但不匹配host12.dhcp.example.com。


1.3.11.dstdom_regex

dstdom_regex ACL也与dstdomain相似。下面的例子匹配以www开头的主机名:

acl WebSite dstdom_regex -i ^www\.

如下是另一个有用的正则表达式,用以匹配在URL主机名里出现的IP地址:

acl IPaddr dstdom_regex [0-9]$

这样可以工作,因为squid要求URL主机名完全可验证。既然全局顶级域名中没有以数字结尾的,该ACL仅仅匹配IP地址,它以数字结尾。


1.3.12.url_regex

url_regex ACL用于匹配请求URL的任何部分,包括传输协议和原始服务器主机名。例如,如下ACL匹配从FTP服务器的MP3文件请求:

acl FTPMP3 url_regex -i ^ftp://.*\.mp3$


1.3.13.urlpath_regex

urlpath_regex与url_regex非常相似,不过传输协议和主机名不包含在匹配条件里。这让某些类型的检测非常容易。例如,假设你必须拒绝URL里的"sex",但仍允许在主机名里含有"sex"的请求,那么这样做:

acl Sex urlpath_regex sex

另一个例子,假如你想特殊处理cgi-bin请求,你能这样捕获它们:

acl CGI1 urlpath_regex ^/cgi-bin

当然,CGI程序并非总在/cgi-bin/目录下,这样你应该编写其他的ACL来捕获它们。


1.3.14.browser

大部分HTTP请求包含了User-Agent头部。该头部的值典型如下:

Mozilla/4.51 [en] (X11; I; Linux 2.2.5-15 i686)

browser ACL对user-agent头执行正则表达式匹配。例如,拒绝不是来自Mozilla浏览器的请求,可以这样写:

acl Mozilla browser Mozilla

http_access deny !Mozilla

在使用browser ACL之前,请确认你完全理解cache接受到的User-Agent字符串。某些user-agent与它们的来源相关。甚至squid可以重写它转发的请求的User-Agent头部。某些浏览器例如Opera和KDE的Konqueror,用户可以对不同的原始服务器发送不同的user-agent字串,或者干脆忽略它们。