ACL元素是Squid的訪問(wèn)控制的基礎(chǔ)。這里告訴你如何指定包括IP地址,端口號(hào),主機(jī)名,和URL匹配等變量。每個(gè)ACL元素有個(gè)名字,在編寫訪問(wèn)控制規(guī)則時(shí)需要引用它們?;镜腁CL元素語(yǔ)法如下:
acl name type value1 value2 ...
例如:
acl Workstations src 10.0.0.0/16
在多數(shù)情況下,你能對(duì)一個(gè)ACL元素列舉多個(gè)值。你也可以有多個(gè)ACL行使用同一個(gè)名字。例如,下列兩行配置是等價(jià)的:
acl Http_ports port 80 8000 8080 acl Http_ports port 80 acl Http_ports port 8000 acl Http_ports port 8080
Squid大約有25個(gè)不同的ACL類型,其中的一些有通用基本類型。例如,src和dst ACL使用IP地址作為它們的基本類型。為避免冗長(zhǎng),我首先描述基本類型,然后在接下來(lái)章節(jié)里描述每種ACL類型。
使用對(duì)象:src,dst,myip
squid在ACL里指定IP地址時(shí),擁有強(qiáng)有力的語(yǔ)法。你能以子網(wǎng),地址范圍,域名等形式編寫地址。squid支持標(biāo)準(zhǔn)IP地址寫法(由”.”連接的4個(gè)小于256的數(shù)字)和無(wú)類域間路由規(guī)范。另外,假如你忽略掩碼,squid會(huì)自動(dòng)計(jì)算相應(yīng)的掩碼。例如,下例中的每組是相等的:
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
當(dāng)你指定掩碼時(shí),squid會(huì)檢查你的工作。如果你的掩碼在IP地址的非零位之外,squid會(huì)告警。例如,下列行導(dǎo)致告警:
acl Foo src 127.0.0.1/8 aclParseIpData: WARNING: Netmask masks away part of the specified IP in 'Foo'
這里的問(wèn)題是/8掩碼(255.0.0.0)在最后三個(gè)字節(jié)里都是零值,但是IP地址127.0.0.1不是這樣的。squid警告你這個(gè)問(wèn)題,以便你消除歧義。正確的寫法是:
acl Foo src 127.0.0.1/32
or:
acl Foo src 127.0.0.0/8
有時(shí)候你可能想列舉多個(gè)相鄰子網(wǎng),在這樣的情況下,通過(guò)指定地址范圍很容易做到。例如:
acl Bar src 172.16.10.0-172.16.19.0/24
這等價(jià)但高效于下面的行:
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
注意使用IP地址范圍,掩碼只能取一個(gè)。你不能為范圍里的地址設(shè)置多個(gè)不同掩碼。 你也能在IP ACL里指定主機(jī)名,例如:
acl Squid dst www.squid-cache.org
squid在啟動(dòng)時(shí),將主機(jī)名轉(zhuǎn)換成IP地址。一旦啟動(dòng),squid不會(huì)對(duì)主機(jī)名的地址發(fā)起第二次DNS查詢。這樣,假如在squid運(yùn)行中地址已改變,squid不會(huì)注意到。
假如主機(jī)名被解析成多個(gè)IP地址,squid將每一個(gè)增加到ACL里。注意你也可以對(duì)主機(jī)名使用網(wǎng)絡(luò)掩碼。
在基于地址的ACL里使用主機(jī)名通常是壞做法。squid在初始化其他組件之前,先解析配置文件,所以這些DNS查詢不使用squid的非阻塞IP緩存接口。代替的,它們使用阻塞機(jī)制的gethostbyname()函數(shù)。這樣,將ACL主機(jī)名轉(zhuǎn)換到IP地址的過(guò)程會(huì)延緩squid的啟動(dòng)。除非絕對(duì)必要,請(qǐng)?jiān)趕rc,dst,和myip ACL里避免使用主機(jī)名。
squid以一種叫做splay tree的數(shù)據(jù)結(jié)構(gòu)在內(nèi)存里存儲(chǔ)IP地址ACL(請(qǐng)見(jiàn)http://www.link.cs.cmu.edu/splay/)。splay tree有一些有趣的自我調(diào)整的特性,其中之一是在查詢發(fā)生時(shí),列表會(huì)自動(dòng)糾正它自己的位置。當(dāng)某個(gè)匹配元素在列表里發(fā)現(xiàn)時(shí),該元素變成新的樹根。在該方法中,最近參考的條目會(huì)移動(dòng)到樹的頂部,這減少了將來(lái)查詢的時(shí)間。
屬于同一ACL元素的所有的子網(wǎng)和范圍不能重迭。如果有錯(cuò)誤,squid會(huì)警告你。例如,如下不被允許:
acl Foo src 1.2.3.0/24 acl Foo src 1.2.3.4/32
它導(dǎo)致squid在cache.log里打印警告:
WARNING: '1.2.3.4' is a subnetwork of '1.2.3.0/255.255.255.0' WARNING: because of this '1.2.3.4' is ignored to keep splay tree searching predictable WARNING: You should probably remove '1.2.3.4' from the ACL named 'Foo'
在該情形下,你需要修正這個(gè)問(wèn)題,可以刪除其中一個(gè)ACL值,或者將它們放置在不同的ACL列表中。
使用對(duì)象:srcdomain,dstdomain,和cache_host_domain指令
域名簡(jiǎn)單的就是DNS名字或區(qū)域。例如,下面是有效的域名:
www.squid-cache.org squid-cache.org org
域名ACL有點(diǎn)深?yuàn)W,因?yàn)橄鄬?duì)于匹配域名和子域有點(diǎn)微妙的差別。當(dāng)ACL域名以"."開(kāi)頭,squid將它作為通配符,它匹配在該域的任何主機(jī)名,甚至域名自身。相反的,如果ACL域名不以"."開(kāi)頭,squid使用精確的字符串比較,主機(jī)名同樣必須被嚴(yán)格檢查。
表6-1顯示了squid的匹配域和主機(jī)名的規(guī)則。第一列顯示了取自URL請(qǐng)求的主機(jī)名(或者srcdomain ACL的客戶主機(jī)名)。第二列指明是否主機(jī)名匹配lrrr.org。第三列顯示是否主機(jī)名匹配.lrrr.org ACL。你能看到,唯一的不同在第二個(gè)實(shí)例里。
Table 6-1. Domain name matching
URL hostname | Matches ACL lrrr.org? | Matches ACL .lrrr.org? |
lrrr.org | Yes | Yes |
i.am.lrrr.org | No | Yes |
iamlrrr.org | No | No |
域名匹配可能讓人迷惑,所以請(qǐng)看第二個(gè)例子以便你能真正理解它。如下是兩個(gè)稍微不同的ACL:
acl A dstdomain foo.com acl B dstdomain .foo.com
用戶對(duì)http://www.foo.com/的請(qǐng)求匹配ACL B,但不匹配A。ACL A要求嚴(yán)格的字符串匹配,然而ACL B里領(lǐng)頭的點(diǎn)就像通配符。
另外,用戶對(duì)http://foo.com/的請(qǐng)求同時(shí)匹配A和B。盡管在URL主機(jī)名里的foo.com前面沒(méi)有字符,但ACL B里領(lǐng)頭的點(diǎn)仍然導(dǎo)致一個(gè)匹配。
squid使用splay tree的數(shù)據(jù)結(jié)構(gòu)來(lái)存儲(chǔ)域名ACL,就像它處理IP地址一樣。然而,squid的域名匹配機(jī)制給splay tree提供了一個(gè)有趣的問(wèn)題。splay tree技術(shù)要求唯一鍵去匹配任意特定搜索條目。例如,讓我們假設(shè)搜索條目是i.am.lrrr.org。該主機(jī)名同時(shí)匹配.lrrr.org和.am.lrrr.org。事實(shí)上就是兩個(gè)ACL值匹配同一個(gè)主機(jī)名擾亂了splay機(jī)制。換句話說(shuō),在配置文件里放置如下語(yǔ)句是錯(cuò)誤的:
acl Foo dstdomain .lrrr.org .am.lrrr.org
假如你這樣做,squid會(huì)產(chǎn)生如下警告信息:
WARNING: '.am.lrrr.org' is a subdomain of '.lrrr.org' WARNING: because of this '.am.lrrr.org' is ignored to keep splay tree searching predictable WARNING: You should probably remove '.am.lrrr.org' from the ACL named 'Foo'
在該情況下你應(yīng)遵循squid的建議。刪除其中一條相關(guān)的域名,以便squid明確知道你的意圖。注意你能在不同的ACL里任意使用這樣的域名:
acl Foo dstdomain .lrrr.org acl Bar dstdomain .am.lrrr.org
這是允許的,因?yàn)槊總€(gè)命名ACL使用它自己的splay tree.
使用對(duì)象:ident,proxy_auth
該類型的ACL被設(shè)計(jì)成匹配用戶名。squid可能通過(guò)RFC 1413 ident協(xié)議或者通過(guò)HTTP驗(yàn)證頭來(lái)獲取用戶名。用戶名必須被嚴(yán)格匹配。例如,bob不匹配bobby。squid也有相關(guān)的ACL對(duì)用戶名使用正則表達(dá)式匹配(ident_regex和proxy_auth_regex)。
你可以使用單詞"REQUIRED"作為特殊值去匹配任意用戶名。假如squid不能查明用戶名,ACL不匹配。當(dāng)使用基于用戶名的訪問(wèn)控制時(shí),squid通常這樣配置。
使用對(duì)象:srcdom_regex, dstdom_regex, url_regex, urlpath_regex, browser, referer_regex, ident_regex, proxy_auth_regex, req_mime_type, rep_mime_type
大量的ACL使用正則表達(dá)式來(lái)匹配字符串(完整的正則表達(dá)式參考,請(qǐng)見(jiàn)O'Reilly的Mastering Regular Expressions一書)。對(duì)squid來(lái)說(shuō),最常使用的正則表達(dá)式功能用以匹配字符串的開(kāi)頭或結(jié)尾。例如,^字符是特殊元字符,它匹配行或字符串的開(kāi)頭:
^http://
該正則表達(dá)式匹配任意以http://開(kāi)頭的URL。$也是特殊的元字符,因?yàn)樗ヅ湫谢蜃址慕Y(jié)尾:
.jpg$
實(shí)際上,該示例也有些錯(cuò)誤,因?yàn)?字符也是特殊元字符。它是匹配任意單個(gè)字符的通配符。我們實(shí)際想要的應(yīng)該是:
\.jpg$
反斜杠對(duì)這個(gè)"."進(jìn)行轉(zhuǎn)義。該正則表達(dá)式匹配以.jpg結(jié)尾的任意字符串。假如你不使用^或$字符,正則表達(dá)式的行為就象標(biāo)準(zhǔn)子串搜索。它們匹配在字符串里任何位置出現(xiàn)的單詞或詞組。
對(duì)所有的squid正則表達(dá)式類,你可以使用大小寫敏感的選項(xiàng)。匹配是默認(rèn)大小寫敏感的。為了大小寫不敏感,在ACL類型后面使用-i選項(xiàng)。例如:
acl Foo url_regex -i ^http://www
使用對(duì)象:port,myport
該類型是相對(duì)的。值是個(gè)別的端口號(hào)或端口范圍?;叵胍幌耇CP端口號(hào)是16位值,這樣它的值必須大于0和小于65536。如下是一些示例:
acl Foo port 123 acl Bar port 1-1024
使用對(duì)象:src_as,dst_as
Internet路由器使用自主系統(tǒng)(AS)號(hào)來(lái)創(chuàng)建路由表。基本上,某個(gè)AS號(hào)指向被同一組織管理的IP網(wǎng)絡(luò)范圍。例如,我的ISP分配了如下網(wǎng)絡(luò)塊:134.116.0.0/16, 137.41.0.0/16, 206.168.0.0/16,和其他更多。在Internet路由表里,這些網(wǎng)絡(luò)被公布為屬于AS 3404。當(dāng)路由器轉(zhuǎn)發(fā)包時(shí),它們典型的選擇經(jīng)過(guò)最少AS的路徑。假如這些對(duì)你不重要,請(qǐng)不必關(guān)注它們。AS基礎(chǔ)的ACL僅僅被網(wǎng)絡(luò)gurus使用。
如下是基于AS的類型如何工作的:當(dāng)squid首先啟動(dòng)時(shí),它發(fā)送一條特殊的查詢到某個(gè)whois服務(wù)器。查詢語(yǔ)句基本是:“告訴我哪個(gè)IP網(wǎng)絡(luò)屬于該AS號(hào)”。這樣的信息被RADB收集和管理。一旦Squid接受到IP網(wǎng)絡(luò)列表,它相似的將它們作為IP基礎(chǔ)的ACL對(duì)待?;贏S的類型僅僅在ISP將他們的RADB信息保持與日更新時(shí)才工作良好。某些ISP更新RADB比其他人做得更好;而許多根本不更新它。請(qǐng)注意squid僅僅在啟動(dòng)或者reconfigure時(shí)才將AS號(hào)轉(zhuǎn)換為網(wǎng)絡(luò)地址。假如ISP更新了它的RADB接口,除非你重啟或者重配置squid,squid不會(huì)知道這個(gè)改變。
另外的情況是,在你的squid啟動(dòng)時(shí),RADB可能不可到達(dá)。假如Squid不能聯(lián)系上RADB服務(wù)器,它從訪問(wèn)控制配置里刪除AS接口。默認(rèn)的whois服務(wù)器是whois.ra.net,對(duì)許多用戶來(lái)說(shuō)太遙遠(yuǎn)了而不可信賴。
現(xiàn)在我們能把焦點(diǎn)放在ACL類型自身上。我在這里按照重要性的降序來(lái)列舉它們。
IP地址在訪問(wèn)控制元素里是最普遍使用的。大部分站點(diǎn)使用IP地址來(lái)控制客戶允許或不允許訪問(wèn)Squid。src類型指客戶源IP地址。也就是說(shuō),當(dāng)src ACL出現(xiàn)在訪問(wèn)控制列表里時(shí),squid將它與發(fā)布請(qǐng)求的客戶IP地址進(jìn)行比較。
正常情況下你允許來(lái)自內(nèi)網(wǎng)中主機(jī)的請(qǐng)求,并阻塞其他的。例如,假如你的單位使用192.168.0.0子網(wǎng),你可以這樣指定ACL:
acl MyNetwork src 192.168.0.0
假如你有許多子網(wǎng),你能在同一個(gè)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類型比較客戶的完整可驗(yàn)證域名。它要求反向DNS查詢,這可能會(huì)延緩處理該請(qǐng)求。srcdom_regex ACL是類似的,但它允許你使用正則表達(dá)式來(lái)匹配域名。最后,src_as類型比較客戶的AS號(hào)。
dst類型指向原始服務(wù)器(目標(biāo))IP地址。在某些情況下,你能使用該類型來(lái)阻止你的用戶訪問(wèn)特定web站點(diǎn)。然而,在使用dst ACL時(shí)你須謹(jǐn)慎。大部分squid接受到的請(qǐng)求有原始服務(wù)器主機(jī)名。例如:
GET http://www.web-cache.com/ HTTP/1.0
這里,www.web-cache.com是主機(jī)名。當(dāng)訪問(wèn)列表規(guī)則包含了dst元素時(shí),squid必須找到該主機(jī)名的IP地址。假如squid的IP緩存包含了該主機(jī)名的有效接口,這條ACL被立即檢測(cè)。否則,在DNS查詢忙碌時(shí),squid會(huì)延緩處理該請(qǐng)求。這對(duì)某些請(qǐng)求來(lái)說(shuō)會(huì)造成延時(shí)。為了避免延時(shí),你該盡可能的使用dstdomain ACL類型來(lái)代替dst。
如下是簡(jiǎn)單的dst ACL示例:
acl AdServers dst 1.2.3.0/24
請(qǐng)注意,dst ACL存在的問(wèn)題是,你試圖允許或拒絕訪問(wèn)的原始服務(wù)器可能會(huì)改變它的IP地址。假如你不關(guān)心這樣的改變,那就不必麻煩去升級(jí)squid.conf。你可以在acl行里放上主機(jī)名,但那樣會(huì)延緩啟動(dòng)速度。假如你的ACL需要許多主機(jī)名,你也許該預(yù)處理配置文件,將主機(jī)名轉(zhuǎn)換成IP地址。
myip類型指Squid的IP地址,它被客戶連接。當(dāng)你在squid機(jī)上運(yùn)行netstat -n時(shí),你見(jiàn)到它們位于本地地址列。大部分squid安裝不使用該類型。通常所有的客戶連接到同一個(gè)IP地址,所以該ACL元素僅僅當(dāng)系統(tǒng)有多個(gè)IP地址時(shí)才有用。
為了理解myip為何有用,考慮某個(gè)有兩個(gè)子網(wǎng)的公司網(wǎng)絡(luò)。在子網(wǎng)1的用戶是程序員和工程師。子網(wǎng)2包括會(huì)計(jì),市場(chǎng)和其他管理部門。這樣情況下的squid有三個(gè)網(wǎng)絡(luò)接口:一個(gè)連接子網(wǎng)1,一個(gè)連接子網(wǎng)2,第三個(gè)連接到外部因特網(wǎng)。
Figure 6-1. An application of the myip ACL
當(dāng)正確的配置時(shí),所有在子網(wǎng)1的用戶連接到squid位于該子網(wǎng)的IP地址,類似的,子網(wǎng)2的用戶連接到squid的第二個(gè)IP地址。這樣你就可以給予子網(wǎng)1的技術(shù)部員工完全的訪問(wèn)權(quán),然而限制管理部門的員工僅僅能訪問(wèn)工作相關(guān)的站點(diǎn)。ACL可能如下:
acl Eng myip 172.16.1.5 acl Admin myip 172.16.2.5
然而請(qǐng)注意,使用該機(jī)制你必須特別小心,阻止來(lái)自某個(gè)子網(wǎng)的用戶連接squid位于另一子網(wǎng)的IP地址。否則,在會(huì)計(jì)和市場(chǎng)子網(wǎng)的聰明的用戶,能夠通過(guò)技術(shù)部子網(wǎng)進(jìn)行連接,從而繞過(guò)你的限制。
在某些情況下,你發(fā)現(xiàn)基于名字的訪問(wèn)控制非常有用。你可以使用它們?nèi)プ枞麑?duì)某些站點(diǎn)的訪問(wèn),去控制squid如何轉(zhuǎn)發(fā)請(qǐng)求,以及讓某些響應(yīng)不可緩存。dstdomain之所以非常有用,是因?yàn)樗鼨z查請(qǐng)求url里的主機(jī)名。然而首先我想申明如下兩行的不同:
acl A dst www.squid-cache.org acl B dstdomain www.squid-cache.org
A實(shí)際上是IP地址ACL。當(dāng)Squid解析配置文件時(shí),它查詢www.squid-cache.org的IP地址,并將它們存在內(nèi)存里。它不保存名字。假如在squid運(yùn)行時(shí)IP地址改變了,squid會(huì)繼續(xù)使用舊的地址。
然而dstdomain ACL以域名形式存儲(chǔ),并非IP地址。當(dāng)squid檢查ACL B時(shí),它對(duì)URL的主機(jī)名部分使用字符串比較功能。在該情形下,它并不真正關(guān)心是否www.squid-cache.org的IP地址改變了。
使用dstdomain ACL的主要問(wèn)題是某些URL使用IP地址代替主機(jī)名。假如你的目標(biāo)是使用dstdomain ACL來(lái)阻塞對(duì)某些站點(diǎn)的訪問(wèn),聰明的用戶能手工查詢站點(diǎn)的IP地址,然后將它們放在URL里。例如,下面的2行URL帶來(lái)同樣的頁(yè)面:
http://www.squid-cache.org/docs/FAQ/ http://206.168.0.9/docs/FAQ/
第一行能被dstdomain ACL輕易匹配,但第二行不能。這樣,假如你依靠dstdomain ACL,你也該同樣阻塞所有使用IP地址代替主機(jī)名的請(qǐng)求。請(qǐng)見(jiàn)6.3.8章節(jié)。
srcdomain ACL也有點(diǎn)麻煩。它要求對(duì)每個(gè)客戶IP地址進(jìn)行所謂的反向DNS查詢。技術(shù)上,squid請(qǐng)求對(duì)該地址的DNS PTR記錄。DNS的響應(yīng)--完整可驗(yàn)證域名(FQDN)--是squid匹配ACL值的東西。(請(qǐng)參考O'Reilly's DNS and BIND找到更多關(guān)于DNS PTR記錄的信息)使用dst ACL,FQDN查詢會(huì)導(dǎo)致延時(shí)。請(qǐng)求會(huì)被延緩處理直到FQDN響應(yīng)返回。FQDN響應(yīng)被緩存下來(lái),所以srcdomain查詢通常僅在客戶首次請(qǐng)求時(shí)延時(shí)。
不幸的是,srcdomain查詢有時(shí)不能工作。許多組織并沒(méi)有保持他們的反向查詢數(shù)據(jù)庫(kù)與日更新。假如某地址沒(méi)有PTR記錄,ACL檢查失敗。在該情形下,請(qǐng)求可能會(huì)延時(shí)非常長(zhǎng)時(shí)間(例如2分鐘)直到DNS查詢超時(shí)。假如你使用srcdomain ACL,請(qǐng)確認(rèn)你自己的DNS in-addr.arpa區(qū)域配置正確并且在工作中。假如這樣,你可以使用如下的ACL:
acl LocalHosts srcdomain .users.example.com
你很可能想使用port ACL來(lái)限制對(duì)某些原始服務(wù)器端口號(hào)的訪問(wèn)。就像我即將講到的,squid其實(shí)不連接到某些服務(wù),例如email和IRC服務(wù)。port ACL允許你定義單獨(dú)的端口或端口范圍。例如:
acl HTTPports port 80 8000-8010 8080
HTTP在設(shè)計(jì)上與其他協(xié)議類似,例如SMTP。這意味著聰明的用戶通過(guò)轉(zhuǎn)發(fā)email消息到SMTP服務(wù)器能欺騙squid。Email轉(zhuǎn)發(fā)是垃圾郵件的主要原因之一,我們必須處理它們。歷史上,垃圾郵件有真正的郵件服務(wù)器。然而近來(lái),越來(lái)越多的垃圾郵件制造者使用開(kāi)放HTTP代理來(lái)隱藏他們的蹤跡。你肯定不想Squid被當(dāng)成垃圾郵件轉(zhuǎn)發(fā)器。假如是這樣,你的IP地址很可能被許多郵件轉(zhuǎn)發(fā)黑名單凍結(jié)(MAPS,ORDB,spamhaus等)。除email之外,還有其他許多TCP/IP服務(wù)是squid不與其通信的。這些包括IRC,Telnet,POP,和NNTP。你的針對(duì)端口的策略必須被配置成拒絕已知危險(xiǎn)端口,并允許剩下的;或者允許已知安全端口,并拒絕剩下的。
我的態(tài)度比較保守,僅僅允許安全的端口。默認(rèn)的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
這是個(gè)較明智的配置。它允許用戶連接到任何非特權(quán)端口(1025-65535),但僅僅指定的特權(quán)端口可以被連接。假如你的用戶試圖訪問(wèn)某個(gè)URL如下:http://www.lrrr.org:123/,squid會(huì)返回訪問(wèn)拒絕錯(cuò)誤消息。在某些情形下,為了讓你的用戶滿意,你可能需要增加另外的端口號(hào)。
寬松的做法是,拒絕對(duì)特別危險(xiǎn)的端口的訪問(wèn)。Squid FAQ包括了如下示例:
acl Dangerous_ports 7 9 19 22 23 25 53 109 110 119 http_access deny Dangerous_ports
使用Dangerous_ports的弊端是squid對(duì)幾乎每個(gè)請(qǐng)求都要搜索整個(gè)列表。這對(duì)CPU造成了額外的負(fù)擔(dān)。大多數(shù)情況下,99%到達(dá)squid的請(qǐng)求是對(duì)80端口的,它不出現(xiàn)在危險(xiǎn)端口列表里。所有請(qǐng)求對(duì)該表的搜索不會(huì)導(dǎo)致匹配。當(dāng)然,整數(shù)比較是快速的操作,不會(huì)顯然影響性能。
(譯者注:這里的意思是,兩者都要對(duì)列表進(jìn)行搜索和匹配。在第一種情況下,它搜索安全端口列表并匹配80,顯然第一個(gè)元素就匹配成功了。而第二種情況中,會(huì)搜索危險(xiǎn)端口列表并試圖匹配80,當(dāng)然危險(xiǎn)端口不會(huì)包括80,所以每次對(duì)80的請(qǐng)求都要搜索完整個(gè)列表,這樣就會(huì)影響性能。)
squid也有myport ACL。port ACL指向原始服務(wù)器的端口號(hào),myport指向squid自己的端口號(hào),用以接受客戶請(qǐng)求。假如你在http_port指令里指定不止一個(gè)端口號(hào),那么squid就可以在不同的端口上偵聽(tīng)。
假如你將squid作為站點(diǎn)HTTP加速器和用戶代理服務(wù)器,那么myport ACL特別有用。你可以在80上接受加速請(qǐng)求,在3128上接受代理請(qǐng)求。你可能想讓所有人訪問(wèn)加速器,但僅僅你自己的用戶能以代理形式訪問(wèn)squid。你的ACL可能如下:
acl AccelPort myport 80 acl ProxyPort myport 3128 acl MyNet src 172.16.0.0/22 http_access allow AccelPort # anyone http_access allow ProxyPort MyNet # only my users http_access deny ProxyPort # deny others
method ACL指HTTP請(qǐng)求方法。GET是典型的最常用方法,接下來(lái)是POST,PUT,和其他。下例說(shuō)明如何使用method ACL:
acl Uploads method PUT POST
Squid知道下列標(biāo)準(zhǔn)HTTP方法:GET, POST, PUT, HEAD, CONNECT, TRACE, OPTIONS和DELETE。另外,squid了解下列來(lái)自WEBDAV規(guī)范,RFC 2518的方法:PROPFIND, PROPPATCH, MKCOL, COPY, MOVE, LOCK, UNLOCK。某些Microsoft產(chǎn)品使用非標(biāo)準(zhǔn)的WEBDAV方法,所以squid也了解它們:BMOVE, BDELETE, BPROPFIND。最后,你可以在extension_methods指令里配置squid去理解其他的請(qǐng)求方法。請(qǐng)見(jiàn)附錄A。
注意CONNECT方法非常特殊。它是用于通過(guò)HTTP代理來(lái)封裝某種請(qǐng)求的方法(請(qǐng)見(jiàn)RFC 2817:Upgrading to TLS Within HTTP/1.1)。在處理CONNECT方法和遠(yuǎn)程服務(wù)器的端口號(hào)時(shí)應(yīng)特別謹(jǐn)慎。就像前面章節(jié)講過(guò)的一樣,你不希望squid連接到某些遠(yuǎn)程服務(wù)。你該限制CONNECT方法僅僅能連接到HTTPS/SSL或NNTPS端口(443和563)。默認(rèn)的squid.conf這樣做:
acl CONNECT method CONNECT acl SSL_ports 443 563 http_access allow CONNECT SSL_ports http_access deny CONNECT
在該配置里,squid僅僅允許加密請(qǐng)求到端口443(HTTPS/SSL)和563(NNTPS)。CONNECT方法對(duì)其他端口的請(qǐng)求都被拒絕。
PURGE是另一個(gè)特殊的請(qǐng)求方法。它是Squid的專有方法,沒(méi)有在任何RFC里定義。它讓管理員能強(qiáng)制刪除緩存對(duì)象。既然該方法有些危險(xiǎn),squid默認(rèn)拒絕PURGE請(qǐng)求,除非你定義了ACL引用了該方法。否則,任何能訪問(wèn)cache者也許能夠刪除任意緩存對(duì)象。我推薦僅僅允許來(lái)自localhost的PURGE:
acl Purge method PURGE acl Localhost src 127.0.0.1 http_access allow Purge Localhost http_access deny Purge
關(guān)于從squid的緩存里刪除對(duì)象,請(qǐng)見(jiàn)7.6章。
該類型指URI訪問(wèn)(或傳輸)協(xié)議。如下是有效值:http, https (same as HTTP/TLS), ftp, gopher, urn, whois, 和cache_object。也就是說(shuō),這些是被squid支持的URL機(jī)制名字。例如,假如你想拒絕所有的FTP請(qǐng)求,你可以使用下列指令:
acl FTP proto FTP http_access deny FTP
cache_object機(jī)制是squid的特性。它用于訪問(wèn)squid的緩存管理接口,我將在14.2章討論它。不幸的是,它并非好名字,可能會(huì)被改變。默認(rèn)的squid.conf文件有許多行限制緩存管理訪問(wèn):
acl Manager proto cache_object acl Localhost src 127.0.0.1 http_access allow Manager Localhost http_access deny Manager
這些配置行僅允許來(lái)自本機(jī)地址的緩存管理請(qǐng)求,所有其他的緩存管理請(qǐng)求被拒絕。這意味著在squid機(jī)器上有賬號(hào)的人,能訪問(wèn)到潛在的敏感緩存管理信息。你也許想修改緩存管理訪問(wèn)控制,或?qū)δ承╉?yè)面使用密碼保護(hù)。我將在14.2.2章里談?wù)摰健?/p>
time ACL允許你控制基于時(shí)間的訪問(wèn),時(shí)間為每天中的具體時(shí)間,和每周中的每天。日期以單字母來(lái)表示,見(jiàn)如下表。時(shí)間以24小時(shí)制來(lái)表示。開(kāi)始時(shí)間必須小于結(jié)束時(shí)間,這樣在編寫跨越0點(diǎn)的time ACL時(shí)可能有點(diǎn)麻煩。
Table 6-2. Day codes for the time ACL
Code | Day |
S | Sunday |
M | Monday |
T | Tuesday |
W | Wednesday |
H | Thursday |
F | Friday |
A | Saturday |
D | All weekdays (M-F) |
日期和時(shí)間由localtime()函數(shù)來(lái)產(chǎn)生。請(qǐng)確認(rèn)你的計(jì)算機(jī)位于正確的時(shí)區(qū),你也該讓你的時(shí)鐘與標(biāo)準(zhǔn)時(shí)間同步。
為了編寫time ACL來(lái)匹配你的工作時(shí)間,你可以這樣寫:
acl Working_hours MTWHF 08:00-17:00
or:
acl Working_hours D 08:00-17:00
讓我們看一個(gè)麻煩的例子。也許你是某個(gè)ISP,在下午8點(diǎn)到早上4點(diǎn)這段不忙的時(shí)間內(nèi)放松訪問(wèn)。既然該時(shí)間跨越子夜,你不能編寫“20:00-04:00”。代替的,你需要把它們分成兩個(gè)ACL來(lái)寫,或者使用否定機(jī)制來(lái)定義非忙時(shí)。例如:
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允許,你也不應(yīng)該在同一個(gè)time ACL里放置多個(gè)日期和時(shí)間范圍列表。對(duì)這些ACL的解析不一定是你想象的那樣。例如,假如你輸入:
acl Blah time M 08:00-10:00 W 09:00-11:00
實(shí)際能做到的是:
acl Blah time MW 09:00-11:00
解析僅僅使用最后一個(gè)時(shí)間范圍。正確的寫法是,將它們寫進(jìn)兩行:
acl Blah time M 08:00-10:00 acl Blah time W 09:00-11:00
ident ACL匹配被ident協(xié)議返回的用戶名。這是個(gè)簡(jiǎn)單的協(xié)議,文檔是RFC 1413。它工作過(guò)程如下:
當(dāng)squid遇到對(duì)特殊請(qǐng)求的ident ACL時(shí),該請(qǐng)求被延時(shí),直到ident查詢完成。這樣,ident ACL可以對(duì)你的用戶請(qǐng)求造成延時(shí)。
我們推薦僅僅在本地局域網(wǎng)中,并且大部分客戶工作站運(yùn)行ident服務(wù)時(shí),才使用ident ACL。假如squid和客戶工作站連在一個(gè)局域網(wǎng)里,ident ACL工作良好。跨廣域網(wǎng)使用ident難以成功。
ident協(xié)議并非很安全。惡意的用戶能替換他們的正常ident服務(wù)為假冒服務(wù),并返回任意的他們選擇的用戶名。例如,假如我知道從administrator用戶的連接總是被允許,那么我可以寫個(gè)簡(jiǎn)單的程序,在回答每個(gè)ident請(qǐng)求時(shí)都返回這個(gè)用戶名。
你可以使用ident ACL攔截cache(請(qǐng)見(jiàn)第9章)。當(dāng)squid被配置成攔截cache時(shí),操作系統(tǒng)假設(shè)它自己是原始服務(wù)器。這意味著用于攔截TCP連接的本地socket地址有原始服務(wù)器的IP地址。假如你在squid上運(yùn)行netstat -n時(shí),你可以看到大量的外部IP地址出現(xiàn)在本地地址欄里。當(dāng)squid發(fā)起一個(gè)ident查詢時(shí),它創(chuàng)建一個(gè)新的TCP套接字,并綁定本地終點(diǎn)到同一個(gè)IP地址上,作為客戶TCP連接的本地終點(diǎn)。既然本地地址并非真正是本地的(它可能與原始服務(wù)器IP地址相距遙遠(yuǎn)),bind()系統(tǒng)調(diào)用失敗。squid將這個(gè)作為失敗的ident查詢來(lái)處理。
注意squid也有個(gè)特性,對(duì)客戶端執(zhí)行懶惰ident查詢。在該情形下,在等待ident查詢時(shí),請(qǐng)求不會(huì)延時(shí)。在HTTP請(qǐng)求完成時(shí),squid記錄ident信息,假如它可用。你能使用ident_lookup_access指令來(lái)激活該特性,我將在本章后面討論。
squid有一套有力的,在某種程度上有點(diǎn)混亂的特性,用以支持HTTP代理驗(yàn)證功能。使用代理驗(yàn)證,客戶的包括頭部的http請(qǐng)求包含了驗(yàn)證信用選項(xiàng)。通常,這簡(jiǎn)單的是用戶名和密碼。squid解密信用選項(xiàng),并調(diào)用外部驗(yàn)證程序以發(fā)現(xiàn)該信用選項(xiàng)是否有效。
squid當(dāng)前支持三種技術(shù)以接受用戶驗(yàn)證:HTTP基本協(xié)議,數(shù)字認(rèn)證協(xié)議,和NTLM?;菊J(rèn)證已經(jīng)發(fā)展了相當(dāng)長(zhǎng)時(shí)間。按今天的標(biāo)準(zhǔn),它是非常不安全的技術(shù)。用戶名和密碼以明文同時(shí)發(fā)送。數(shù)字認(rèn)證更安全,但也更復(fù)雜?;竞蛿?shù)字認(rèn)證在RFC 2617文檔里被描述。NTLM也比基本認(rèn)證更安全。然而,它是Microsoft發(fā)展的專有協(xié)議。少數(shù)squid開(kāi)發(fā)者已經(jīng)基本完成了對(duì)它的反向工程。
為了使用代理驗(yàn)證,你必須配置squid使用大量的外部輔助程序。squid源代碼里包含了一些程序,用于對(duì)許多標(biāo)準(zhǔn)數(shù)據(jù)庫(kù)包括LDAP,NTLM,NCSA類型的密碼文件,和標(biāo)準(zhǔn)Unix密碼數(shù)據(jù)庫(kù)進(jìn)行認(rèn)證。auth_param指令控制對(duì)所有輔助程序的配置。我將在12章里討論這些細(xì)節(jié)。
auth_param指令和proxy_auth ACL是少數(shù)在配置文件里順序重要的實(shí)例。你必須在proxy_auth ACL之前定義至少一個(gè)驗(yàn)證輔助程序(使用auth_param)。假如你沒(méi)有這樣做,squid打印出錯(cuò)誤消息,并且忽略proxy_auth ACL。這并非致命錯(cuò)誤,所以squid可以啟動(dòng),但所有你的用戶的請(qǐng)求可能被拒絕。
proxy_auth ACL取用戶名作為值。然而,大部分安裝里簡(jiǎn)單的使用特殊值REQUIRED:
auth_param ... acl Auth1 proxy_auth REQUIRED
在該情況中,任何具有有效信用選項(xiàng)的請(qǐng)求會(huì)匹配該ACL。假如你需要細(xì)化控制,你可以指定獨(dú)立的用戶名:
auth_param ... acl Auth1 proxy_auth allan bob charlie acl Auth2 proxy_auth dave eric frank
代理驗(yàn)證不支持HTTP攔截,因?yàn)橛脩舸聿恢浪谂c代理服務(wù)器,而非原始服務(wù)器通信。用戶代理不知道在請(qǐng)求里發(fā)送Proxy-Authorization頭部。見(jiàn)9.2章更多細(xì)節(jié)。
該類型檢查客戶源IP地址所屬的具體AS號(hào)(見(jiàn)6.1.1.6關(guān)于squid如何將AS號(hào)映射到IP地址的信息)。作為示例,我們虛構(gòu)某ISP使用AS 64222并且通告使用10.0.0.0/8,172.16.0.0/12,192.168.0.0/16網(wǎng)絡(luò)。你可以編寫這樣的ACL,它允許來(lái)自該ISP地址空間的任何主機(jī)請(qǐng)求:
acl TheISP src 10.0.0.0/8 acl TheISP src 172.16.0.0/12 acl TheISP src 192.168.0.0/16 http_access allow TheISP
當(dāng)然,你還可以這樣寫:
acl TheISP src_as 64222 http_access allow TheISP
第二種寫法不但更短,而且假如ISP增加了新的網(wǎng)絡(luò),你不必更新ACL配置。
dst_as ACL經(jīng)常與cache_peer_access指令一起使用。在該方法中,squid使用與IP路由一致的方式轉(zhuǎn)發(fā)cache丟失。考慮某ISP,它比其他ISP更頻繁的更換路由。每個(gè)ISP處理他們自己的cache代理,這些代理能轉(zhuǎn)發(fā)請(qǐng)求到其他代理。理論上,ISP A將ISP B網(wǎng)絡(luò)里主機(jī)的cache丟失轉(zhuǎn)發(fā)到ISP B的cache代理。使用AS ACL和cache_peer_access指令容易做到這點(diǎn):
acl ISP-B-AS dst_as 64222 acl ISP-C-AS dst_as 64333 cache_peer proxy.isp-b.net parent 3128 3130 cache_peer proxy.isp-c.net parent 3128 3130 cache_peer_access proxy.isb-b.net allow ISP-B-AS cache_peer_access proxy.isb-c.net allow ISP-C-AS
我將在第10章里討論更多關(guān)于cache協(xié)作。
snmp_community ACL對(duì)SNMP查詢才有意義,后者被snmp_access指令控制。例如,你可以這樣寫:
acl OurCommunityName snmp_community hIgHsEcUrItY acl All src 0/0 snmp_access allow OurCommunityName snmp_access deny All
在該情況中,假如community名字設(shè)置為hIgHsEcUrItY,SNMP查詢才被允許。
maxconn ACL指來(lái)自客戶IP地址的大量同時(shí)連接。某些squid管理員發(fā)現(xiàn)這是個(gè)有用的方法,用以阻止用戶濫用代理或者消耗過(guò)多資源。
maxconn ACL在請(qǐng)求超過(guò)指定的數(shù)量時(shí),會(huì)匹配這個(gè)請(qǐng)求。因?yàn)檫@個(gè)理由,你應(yīng)該僅僅在deny規(guī)則里使用maxconn??紤]如下例子:
acl OverConnLimit maxconn 4 http_access deny OverConnLimit
在該情況中,squid允許來(lái)自每個(gè)IP地址的同時(shí)連接數(shù)最大為4個(gè)。當(dāng)某個(gè)客戶發(fā)起第五個(gè)連接時(shí),OverConnLimit ACL被匹配,http_access規(guī)則拒絕該請(qǐng)求。
arp ACL用于檢測(cè)cache客戶端的MAC地址(以太網(wǎng)卡的物理地址)。地址解析協(xié)議(ARP)是主機(jī)查找對(duì)應(yīng)于IP地址的MAC地址的方法。某些大學(xué)學(xué)生發(fā)現(xiàn),在Microsoft Windows下,他們可以改變系統(tǒng)的IP地址到任意值,然后欺騙squid的基于地址的控制。這時(shí)arp功能就派上用場(chǎng)了,聰明的系統(tǒng)管理員會(huì)配置squid檢查客戶的以太網(wǎng)地址。
不幸的是,該特性使用非移植性代碼。假如你運(yùn)行Solaris或Linux,你能使用arp ACL。其他系統(tǒng)不行。當(dāng)你運(yùn)行./configure時(shí)增加--enable-arp-acl選項(xiàng),就可以激活該功能。
arp ACL有另一個(gè)重要限制。ARP是數(shù)據(jù)鏈路層協(xié)議,假如客戶主機(jī)和squid在同一子網(wǎng),它才能工作。你不容易發(fā)現(xiàn)不同子網(wǎng)主機(jī)的MAC地址。假如在squid和你的用戶之間有路由器存在,你可能不能使用arp ACL。
現(xiàn)在你知道何時(shí)去使用它們,讓我們看看arp ACL實(shí)際上是怎樣的。它的值是以太網(wǎng)地址,當(dāng)使用ifconfig和arp時(shí)你能看到以太網(wǎng)地址。例如:
acl WinBoxes arp 00:00:21:55:ed:22 acl WinBoxes arp 00:00:21:ff:55:38
srcdom_regex ACL允許你使用正則表達(dá)式匹配客戶域名。這與srcdomain ACL相似,它使用改進(jìn)的的子串匹配。相同的限制是:某些客戶地址不能反向解析到域名。作為示例,下面的ACL匹配以dhcp開(kāi)頭的主機(jī)名:
acl DHCPUser srcdom_regex -i ^dhcp
因?yàn)轭I(lǐng)頭的^符號(hào),該ACL匹配主機(jī)名dhcp12.example.com,但不匹配host12.dhcp.example.com。
dstdom_regex ACL也與dstdomain相似。下面的例子匹配以www開(kāi)頭的主機(jī)名:
acl WebSite dstdom_regex -i ^www\.
如下是另一個(gè)有用的正則表達(dá)式,用以匹配在URL主機(jī)名里出現(xiàn)的IP地址:
acl IPaddr dstdom_regex [0-9]$
這樣可以工作,因?yàn)閟quid要求URL主機(jī)名完全可驗(yàn)證。既然全局頂級(jí)域名中沒(méi)有以數(shù)字結(jié)尾的,該ACL僅僅匹配IP地址,它以數(shù)字結(jié)尾。
url_regex ACL用于匹配請(qǐng)求URL的任何部分,包括傳輸協(xié)議和原始服務(wù)器主機(jī)名。例如,如下ACL匹配從FTP服務(wù)器的MP3文件請(qǐng)求:
acl FTPMP3 url_regex -i ^ftp://.*\.mp3$
urlpath_regex與url_regex非常相似,不過(guò)傳輸協(xié)議和主機(jī)名不包含在匹配條件里。這讓某些類型的檢測(cè)非常容易。例如,假設(shè)你必須拒絕URL里的"sex",但仍允許在主機(jī)名里含有"sex"的請(qǐng)求,那么這樣做:
acl Sex urlpath_regex sex
另一個(gè)例子,假如你想特殊處理cgi-bin請(qǐng)求,你能這樣捕獲它們:
acl CGI1 urlpath_regex ^/cgi-bin
當(dāng)然,CGI程序并非總在/cgi-bin/目錄下,這樣你應(yīng)該編寫其他的ACL來(lái)捕獲它們。
大部分HTTP請(qǐng)求包含了User-Agent頭部。該頭部的值典型如下:
Mozilla/4.51 [en] (X11; I; Linux 2.2.5-15 i686)
browser ACL對(duì)user-agent頭執(zhí)行正則表達(dá)式匹配。例如,拒絕不是來(lái)自Mozilla瀏覽器的請(qǐng)求,可以這樣寫:
acl Mozilla browser Mozilla http_access deny !Mozilla
在使用browser ACL之前,請(qǐng)確認(rèn)你完全理解cache接受到的User-Agent字符串。某些user-agent與它們的來(lái)源相關(guān)。甚至squid可以重寫它轉(zhuǎn)發(fā)的請(qǐng)求的User-Agent頭部。某些瀏覽器例如Opera和KDE的Konqueror,用戶可以對(duì)不同的原始服務(wù)器發(fā)送不同的user-agent字串,或者干脆忽略它們。
req_mime_type ACL指客戶HTTP請(qǐng)求里的Content-Type頭部。該類型頭部通常僅僅出現(xiàn)在請(qǐng)求消息主體里。POST和PUT請(qǐng)求可能包含該頭部,但GET從不。你能使用該類型ACL來(lái)檢測(cè)某些文件上傳,和某些類型的HTTP隧道請(qǐng)求。req_mime_type ACL值是正則表達(dá)式。你可以這樣編寫ACL去捕獲音頻文件類型:
acl AuidoFileUploads req_mime_type -i ^audio/
該類型ACL指原始服務(wù)器的HTTP響應(yīng)里的Content-Type頭部。它僅在使用http_reply_access規(guī)則時(shí)才有用。所有的其他訪問(wèn)控制形式是基于客戶端請(qǐng)求的。該ACL基于服務(wù)器響應(yīng)。假如你想使用squid阻塞Java代碼,你可以這樣寫:
acl JavaDownload rep_mime_type application/x-java http_reply_access deny JavaDownload
在本節(jié)早些時(shí)講過(guò)ident ACL。ident_regex允許你使用正則表達(dá)式,代替嚴(yán)格的字符串匹配,這些匹配是對(duì)ident協(xié)議返回的用戶名進(jìn)行。例如,如下ACL匹配包含數(shù)字的用戶名:
acl NumberInName ident_regex [0-9]
該ACL允許對(duì)代理認(rèn)證用戶名使用正則表達(dá)式。例如,如下ACL匹配admin,administrator和administrators:
acl Admins proxy_auth_regex -i ^admin
Squid 2.5版本介紹了一個(gè)新特性:外部ACL。你可以指示squid發(fā)送某些信息片斷到外部進(jìn)程,然后外部的輔助程序告訴squid,數(shù)據(jù)匹配或不匹配。
squid附帶著大量的外部ACL輔助程序;大部分用于確定命名用戶是不是某個(gè)特殊組的成員。請(qǐng)見(jiàn)12.5章關(guān)于這些程序的描述,以及關(guān)于如何編寫你自己的程序的信息?,F(xiàn)在,我解釋如何定義和使用外部ACL類型。
external_acl_type指令定義新的外部ACL類型。如下是通用語(yǔ)法:
external_acl_type type-name [options] format helper-command
type-name是用戶定義的字串。你也可以在acl行里引用它。Squid當(dāng)前支持如下選項(xiàng)(options):
ttl=n
時(shí)間數(shù)量,單位是秒,用以緩存匹配值的時(shí)間長(zhǎng)短。默認(rèn)是3600秒,或1小時(shí)。
negative_ttl=n
時(shí)間數(shù)量,單位是秒,用以緩存不匹配值的時(shí)間長(zhǎng)短。默認(rèn)是3600秒,或1小時(shí)。
concurrency=n
衍生的輔助程序的數(shù)量,默認(rèn)是5。
cache=n
緩存結(jié)果的最大數(shù)量。默認(rèn)是0,即不限制cache大小。格式是以%字符開(kāi)始的一個(gè)或多個(gè)關(guān)鍵字。squid當(dāng)前支持如下格式:
%LOGIN
從代理驗(yàn)證信用選項(xiàng)里獲取的用戶名。
%IDENT
從RFC 1413 ident獲取的用戶名。
%SRC
客戶端IP地址。
%DST
原始服務(wù)器IP地址。
%PROTO
傳輸協(xié)議(例如HTTP,FTP等)
%PORT
原始服務(wù)器的TCP端口。
%METHOD
HTTP請(qǐng)求方法。
%{Header}
HTTP請(qǐng)求頭部的值;例如,%{User-Agent}導(dǎo)致squid發(fā)送這樣的字串到驗(yàn)證器:
"Mozilla/4.0 (compatible; MSIE 6.0; Win32)"
%{Hdr:member}
選擇某些數(shù)量的基于列表的HTTP頭部,例如Caceh-Control;例如,給出如下HTTP頭部:
X-Some-Header: foo=xyzzy, bar=plugh, foo=zoinks
對(duì)%{X-Some-Header:foo}的取值,squid發(fā)送這樣的字串到外部ACL進(jìn)程:
foo=xyzzy, foo=zoinks
%{Hdr:;member}
與%{Hdr:member}相同,除了";"是列表分隔符外。你能使用任何非字母數(shù)字的字符作為分隔符。輔助命令是squid為輔助程序衍生的命令。你也可以在這里包含命令參數(shù)。例如,整條命令可能類似如此:
/usr/local/squid/libexec/my-acl-prog.pl -X -5 /usr/local/squid/etc/datafile
將這些放在一個(gè)長(zhǎng)行里。squid不支持如下通過(guò)反斜杠分隔長(zhǎng)行的技術(shù),所以請(qǐng)記住所有這些必須放在單行里:
external_acl_type MyAclType cache=100 %LOGIN %{User-Agent} /usr/local/squid/libexec/my-acl-prog.pl -X -5 /usr/local/squid/share/usernames /usr/local/squid/share/useragents
現(xiàn)在你知道如何定義外部ACL,下一步是編寫引用它的acl行。這相對(duì)容易,語(yǔ)法如下:
acl acl-name external type-name [args ...]
如下是個(gè)簡(jiǎn)單示例:
acl MyAcl external MyAclType
squid接受在type-name后面的任意數(shù)量的參數(shù)。這些在每個(gè)請(qǐng)求里被發(fā)送到輔助程序。請(qǐng)見(jiàn)12.5.3章,我描述了unix_group輔助程序,作為該功能的示例。
ACL列表某些時(shí)候非常長(zhǎng)。這樣的列表在squid.conf文件里難以維護(hù)。你也可能想從其他資源里自動(dòng)產(chǎn)生squid ACL列表。在如此情況下,你可以從外部文件里包含ACL列表。語(yǔ)法如下:
acl name "filename"
這里的雙引號(hào)指示squid打開(kāi)filename,并且將它里面的內(nèi)容分配給ACL。例如,如下的ACL太長(zhǎng)了:
acl Foo BadClients 1.2.3.4 1.2.3.5 1.2.3.6 1.2.3.7 1.2.3.9 ...
你可以這樣做:
acl Foo BadClients "/usr/local/squid/etc/BadClients"
將IP地址放在BadClients文件里:
1.2.3.4 1.2.3.5 1.2.3.6 1.2.3.7 1.2.3.9 ...
文件可以包含以#開(kāi)頭的注釋。注意在該文件里的每個(gè)IP地址必須是一個(gè)單獨(dú)的行。acl行里的任何地方,以空格來(lái)分隔值,新行是包含ACL值的文件的分界。
理解squid如何搜索ACL元素去匹配是很重要的。當(dāng)ACL元素有多個(gè)值時(shí),任何單個(gè)值能導(dǎo)致匹配。換句話說(shuō),squid在檢查ACL元素值時(shí)使用OR邏輯。當(dāng)squid找到第一個(gè)值匹配時(shí),它停止搜索。這意味著把最可能匹配的值放在列表開(kāi)頭處,能減少延時(shí)。
讓我們看一個(gè)特殊的例子,考慮如下ACL定義:
acl Simpsons ident Maggie Lisa Bart Marge Homer
當(dāng)squid在訪問(wèn)列表里遇到Simpsons ACL時(shí),它執(zhí)行ident查詢。讓我們看一下,當(dāng)用戶ident服務(wù)返回Marge時(shí),會(huì)發(fā)生什么呢?squid的ACL代碼在成功匹配Marge前,會(huì)先后將這個(gè)值與Maggie,Lisa,和Bart對(duì)比。當(dāng)搜索完成時(shí),我們認(rèn)為Simpsons ACL匹配了這個(gè)請(qǐng)求。
實(shí)際上,這有點(diǎn)欺騙。ident ACL值并非存儲(chǔ)在無(wú)序列表里。它們存儲(chǔ)在splay tree中。這意味著,在非匹配事件中,squid不會(huì)搜索完所有的名字。對(duì)一個(gè)splay tree搜索N個(gè)條目需要記錄N個(gè)比較。許多其他的ACL類型也使用splay tree。然而,基于正則表達(dá)式的類型不使用。
既然正則表達(dá)式不能這樣存儲(chǔ),它們以鏈表形式存儲(chǔ)。這使得在大鏈表里它們特別低效,特別是不匹配鏈表里任何正則表達(dá)式的請(qǐng)求。為了改進(jìn)這個(gè)形式,當(dāng)匹配發(fā)生時(shí),squid將正則表達(dá)式移到列表的頂部。實(shí)際上,因?yàn)锳CL匹配代碼的天然特性,squid將匹配的條目移到列表的第二個(gè)位置。這樣,普通的匹配值自然移到ACL列表的頂部,這樣會(huì)減少比較數(shù)量。
讓我們看另一個(gè)簡(jiǎn)單示例:
acl Schmever port 80-90 101 103 107 1 2 3 9999
該ACL匹配到原始服務(wù)器80-90端口,和其他獨(dú)立端口的請(qǐng)求。對(duì)80端口的請(qǐng)求,squid通過(guò)查看第一個(gè)值就匹配了該ACL。對(duì)9999端口,其他每個(gè)值都先被檢查。對(duì)某個(gè)不在列表里的端口,squid要檢查所有值才宣布它不匹配。就像我已經(jīng)講過(guò)的,將最常用的值放在第一位能優(yōu)化ACL匹配。
前面提過(guò),ACL元素是建立訪問(wèn)控制的第一步。第二步是訪問(wèn)控制規(guī)則,用來(lái)允許或拒絕某些動(dòng)作。在早先的例子里,你已見(jiàn)過(guò)http_access規(guī)則。squid有大量其他的訪問(wèn)控制列表:
http_access
這是最重要的訪問(wèn)控制列表。它決定哪些客戶HTTP請(qǐng)求被允許,和哪些被拒絕。假如http_access配置錯(cuò)誤,squid cache容易遭受攻擊或被不當(dāng)利用。
http_reply_access
http_reply_access與http_access類似。不同之處是前者在squid接受到來(lái)自原始服務(wù)器或上級(jí)代理的響應(yīng)時(shí),才會(huì)被檢測(cè)。大部分訪問(wèn)控制基于客戶請(qǐng)求的方式,對(duì)這些使用http_access就夠了。然而,某些人喜歡基于響應(yīng)內(nèi)容類型來(lái)允許或拒絕請(qǐng)求。更多信息請(qǐng)見(jiàn)6.3.9章。
icp_access
假如你的squid被配置來(lái)服務(wù)ICP響應(yīng)(見(jiàn)10.6章),那么該使用icp_access列表。大部分情況下,你該僅僅允許來(lái)自鄰居cache的ICP請(qǐng)求。
no_cache
你能使用no_cache訪問(wèn)列表來(lái)指示squid,它不必存儲(chǔ)某些響應(yīng)(在磁盤或內(nèi)存里)。該列表典型的與dst,dstdomain,url_regex ACL結(jié)合使用。
對(duì)no_cache使用"否"條件,這樣的雙重否定會(huì)導(dǎo)致某些混亂。被no_cache列表拒絕的請(qǐng)求不被緩存。換句話說(shuō),no_cache deny...是讓目標(biāo)不被緩存。見(jiàn)6.3.10章的示例。
miss_access
miss_access列表主要用于squid的鄰居cache。它決定squid怎樣處理cache丟失的請(qǐng)求。如果squid使用集群技術(shù),那么該功能必需。見(jiàn)6.3.7的示例。
redirector_access
該訪問(wèn)列表決定哪個(gè)請(qǐng)求被發(fā)送到重定向進(jìn)程(見(jiàn)11章)。默認(rèn)情況下,假如你使用重定向器,那么所有的請(qǐng)求都通過(guò)重定向器。你可以使用redirector_access列表來(lái)阻止某些請(qǐng)求被重寫。這點(diǎn)特別有用,因?yàn)檫@樣的訪問(wèn)列表,使重定向器相對(duì)于訪問(wèn)控制系統(tǒng),接受的請(qǐng)求信息要少一些。
ident_lookup_access
ident_lookup_access列表與redirector_access類似。它允許你對(duì)某些請(qǐng)求執(zhí)行懶惰ident查詢。squid默認(rèn)不發(fā)布ident查詢。假如請(qǐng)求被ident_lookup_access規(guī)則(或ident ACL)允許,那么squid才會(huì)進(jìn)行ident查詢。
always_direct
該訪問(wèn)列表影響squid怎樣處理與鄰居cache轉(zhuǎn)發(fā)cache丟失。通常squid試圖轉(zhuǎn)發(fā)cache丟失到父cache,和/或squid使用ICP來(lái)查找臨近c(diǎn)ache響應(yīng)。然而,當(dāng)請(qǐng)求匹配always_direct規(guī)則時(shí),squid直接轉(zhuǎn)發(fā)請(qǐng)求到原始服務(wù)器。
使用該規(guī)則,對(duì)"allow"規(guī)則的匹配導(dǎo)致squid直接轉(zhuǎn)發(fā)請(qǐng)求,見(jiàn)10.4.4章的更多細(xì)節(jié)和示例。
never_direct
never_direct與always_direct相反。匹配該列表的cache丟失請(qǐng)求必須發(fā)送到鄰居cache。這點(diǎn)對(duì)在防火墻之后的代理特別有用。使用該列表,對(duì)"allow"規(guī)則的匹配導(dǎo)致squid轉(zhuǎn)發(fā)請(qǐng)求到鄰居cache。見(jiàn)10.4.3章的更多細(xì)節(jié)和示例。
snmp_access
該訪問(wèn)列表應(yīng)用到發(fā)送給squid的SNMP端口的查詢。你能配合該列表使用的ACL是snmp_community和src。假如你確實(shí)想使用它,那也能使用srcdomain,srcdom_regex,和src_as。見(jiàn)14.3章的示例。
broken_posts
該訪問(wèn)列表影響squid處理某些POST請(qǐng)求的方法。某些老的用戶代理在請(qǐng)求主體的結(jié)尾處發(fā)送一個(gè)特別的回車換行符。那就是說(shuō),消息主體比content-length頭部指示的長(zhǎng)度要多2個(gè)字節(jié)。更糟糕的是,某些老的HTTP服務(wù)器實(shí)際上依賴于這種不正確的行為。當(dāng)請(qǐng)求匹配該訪問(wèn)列表時(shí),squid模擬這種客戶端并且發(fā)送特殊的回車換行符。Squid有大量的使用ACL元素的其他配置指令。它們中的某些過(guò)去是全局配置,后被修改來(lái)使用ACL以提供更靈活的控制。
cache_peer_access
該訪問(wèn)列表控制發(fā)送到鄰居cache的HTTP請(qǐng)求和ICP/HTCP查詢。見(jiàn)10.4.1章的更多信息和示例。
reply_body_max_size
該訪問(wèn)列表限制對(duì)HTTP響應(yīng)主體的最大可接受size。見(jiàn)附錄A的更多信息。
delay_access
該訪問(wèn)規(guī)則列表控制是否延時(shí)池被應(yīng)用到某個(gè)請(qǐng)求的cache丟失響應(yīng)。見(jiàn)附錄C。
tcp_outgoing_address
該訪問(wèn)列表綁定服務(wù)端TCP連接到指定的本地IP地址。見(jiàn)附錄A。
tcp_outgoing_tos
該訪問(wèn)列表能設(shè)置到原始服務(wù)器和鄰居cache的TCP連接的不同TOS/Diffserv值,見(jiàn)附錄A。
header_access
使用該指令,你能配置squid從它轉(zhuǎn)發(fā)的請(qǐng)求里刪除某些HTTP頭部。例如,你也許想過(guò)濾掉發(fā)送到某些原始服務(wù)器的請(qǐng)求里的Cookie頭部。見(jiàn)附錄A。
header_replace
該指令允許你替換,而不是刪除,HTTP頭部的內(nèi)容。例如,你能設(shè)置user-agent頭部為假值,滿足某些原始服務(wù)器的要求,但仍保護(hù)你的隱私。見(jiàn)附錄A。
訪問(wèn)控制規(guī)則的語(yǔ)法如下:
access_list allow|deny [!]ACLname ...
例如:
http_access allow MyClients http_access deny !Safe_Ports http_access allow GameSites AfterHours
當(dāng)讀取配置文件時(shí),squid僅僅掃描一遍訪問(wèn)控制行。這樣,在訪問(wèn)列表里引用ACL元素之前,你必須在acl行里定義它們。甚至,訪問(wèn)列表規(guī)則的順序也非常重要。你以怎樣的順序編寫訪問(wèn)列表,那么squid就按怎樣的順序來(lái)檢查它們。將最常用的ACL放在列表的開(kāi)始位置,可以減少squid的CPU負(fù)載。
對(duì)大部分訪問(wèn)列表,deny和allow的意義明顯。然而,它們中的某些,卻并非如此含義清楚。請(qǐng)謹(jǐn)慎的編寫always_direct,never_direct,和no_cache規(guī)則。在always_direct中,allow規(guī)則意味著匹配的請(qǐng)求直接轉(zhuǎn)發(fā)到原始服務(wù)器。always_direct deny規(guī)則意味著匹配的請(qǐng)求不強(qiáng)迫發(fā)送到原始服務(wù)器,但假如鄰居cache不可到達(dá),那可能還是會(huì)這么做。no_cache規(guī)則也有點(diǎn)麻煩。這里,你必須對(duì)不必被cache的請(qǐng)求使用deny。
回想一下squid在搜索ACL元素時(shí)使用的“或”邏輯。在acl里的任何單值都可以導(dǎo)致匹配。
然而,訪問(wèn)規(guī)則恰好相反。對(duì)http_access和其他規(guī)則設(shè)置,squid使用“與”邏輯??紤]如下示例:
access_list allow ACL1 ACL2 ACL3
對(duì)該匹配規(guī)則來(lái)說(shuō),請(qǐng)求必須匹配ACL1,ACL2,ACL3中的任何一個(gè)。假如這些ACL中的任何一個(gè)不匹配請(qǐng)求,squid停止搜索該規(guī)則,并繼續(xù)處理下一條。對(duì)某個(gè)規(guī)則來(lái)說(shuō),將最少匹配的ACL放在首位,能使效率最佳??紤]如下示例:
acl A method http acl B port 8080 http_access deny A B
該http_access規(guī)則有點(diǎn)低效,因?yàn)锳 ACL看起來(lái)比B ACL更容易匹配。反轉(zhuǎn)順序應(yīng)該更好,以便squid僅僅檢查一個(gè)ACL,而不是兩個(gè):
http_access deny B A
人們易犯的典型錯(cuò)誤是編寫永不正確的規(guī)則。例如:
acl A src 1.2.3.4 acl B src 5.6.7.8 http_access allow A B
該規(guī)則永不正確,因?yàn)槟硞€(gè)源IP地址不可能同時(shí)等同于1.2.3.4和5.6.7.8。這條規(guī)則的真正意圖是:
acl A src 1.2.3.4 5.6.7.8 http_access allow A
對(duì)某個(gè)ACL值的匹配算法是,squid在訪問(wèn)列表里找到匹配規(guī)則時(shí),搜索終止。假如沒(méi)有訪問(wèn)規(guī)則導(dǎo)致匹配,默認(rèn)動(dòng)作是列表里最后一條規(guī)則的取反。例如,考慮如下簡(jiǎn)單訪問(wèn)配置:
acl Bob ident bob http_access allow Bob
假如用戶Mary發(fā)起請(qǐng)求,她會(huì)被拒絕。列表里最后的(唯一的)規(guī)則是allow規(guī)則,它不匹配用戶名mary。這樣,默認(rèn)的動(dòng)作是allow的取反,故請(qǐng)求被拒絕。類似的,假如最后的規(guī)則是deny規(guī)則,默認(rèn)動(dòng)作是允許請(qǐng)求。在訪問(wèn)列表的最后加上一條,明確允許或拒絕所有請(qǐng)求,是好的實(shí)際做法。為清楚起見(jiàn),以前的示例應(yīng)該如此寫:
acl All src 0/0 acl Bob ident bob http_access allow Bob http_access deny All
src 0/0 ACL表示匹配每一個(gè)和任意類型的請(qǐng)求。
squid的訪問(wèn)控制語(yǔ)法非常強(qiáng)大。大多數(shù)情況下,你可以使用兩種或多種方法來(lái)完成同樣的事。通常,你該將更具體的和受限制的訪問(wèn)列表放在首位。例如,如下語(yǔ)句并非很好:
acl All src 0/0 acl Net1 src 1.2.3.0/24 acl Net2 src 1.2.4.0/24 acl Net3 src 1.2.5.0/24 acl Net4 src 1.2.6.0/24 acl WorkingHours time 08:00-17:00 http_access allow Net1 WorkingHours http_access allow Net2 WorkingHours http_access allow Net3 WorkingHours http_access allow Net4 http_access deny All
假如你這樣寫,訪問(wèn)控制列表會(huì)更容易維護(hù)和理解:
http_access allow Net4 http_access deny !WorkingHours http_access allow Net1 http_access allow Net2 http_access allow Net3 http_access deny All
無(wú)論何時(shí),你編寫了一個(gè)帶兩個(gè)或更多ACL元素的規(guī)則,建議你在其后緊跟一條相反的,更廣泛的規(guī)則。例如,默認(rèn)的squid配置拒絕非來(lái)自本機(jī)IP地址的cache管理請(qǐng)求,你也許試圖這樣寫:
acl CacheManager proto cache_object acl Localhost src 127.0.0.1 http_access deny CacheManager !Localhost
然而,這里的問(wèn)題是,你沒(méi)有允許確實(shí)來(lái)自本機(jī)的cache管理請(qǐng)求。隨后的規(guī)則可能導(dǎo)致請(qǐng)求被拒絕。如下規(guī)則就產(chǎn)生了問(wèn)題:
acl CacheManager proto cache_object acl Localhost src 127.0.0.1 acl MyNet 10.0.0.0/24 acl All src 0/0 http_access deny CacheManager !Localhost http_access allow MyNet http_access deny All
既然來(lái)自本機(jī)的請(qǐng)求不匹配MyNet,它被拒絕。編寫本規(guī)則的更好方法是:
http_access allow CacheManager localhost http_access deny CacheManager http_access allow MyNet http_access deny All
某些ACL不能在一個(gè)過(guò)程里被檢查,因?yàn)楸匾男畔⒉豢捎?。ident,dst,srcdomain和proxy_auth類型屬于該范疇。當(dāng)squid遇到某個(gè)ACL不能被檢查時(shí),它延遲決定并且發(fā)布對(duì)必要信息的查詢(IP地址,域名,用戶名等)。當(dāng)信息可用時(shí),squid再次在列表的開(kāi)頭位置檢查這些規(guī)則。它不會(huì)從前次檢查剩下的位置繼續(xù)。假如可能,你應(yīng)該將這些最可能被延時(shí)的ACL放在規(guī)則的頂部,以避免不必要的,重復(fù)的檢查。
因?yàn)檠訒r(shí)的代價(jià)太大,squid會(huì)盡可能緩存查詢獲取的信息。ident查詢?cè)诿總€(gè)連接里發(fā)生,而不是在每個(gè)請(qǐng)求里。這意味著,當(dāng)你使用ident查詢時(shí),持續(xù)HTTP連接切實(shí)對(duì)你有利。DNS響應(yīng)的主機(jī)名和IP地址也被緩存,除非你使用早期的外部dnsserver進(jìn)程。代理驗(yàn)證信息被緩存,請(qǐng)見(jiàn)6.1.2.12章節(jié)的描述。
某些訪問(wèn)規(guī)則使用快速檢查。例如,icp_access規(guī)則被快速檢查。為了快速響應(yīng)ICP查詢,它必須被快速檢查。甚至,某些ACL類型例如proxy_auth,對(duì)ICP查詢來(lái)說(shuō)無(wú)意義。下列訪問(wèn)規(guī)則被快速檢查:
header_access reply_body_max_size reply_access ident_lookup delay_access miss_access broken_posts icp_access cache_peer_access redirector_access snmp_access
下列ACL類型可能需要來(lái)自外部數(shù)據(jù)源(DNS,驗(yàn)證器等)的信息,這樣與快速的訪問(wèn)規(guī)則不兼容:
srcdomain, dstdomain, srcdom_regex, dstdom_regex dst, dst_as proxy_auth ident external_acl_type
這意味著,例如,不能在header_access規(guī)則里使用ident ACL。
因?yàn)樵L問(wèn)控制可能很復(fù)雜,本節(jié)包含一些示例。它們描述了一些訪問(wèn)控制的普通用法。你可以在實(shí)際中調(diào)整它們。
幾乎每個(gè)squid安裝后,都限制基于客戶IP地址的訪問(wèn)。這是保護(hù)你的系統(tǒng)不被濫用的最好的方法之一。做到這點(diǎn)最容易的方法是,編寫包含IP地址空間的ACL,然后允許該ACL的HTTP請(qǐng)求,并拒絕其他的。
acl All src 0/0 acl MyNetwork src 172.16.5.0/24 172.16.6.0/24 http_access allow MyNetwork http_access deny All
也許該訪問(wèn)控制配置過(guò)于簡(jiǎn)單,所以你要增加更多行。記住http_access的順序至關(guān)重要。不要在deny all后面增加任何語(yǔ)句。假如必要,應(yīng)該在allow MyNetwork之前或之后增加新規(guī)則。
因?yàn)槟撤N理由,你也許有必要拒絕特定客戶IP地址的訪問(wèn)。這種情況可能發(fā)生,例如,假如某個(gè)雇員或?qū)W生發(fā)起一個(gè)異常耗費(fèi)網(wǎng)絡(luò)帶寬或其他資源的web連接,在根本解決這個(gè)問(wèn)題前,你可以配置squid來(lái)阻止這個(gè)請(qǐng)求:
acl All src 0/0 acl MyNetwork src 172.16.5.0/24 172.16.6.0/24 acl ProblemHost src 172.16.5.9 http_access deny ProblemHost http_access allow MyNetwork http_access deny All
阻塞對(duì)特定內(nèi)容的訪問(wèn)是棘手的問(wèn)題。通常,使用squid進(jìn)行內(nèi)容過(guò)濾最難的部分,是被阻塞的站點(diǎn)列表。你也許想自己維護(hù)一個(gè)這樣的列表,或從其他地方獲取一個(gè)。squid FAQ的“訪問(wèn)控制”章節(jié)有鏈接指向免費(fèi)的可用列表。
使用這樣的列表的ACL語(yǔ)法依賴于它的內(nèi)容。假如列表包含正則表達(dá)式,你可能要這樣寫:
acl PornSites url_regex "/usr/local/squid/etc/pornlist" http_access deny PornSites
另一方面,假如列表包含原始服務(wù)器主機(jī)名,那么簡(jiǎn)單的更改url_regex為dstdomain。
某些公司喜歡在工作時(shí)間限制web使用,為了節(jié)省帶寬,或者是公司政策禁止員工在工作時(shí)做某些事情。關(guān)于這個(gè)最難的部分是,所謂合適的和不合適的internet使用之間的區(qū)別是什么。不幸的是,我不能對(duì)這個(gè)問(wèn)題作出回答。在該例子里,假設(shè)你已收集了一份web站點(diǎn)域名列表,它包含已知的不適合于你的站點(diǎn)名,那么這樣配置squid:
acl NotWorkRelated dstdomain "/usr/local/squid/etc/not-work-related-sites" acl WorkingHours time D 08:00-17:30 http_access deny !WorkingHours NotWorkRelated
請(qǐng)注意在該規(guī)則里首先放置!WorkingHours ACL。相對(duì)于字符串或列表,dstdomain ACL產(chǎn)生的性能代價(jià)較大,但time ACL檢查卻很簡(jiǎn)單。下面的例子,進(jìn)一步理解如何結(jié)合如下方法和前面描述的源地址控制,來(lái)控制訪問(wèn)。
acl All src 0/0 acl MyNetwork src 172.16.5.0/24 172.16.6.0/24 acl NotWorkRelated dstdomain "/usr/local/squid/etc/not-work-related-sites" acl WorkingHours time D 08:00-17:30 http_access deny !WorkingHours NotWorkRelated http_access allow MyNetwork http_access deny All
上面的方法可行,因?yàn)樗鼘?shí)現(xiàn)了我們的目標(biāo),在工作時(shí)間內(nèi)拒絕某些請(qǐng)求,并允許來(lái)自你自己網(wǎng)絡(luò)的請(qǐng)求。然而,它也許有點(diǎn)低效。注意NotWorkRelated ACL在所有請(qǐng)求里被搜索,而不管源IP地址。假如那個(gè)列表非常長(zhǎng),在列表里對(duì)外部網(wǎng)絡(luò)請(qǐng)求的搜索,純粹是浪費(fèi)CPU資源。所以,你該這樣改變規(guī)則:
http_access deny !MyNetwork http_access deny !WorkingHours NotWorkRelated http_access Allow All
這里,將代價(jià)較大的檢查放在最后。試圖濫用squid的外部用戶不會(huì)再浪費(fèi)你的CPU資源。
你必須盡可能不讓squid與某些類型的TCP/IP服務(wù)器通信。例如,永不能夠使用squid緩存來(lái)轉(zhuǎn)發(fā)SMTP傳輸。我在前面介紹port ACL時(shí)提到過(guò)這點(diǎn)。然而,它是至關(guān)重要的,所以再?gòu)?qiáng)調(diào)一下。
首先,你必須關(guān)注CONNECT請(qǐng)求方法。使用該方法的用戶代理,通過(guò)HTTP代理來(lái)封裝TCP連接。它被創(chuàng)造用于HTTP/TLS請(qǐng)求,這是CONNECT方法的主要用途。某些用戶代理也可以通過(guò)防火墻代理來(lái)封裝NNTP/TLS傳輸。所有其他的用法應(yīng)該被拒絕。所以,你的訪問(wèn)列表,應(yīng)該僅僅允許到HTTP/TLS和NNTP/TLS端口的CONNECT請(qǐng)求。
第二,你應(yīng)該阻止squid連接到某些服務(wù),例如SMTP。你也可以開(kāi)放安全端口和拒絕危險(xiǎn)端口。我對(duì)這兩種技術(shù)給出示例。讓我們看看默認(rèn)的squid.conf文件提供的規(guī)則:
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 280 # http-mgmt acl Safe_ports port 488 # gss-http acl Safe_ports port 591 # filemaker acl Safe_ports port 777 # multiling http acl Safe_ports port 1025-65535 # unregistered ports acl SSL_ports port 443 563 acl CONNECT method CONNECT http_access deny !Safe_ports http_access deny CONNECT !SSL_ports <additional http_access lines as necessary...>
Safe_ports ACL列舉了所有的squid有合法響應(yīng)的特權(quán)端口(小于1024)。它也列舉了所有非特權(quán)端口范圍。注意Safe_ports ACL也包括了安全HTTP和NNTP端口(443和563),即使它們也出現(xiàn)在SSL_ports ACL里。這是因?yàn)镾afe_ports在規(guī)則里首先被檢查。假如你交換了兩個(gè)http_access行的順序,你也許能從Safe_ports列表里刪除443和563,但沒(méi)必要這么麻煩。與此相似的其他方法是,列舉已知不安全的特權(quán)端口:
acl Dangerous_ports 7 9 19 22 23 25 53 109 110 119 acl SSL_ports port 443 563 acl CONNECT method CONNECT http_access deny Dangerous_ports http_access deny CONNECT !SSL_ports <additional http_access lines as necessary...>
假如你不熟悉這些奇特的端口號(hào),也不要擔(dān)心。你可以閱讀unix系統(tǒng)的/etc/services文件,或者閱讀IANA的注冊(cè)TCP/UDP端口號(hào)列表:
http://www.iana.org/assignments/port-numbers使用基于用戶名進(jìn)行訪問(wèn)控制的組織,通常需要授予某些用戶特殊的權(quán)限。在該簡(jiǎn)單示例里,有三個(gè)元素:所有授權(quán)用戶,管理員用戶名,限制訪問(wèn)的web站點(diǎn)列表。正常的用戶不允許訪問(wèn)受限站點(diǎn),但管理員有維護(hù)這個(gè)列表的任務(wù)。他們必須連接到所有服務(wù)器,去驗(yàn)證某個(gè)特殊站點(diǎn)是否該放到受限站點(diǎn)列表里。如下顯示如何完成這個(gè)任務(wù):
auth_param basic program /usr/local/squid/libexec/ncsa_auth /usr/local/squid/etc/passwd acl Authenticated proxy_auth REQUIRED acl Admins proxy_auth Pat Jean Chris acl Porn dstdomain "/usr/local/squid/etc/porn.domains" acl All src 0/0 http_access allow Admins http_access deny Porn http_access allow Authenticated http_access deny All
首先,有三個(gè)ACL定義。Authenticated ACL匹配任何有效的代理驗(yàn)證信用。Admins ACL匹配來(lái)自用戶Pat,Jean,和Chris的有效信用。Porn ACL匹配某些原始服務(wù)器主機(jī)名,它們?cè)趐orn.domains文件里找到。
該示例有四個(gè)訪問(wèn)控制規(guī)則。第一個(gè)僅僅檢查Admins ACL,允許所有來(lái)自Pat,Jean,和Chris的請(qǐng)求。對(duì)其他用戶,squid轉(zhuǎn)移到下一條規(guī)則。對(duì)第二條規(guī)則,假如原始主機(jī)名位于porn.domains文件,那么該請(qǐng)求被拒絕。對(duì)不匹配Porn ACL的請(qǐng)求,squid轉(zhuǎn)移到第三條規(guī)則。第三條規(guī)則里,假如請(qǐng)求包含有效的驗(yàn)證信用,那么該請(qǐng)求被允許。外部驗(yàn)證器(這里的ncsa_auth)決定是否信用有效。假如它們無(wú)效,最后的規(guī)則出現(xiàn),該請(qǐng)求被拒絕。注意ncsa_auth驗(yàn)證器并非必需。你可以使用12章里描述的任何驗(yàn)證輔助程序。
假如你使用了cache集群,你必須付出多余的小心。cache通常使用ICP來(lái)發(fā)現(xiàn)哪些對(duì)象被緩存在它們的鄰居機(jī)器上。你僅該接受來(lái)自已知授權(quán)的鄰居cache的ICP查詢。
更進(jìn)一步,通過(guò)使用miss_access規(guī)則列表,你能配置squid強(qiáng)制限制鄰近關(guān)系。squid僅僅在cache丟失,沒(méi)有cache命中時(shí)才檢查這些規(guī)則。這樣,在miss_access列表生效前,所有請(qǐng)求必須首先通過(guò)http_access規(guī)則。
在本示例里,有三個(gè)獨(dú)立的ACL。一個(gè)是直接連接到cache的本地用戶;另一個(gè)是子cache,它被允許來(lái)轉(zhuǎn)發(fā)cache丟失的請(qǐng)求;第三個(gè)是鄰近c(diǎn)ache,它必須從不轉(zhuǎn)發(fā)導(dǎo)致cache丟失的請(qǐng)求。如下是它們?nèi)绾喂ぷ鳎?/p>
alc All src 0/0 acl OurUsers src 172.16.5.0/24 acl ChildCache src 192.168.1.1 acl SiblingCache src 192.168.3.3 http_access allow OurUsers http_access allow ChildCache http_access allow SiblingCache http_access deny All miss_access deny SiblingCache icp_access allow ChildCache icp_access allow SiblingCache icp_access deny All
我在6.1.2.4章節(jié)里提過(guò),dstdomain類型是阻塞對(duì)指定原始主機(jī)訪問(wèn)的好選擇。然而,聰明的用戶通過(guò)替換URL主機(jī)名成IP地址,能夠繞過(guò)這樣的規(guī)則。假如你想徹底阻止這樣的請(qǐng)求,你可能得阻塞所有包含IP地址的請(qǐng)求。你可以使用重定向器,或者使用dstdom_regex ACL來(lái)完成。例如:
acl IPForHostname dstdom_regex ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ http_access deny IPForHostname
回想一下,當(dāng)squid檢查http_reply_access規(guī)則時(shí),響應(yīng)的內(nèi)容類型是唯一的可用新信息。這樣,你能保持http_reply_access規(guī)則簡(jiǎn)單化。你只需檢查rep_mime_type ACL。例如,如下示例告訴你如何拒絕某些內(nèi)容類型的響應(yīng):
acl All src 0/0 acl Movies rep_mime_type video/mpeg acl MP3s rep_mime_type audio/mpeg http_reply_access deny Movies http_reply_access deny MP3s http_reply_access allow All
你不必在http_reply_access列表里重復(fù)http_access規(guī)則。這里的allow ALL規(guī)則不意味著所有對(duì)squid的請(qǐng)求被允許。任何被http_access拒絕的請(qǐng)求,從來(lái)不會(huì)再被http_reply_access檢查。
假如你有許多原始服務(wù)器在本地網(wǎng)絡(luò)中,你也許想配置squid,以便它們的響應(yīng)永不被緩存。因?yàn)榉?wù)器就在附近,它們不會(huì)從cache命中里獲益很多。另外,它釋放存儲(chǔ)空間給其他遠(yuǎn)程原始主機(jī)。
第一步是定義本地服務(wù)器的ACL。你可能使用基于地址的ACL,例如:
acl LocalServers dst 172.17.1.0/24
假如服務(wù)器不位于單一的子網(wǎng),你也許該創(chuàng)建dstdomain ACL:
acl LocalServers dstdomain .example.com
接下來(lái),你簡(jiǎn)單的使用no_cache access規(guī)則,拒絕這些服務(wù)器的cache:
no_cache deny LocalServers
no_cache規(guī)則不會(huì)阻止客戶發(fā)送請(qǐng)求到squid。沒(méi)有辦法配置squid阻止這樣的請(qǐng)求進(jìn)來(lái)。代替的,你必須配置用戶代理自身。
假如你在squid運(yùn)行一段時(shí)間后增加no_cache規(guī)則,cache可能包含一些匹配新規(guī)則的對(duì)象。在squid2.5之前的版本,這些以前緩存的對(duì)象可能以cache命中返回。然而現(xiàn)在,squid清除掉所有匹配no_cache規(guī)則的緩存響應(yīng)。
訪問(wèn)控制配置越長(zhǎng),它就越復(fù)雜。強(qiáng)烈建議你在將它們用于產(chǎn)品環(huán)境之前,先測(cè)試訪問(wèn)控制。當(dāng)然,首先做的事是確認(rèn)squid能正確的解析配置文件。使用-k parse功能:
% squid -k parse
為了進(jìn)一步測(cè)試訪問(wèn)控制,你需要安裝一個(gè)用于測(cè)試的squid。容易做到的方法是,編譯另一份squid到其他$prefix位置。例如:
% tar xzvf squid-2.5.STABLE4.tar.gz % cd squid-2.5.STABLE4 % ./configure --prefix=/tmp/squid ... % make && make install
在安裝完后,你必須編輯新的squid.conf文件,更改一些指令。假如squid已經(jīng)運(yùn)行在默認(rèn)端口,那么請(qǐng)改變http_port。為了執(zhí)行簡(jiǎn)單的測(cè)試,創(chuàng)建單一的小目錄:
cache_dir ufs /tmp/squid/cache 100 4 4
假如你不想重編譯squid,你也能創(chuàng)建一份新的配置文件。該方法的弊端是你必須設(shè)置所有的日志文件路徑為臨時(shí)目錄,以便不會(huì)覆蓋真正的文件。
你可以使用squidclient程序來(lái)輕松的測(cè)試某些訪問(wèn)控制。例如,假如你有一條規(guī)則,它依賴于原始服務(wù)器主機(jī)名(dstdomain ACL),或者某些URL部分(url_regex或urlpath_regex),簡(jiǎn)單的輸入你期望被允許或拒絕的URI:
% squidclient -p 4128 http://blocked.host.name/blah/blah
or:
% squidclient -p 4128 http://some.host.name/blocked.ext
某些類型的請(qǐng)求難以控制。假如你有src ACL,它們阻止來(lái)自外部網(wǎng)絡(luò)的請(qǐng)求,你也許需要從外部主機(jī)測(cè)試它們。測(cè)試time ACL也很困難,除非你能改變系統(tǒng)時(shí)鐘,或者等待足夠長(zhǎng)時(shí)間。
你能使用squidclient的-H選項(xiàng)來(lái)設(shè)置任意請(qǐng)求頭。例如,假如你需要測(cè)試browser ACL,那么這樣做:
% squidclient -p 4128 http://www.host.name/blah -H 'User-Agent: Mozilla/5.0 (compatible; Konqueror/3)\r\n'
更多的復(fù)雜請(qǐng)求,包括多個(gè)頭部,請(qǐng)參考16.4章中描述的技術(shù)。
你也許考慮制訂一項(xiàng)cron,定期檢查ACL,以發(fā)現(xiàn)期望的行為,并報(bào)告任何異常。如下是可以起步的示例shell腳本:
#!/bin/sh set -e TESTHOST="www.squid-cache.org" # make sure Squid is not proxying dangerous ports # ST=`squidclient 'http://$TESTHOST:25/' | head -1 | awk '{print $2}'` if test "$ST" != 403 ; then echo "Squid did not block HTTP request to port 25" fi # make sure Squid requires user authentication # ST=`squidclient 'http://$TESTHOST/' | head -1 | awk '{print $2}'` if test "$ST" != 407 ; then echo "Squid allowed request without proxy authentication" fi # make sure Squid denies requests from foreign IP addresses # elsewhere we already created an alias 192.168.1.1 on one of # the system interfaces # EXT_ADDR=192.168.1.1 ST=`squidclient -l $EXT_ADDR 'http://$TESTHOST/' | head -1 | awk '{print $2}'` if test "$ST" != 403 ; then echo "Squid allowed request from external address $EXT_ADDR" fi exit 0
聯(lián)系客服