Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1213183
  • 博文数量: 212
  • 博客积分: 10450
  • 博客等级: 上将
  • 技术积分: 1957
  • 用 户 组: 普通用户
  • 注册时间: 2006-02-23 09:00
文章分类

全部博文(212)

文章存档

2012年(1)

2011年(16)

2010年(11)

2009年(9)

2008年(22)

2007年(36)

2006年(117)

分类: LINUX

2006-09-28 09:51:45

第一章是Squid 的简介性描述。 

1.1 Web 缓存 

这节里需要明白3个概念: 

cache 命中 - 在 每次从它的缓存里满足HTTP 请求时发生。cache 命中率,是所有HTTP 请求中命中的比例。Web 缓存典型的cache 命中率在30%到60%之间。另一个相似的度量单位叫做字节命中率,描绘了cache 提供服务的数据容量(字节数)。 

cache丢失 - 在 不能从它的缓存里满足HTTP 请求时发生。cache 丢失的理由有很多种。最明显的,当 第一次接受到对特殊资源的请求时,就是一个cache 丢失。类似的情况是, 会清除缓存以释放空间给新对象。另外的可能是资源不可到达。原始服务器会指示cache 怎样处理响应。例如,它会提示数据不能被缓存,或在有限的时间内才被重复使用,等等。 

cache确认 - 保证 不对用户返回过时数据。在重复使用缓存对象时, 经常从原始服务器确认它。假如服务器指示 的拷贝仍然有效,数据就发送出去。否则,升级它的缓存拷贝,并且转发给客户。 

1.2 Squid 的简明历史 

对本节感兴趣的读者请阅读英文原文档。 

1.3 硬件和操作系统要求 

Squid 运行在所有流行的Unix 系统上,也可以在Microsoft Windows 上运行。尽管的Windows 支持在不断改进,但也许在Unix 上容易一些。假如你有一个喜欢的操作系统,我建议你使用那个。否则,假如你找人推荐,我很喜欢FreeBSD。 

 对硬件要求不算高。内存是最重要的资源。内存短缺会严重影响性能。磁盘空间也是另一个重要因素。更多的磁盘空间意味着更多的缓存目标和更高的命中率。快速的磁盘和驱动器也是有利的。如果你舍得花钱,SCSI 磁盘比ATA 的执行性能好。当然快速的CPU也是好的,但它并不是提高性能的关键因素。 

因为 对每个缓存响应使用少数内存,因此在磁盘空间和内存要求之间有一定联系。基本规则是,每G 磁盘空间需要32M内存。这样,512M 内存的系统,能支持16G 的磁盘缓存。你的情况当然会不同。内存需求依赖于如下事实:缓存目标大小,CPU 体系(32位或64 位),同时在线的用户数量,和你使用的特殊功能。 

人们经常问如此问题:“我的网络有X 个用户,需要配备什么样的硬件给?”因为许多理由,这样的问题好难回答。特别的,很难说X 个用户将产生多少流量。我告诉人们去建立一个有足够磁盘空间,可存储3-7 天web 流量数据的系统。例如,假如你的用户每天8 小时耗费1M 流量(仅仅HTTP 和FTP 传输),那就是每天大约3.5G。所以,我可以说,每兆web 传输你需要10 到25G 的磁盘空间。 

1.4  是开源的 

Squid 是自由软件和合作项目。假如你觉得 有用,请考虑以下面一种或几种方法来回报该项目: 
1.参与 用户讨论列表,回答问题和帮助新用户。 
2.测试新版本,报告bug 或其他问题。 
3.致力于在线文档和FAQ。假如你发现错误,将它报告给维护者。 
4.将你的局部修改提交给开发者。 
5.对开发者提供财政支持。 
6.告诉开发者你想要的新功能。 
7.告诉你的朋友和同学,Squid 非常Cool。 

Squid 是在GNU 公用许可证(GPL)下发行的自由软件。关于GPL 的更多信息请见: 

1.5 Squid 的Web 主页 

Squid的主页在-cache.org" target="_blank"> 你自己阅读该站点吧。 

1.6 获取帮助 

1.6.1 FAQ 

Squid的FAQ文档在-cache.org" target="_blank">/Doc/FAQ/FAQ.html ,是对新用户的好信息资源。 

1.6.2 邮件列表 

Squid 有三个邮件列表可用。邮件列表主页在:-cache.org/mailing-lists.html" target="_blank">/mailing-lists.html 

1.6.2.1 Squid 用户 

订阅该邮件列表,发邮件到 -users-subscribe@-cache.org 

1.6.2.2 Squid 公告 

订阅该邮件列表,发邮件到 -announce-subscribe@-cache.org 

1.6.2.3 Squid 开发 

加入该邮件列表有所限制。它的内容发布在-cache.org" target="_blank">/mail-archive/-dev/ 

1.6.3 职业支持 

即付费的支持 - 职业支持服务提供商列表,请见-cache.org/Support/services.html" target="_blank">/Support/services.html 

1.7 启动Squid 

请按下面的章节一步一步来吧。 

第2章 获取Squid 

2.1 版本和发布 

Squid 开发者定期发布源代码。每一个发布版有一个版本号,例如2.5.STABLE4。版本号的第三部分以STABLE 或DEVEL(短期开发版本)开头。 

也许你能猜到,DEVEL 版本倾向于拥有更新,更试验性的功能。但也许它们有更多的bugs。无经验的用户不应该运行DEVEL 版本。假如你选择运行一个DEVEL 版本,并且遇到了问题,请将问题报告给Squid 维护者。 

在一段时间的开发期后,Squid 版本号变为STABLE。该版本适合于普通用户。当然,即使稳定版可能也有一些bugs。高的稳定版本(例如STABLE3,STABLE4)应该bugs 更少。假如你特别关心稳定性,你应该使用这些最近发布版本中的一个。 

2.2 使用源代 
为什么你不能copy 一份预编译的二进制代码到你的系统中,并且期望它运行良好呢?主要理由是 的代码需要知道特定操作系统的参数。实际上,最重要的参数是打开文件描述符的最大数量。Squid 的./configure 脚本在编译之前侦察这些值。假如你获取一个已编译的使用某个参数值的 到另一个使用不同参数值的系统中,可能会遇到问题。 

另一个理由是许多 功能在编译时必须被激活。假如你获取一个别人已编译的文件,它不包含你所需要的功能,那么你又得再编译一遍。最后,共享库的问题可能使得在系统之间共享可执行文件困难。共享库在运行时被装载,如已知的动态链接一样。 在编译时会侦察你系统中的C 库的某些功能(例如它们是否被提供,是否能运行等)。尽管库功能不常改变,但两个不同的系统的C 库之间可能有明显的区别。如果两个系统差别太大,就会对Squid 造成问题。 

获取 的源代码是非常容易的。请访问 的首页:-cache.org" target="_blank">。首页有链接指向不同的稳定版和开发版。假如你不在美国,那么请访问 的众多镜像站点中的一个。镜像站点通常以"wwwN.CC.-cache.org"命名,N 是数字,CC 是国家的两位代码。例如,www1.au.-cache.org 是澳大利亚的镜像站点,在主页上有链接指向不同的镜像站点。 

每一个 发布版分支(例如Squid-2.5)有它自己的HTML 页面。该页面有链接指向源代码,以及与其他发布版的差别。假如你从一个发布版升级到下一个,你应该下载这些差别文件,并且打上补丁,请见3.7 章节中的描述。每个版本的发布页描述新功能和重要的改进,也有链接指向已经修正的bugs。 

如果web 访问不可行,你能从-cache.org" target="_blank">ftp://ftp.-cache.org 的FTP 服务器获取源代码,或者使用其他FTP 镜像。要获取当前版本,请访问pub/-2/DEVEL 或 pub/-2/STABLE目录。FTP 镜像也在许多国家有,你能用同样的国家代码去猜测一些FTP 镜像站点,例如ftp1.uk.-cache.org。 

当前的Squid 发布版本大约1M 大小。在下载完压缩的打包文件后,你能继续第3章。 

2.3 预编译的二进制文件 

一些Unix 发布版可能预包含了Squid 的编译版。对Linux 系统,你可以找到Squid 的RPM 包。通常 RPM 包含在你所买的Linux 光碟里。Freebsd/Netbsd/OpenBSD 也在它们的ports 或者packages 里面包含了。 

虽然RPM 或者预编译的packages 能节省你一些时间,但它们也有一些弊端。就像我提过的一样,在你开始编译 之前,某些功能必须被激活或禁止。而你安装的预编译的包可能不包含你想要的特定功能。而且, 的./configure 脚本侦察你系统中的特定参数,这些在你系统中的参数可能与编译它的机器的参数不同。 

最后,假如你想对 打补丁,你必须等某个人编译更新的RPM 或packages,或者你还得自己找源代码编译。 

我强烈建议你从源代码编译,当然怎样选择由得你。 

2.4 匿名CVS 

你能匿名访问 的CVS 文件(只读)以保持你的源代码同步更新。使用CVS 的有利面是你能轻易获取当前运行版本的补丁。这样就容易发现近来改变了什么。 

将这些补丁打到你所运行的版本中,有效的保持你的源代码和官方版本的同步。 

CVS 使用树型索引系统,树干叫做头分支。对Squid 而言,这里也是所有的新改变和新功能的存放之地。头分支通常包含试验性的,也许不太稳定的代码。稳定的代码通常在其他分支上。 

为了有效的使用 的匿名CVS,你首先应知道版本和分支是怎样被标明不同的。例如, 版本2.5 分支被命名为SQUID_2_5 。具体的发布有长的命名, 例如SQUID_2_5_STABLE4。为了得到 版本2.5.STABLE4,请使用SQUID_2_5_STABLE4标签;使用SQUID_2_5 得到最近的2.5 分支的代码。 

为了使用 匿名CVS 服务,你首先必须设置CVSROOT 环境变量: 
csh% setenv CVSROOT:pserver:anoncvs@cvs.-cache.org:/, 
或者,对Bourne shell 用户: 
sh$ CVSROOT=:pserver:anoncvs@cvs.-cache.org:/ 
sh$ export CVSROOT 

然后你就可以登陆到服务器: 

% cvs login 
(Logging in to anoncvs@cvs.-cache.org) 
CVS password: 

在提示符下,敲入anoncvs 作为密码。现在你可以用这个命令检查源代码树: 

% cvs checkout -r SQUID_2_5 -d -2.5  

-r 选项指定获取修订标签。省略-r 选项你将获得头分支。 

-d 选项改变存放文件的顶级目录名。假如你省略-d 选项,顶级目录名就与模块名字一样。 

最后的命令行参数()是要检查的模块名字。 

一旦你检查完 源代码树,你能运行cvs update 命令去升级你的文件,和保持文件同步。其他命令包括:cvs diff, cvs log, 和 cvs annotate。 

想获取更多CVS 知识,请访问: 

2.5 devel.-cache.org 

Squid 的开发者维持一个独立的站点,当前运行在SourceForge,提供了试验性的功能。请检查它们在squid-cache.org." target="_blank">http://devel.-cache.org.在这里你能发现许多正在开发的工程,它们还未集成到 的官方源代码里。你能通过SourceForge 的匿名CVS 服务来访问这些工程,或者下载与标准版本不同的差别文件。 
 
第3章 编译和安装 

3.1 安装之前 

假如你使用unix 有一段时间,并且已编译过许多其他软件包,那么只需快速的扫描本章。编译安装 的过程与安装其他软件相似。 

为了编译,你需要一个ANSI C 编译器。不要被ANSI 字眼吓倒。假如你已经有一个编译器,它顺从ANSI 指令,那么也一样。GNU C 编译器(gcc)是很好的选择,它被广泛使用。大部分操作系统在其标准安装中附带了C 编译器,不过Solaris 和HP-UX 除外。假如你使用这样的操作系统,那可能没有安装编译器。 

理论上你应该在即将运行 的机器上编译。安装过程侦察你的操作系统以发现特定的参数,例如可用文件描述符的数量。然而,假如你的系统没有C 编译器存在,你也许会在其他机器上编译,然后把二进制代码copy 回来。如果操作系统不同,那么可能会遇到问题。假如操作系统有不同的内核配置, 会变得混乱。 

除了C 编译器,你还需要perl 和awk。awk 是所有unix 系统的标准程序,所以你不必担心它。perl 也是相当普及的,但它也许没有默认安装在你的系统上。你需要gzip 程序来解压源代码发布文件。 

对Solaris 用户,请确认/usr/ccs/bin 包含在你的PATH 环境变量里,即使你使用gcc编译器。为了编译,make 和ar 程序需要在这个目录找到。 

3.2 解开源代码包 

在下载完源代码后,你需要在某个目录解开它。具体哪个目录无关紧要。你能解开在你的家目录或任何其他地方,大概需要20M 的自由磁盘空间。我个人喜欢用/tmp。使用tar 命令来展开源代码目录: 
% cd /tmp 
% tar xzvf /some/where/-2.5.STABLE4-src.tar.gz 

一些tar 程序不支持z选项,该选项自动解压gzip 文件。如果这样,你需要运行如下命令: 
% gzip -dc /some/where/-2.5.STABLE4-src.tar.gz | tar xvf - 

一旦源代码被展开,下一步通常是配置源代码树。然而,假如这是你第一次编译,你应确认特定的内核资源限制足够高。怎样发现,请继续。 

3.3 调整内核 

Squid 在高负载下,需要大量的内核资源。特别的,你需要给你的系统配置比正常情况更高的文件描述符和缓存。文件描述符的限制通常很恼人。你最好在开始编译 之前来增加这些限制的大小。 

因为这点,你可能为了避免重建内核的麻烦,而倾向于使用预编译的二进制版本。不幸的是,不管如何你必须重建一个新内核。 和内核通过数据结构来交换信息,数据结构的大小不能超过设置的文件描述符的限制。 在运行时检查这些设置,并且使用最安全的(最小的)值。这样,即使预编译的二进制版本有比你的内核更高的文件描述符,但还是以你系统内核的实际数值为主。 

为了改编一些参数,你需要重建新内核。这个过程在不同的操作系统之间不同。假如需要,请参阅Unix 系统管理员手册(Prentice Hall 出版)或者你的操作系统文档。假如你正使用Linux,可能不必重建内核。 

3.3.1 文件描述符 

文件描述符是一个简单的整数,用以标明每一个被进程所打开的文件和socket。第一个打开的文件是0,第二个是1,依此类推。Unix 操作系统通常给每个进程能打开的文件数量强加一个限制。更甚的是,unix 通常有一个系统级的限制。 

因为 的工作方式,文件描述符的限制可能会极大的影响性能。当 用完所有的文件描述符后,它不能接收用户新的连接。也就是说,用完文件描述符导致拒绝服务。直到一部分当前请求完成,相应的文件和socket 被关闭, 不能接收新请求。当发现文件描述符短缺时,它会发布警告。 

在运行./configure 之前,检查你的系统的文件描述符限制是否合适,能给你避免一些麻烦。大多数情况下,1024 个文件描述符足够了。非常忙的cache可能需要4096或更多。在配置文件描述符限制时,我推荐设置系统级限制的数量为每个进程限制的2 倍。 

通常在你的Unix shell 中能找到系统的文件描述符限制。所有的C shell 及其类似的shell有内建的limit 命令。更新的Bourne shell 及其类似的shell 有一条叫做ulimit 的命令。为了发现你的系统的文件描述符限制,试运行如下命令: 
csh% limit descriptors unlimited 
csh% limit descriptors 
descriptors 4096 

或者 

sh$ ulimit -n unlimited 
sh$ ulimit -n 
4096 

在Freebsd 上,你能使用sysctl 命令: 
% sysctl -a | grep maxfiles 
kern.maxfiles: 8192 
kern.maxfilesperproc: 4096 

如果你不能确认文件描述符限制, 的./configure 脚本能替你做到。当你运行./configure 时,请见3.4 章节,观察末尾这样的输出: 
checking Maximum number of file descriptors we can open... 4096 

假如其他的limit,ulimit,或者./configure 报告这个值少于1024,你不得不在编译 之前,花费时间来增加这个限制值的大小。否则, 在高负载时执行性能将很低。 

增加文件描述符限制的方法因系统不同而不同。下面的章节提供一些方法帮助你开始。 

3.3.1.1 Freebsd,NetBSD,OpenBSD 

编辑你的内核配置文件,增加如下一行: 
options MAXFILES=8192 

在OpenBSD 上,使用option 代替options。然后,configure,编译,和安装新内核。最后重启系统以使内核生效。 

3.3.1.2 Linux 

在Linux 上配置文件描述符有点复杂。在编译 之前,你必须编辑系统include 文件中的一个,然后执行一些shell 命令。请首先编辑/usr/include/bits/types.h 文件,改变__FD_SETSIZE 的值: 
#define _ _FD_SETSIZE 8192 

下一步,使用这个命令增加内核文件描述符的限制: 
# echo 8192 > /proc/sys/fs/file-max 

最后,增加进程文件描述符的限制,在你即将编译 的同一个shell 里执行: 
sh# ulimit -Hn 8192 

该命令必须以root 运行,仅仅运行在bash shell。不必重启机器。 

使用这个技术,你必须在每一次系统启动后执行上述echo 和ulimit 命令,或者至少在 启动之前。假如你使用某个rc.d 脚本来启动,那是一个放置这些命令的好地方。 

3.3.1.3 Solaris 

增加该行到你的/etc/system 文件: 
set rlim_fd_max = 4096 

然后,重启机器以使改动生效。 

3.3.2 Mbuf Clusters 

BSD 基础的网络代码使用一个叫做mbuf(参阅W.R.Stevens 的TCP/IP 描述卷2)的数据结构。Mbuf 典型的是小块内存(例如128 字节)。较大的网络包的数据存储在mbuf clusters里。内核可能给系统可用的mbuf clusters 的总数量强加一个最高限制。你能使用netstat 命令来发现这个限制: 
% netstat -m 
196/6368/32768 mbufs in use (current/peak/max): 
146 mbufs allocated to data 
50 mbufs allocated to packet headers 
103/6182/8192 mbuf clusters in use (current/peak/max) 
13956 Kbytes allocated to network (56% of mb_map in use) 
0 requests for memory denied 
0 requests for memory delayed 
0 calls to protocol drain routines 

在这个例子里,有8192 个mbuf clusters 可用,但是永远不会同时用到6182 个。当系统用尽mbuf clusters 时,I/O 机制例如read()和write()返回“无缓存空间可用”的错误信息。 

NetBSD 和OpenBSD 使用netstat -m 不会显示mbuf 的输出。代替的,它们在syslog 里报告:"WARNING: mclpool limit reached" 。 

为了增加mbuf clusters 的数量,你必须在内核配置文件里增加一个选项: 
options NMBCLUSTERS=16384 
Squid 中文权威指南 3 

3.3.3 临时端口范围 

临时端口是TCP/IP 栈分配给出去连接的本地端口。换句话说,当 发起一条连接到另一台服务器,内核给本地socket 分配一个端口号。这些本地端口号有特定的范围限制。 

例如,在FreeBSD 上,默认的临时端口范围是1024-5000。 

临时端口号的短缺对非常忙的代理服务器(例如每秒数百个连接)来说,会较大的影响性能。这是因为一些TCP 连接在它们被关闭时进入TIME_WAIT 状态。当连接进入TIME_WATI 状态时,临时端口号不能被重用。 

你能使用netstat 命令来显示有多少个连接进入这个状态: 

% netstat -n | grep TIME_WAIT 
Proto Recv-Q Send-Q Local Address Foreign Address (state) 
tcp4 0 0 192.43.244.42.19583 212.67.202.80.80 TIME_WAIT 
tcp4 0 0 192.43.244.42.19597 202.158.66.190.80 TIME_WAIT 
tcp4 0 0 192.43.244.42.19600 207.99.19.230.80 TIME_WAIT 
tcp4 0 0 192.43.244.42.19601 216.131.72.121.80 TIME_WAIT 
tcp4 0 0 192.43.244.42.19602 209.61.183.115.80 TIME_WAIT 
tcp4 0 0 192.43.244.42.3128 128.109.131.47.25666 TIME_WAIT 
tcp4 0 0 192.43.244.42.3128 128.109.131.47.25795 TIME_WAIT 
tcp4 0 0 192.43.244.42.3128 128.182.72.190.1488 TIME_WAIT 
tcp4 0 0 192.43.244.42.3128 128.182.72.190.2194 TIME_WAIT 

注意这个例子中既有客户端连接又有服务器端的连接。客户端连接有3128作为临时端口号,服务器端连接有80作为远程主机的端口号。临时端口号出现在本地地址栏里。在该例子里,它们是19000 秒。 

如果你没有看到数千个临时端口在TIME_WAIT状态,那也许不必增加这个端口范围。 

在Freebsd 上,用如下命令增加临时端口范围: 
# sysctl -w net.inet.ip.portrange.last=30000 

在OpenBSD 上,命令类似,但sysctl 变量有不同的名字: 
# sysctl -w net.inet.ip.portlast=49151 

在NetBSD 上,事情稍有不同。默认的值是49152-65535.为了增加这个范围,需改变最低限制: 
# sysctl -w net.inet.ip.anonportmin=10000 

在Linux 上,简单的写一对数字到下列指定文件: 
# echo "1024 40000" > /proc/sys/net/ipv4/ip_local_port_range 

不要忘记将这些命令加到你的系统启动脚本中,以使机器每一次重启后都生效。 

3.4 Configure 脚本 

象许多其他Unix 软件一样,在开始编译之前使用./configure脚本来了解操作系统信息。./configure脚本由流行的GNU autoconf程序产生。当script运行时,它用不同的方法来侦察系统,以发现关于库,函数,类型,参数,和有没有功能被提供等。./configure所做的第一件事情是去找一个C 编译器。假如C编译器没有找到,或者编译一个简单的测试程序失败,./configure脚本不能继续。 

./configure 脚本有大量的选项。最重要的是安装prefix。在运行./configure 之前,你需要决定 被安装在哪里。prefix选项指定日志,二进制文件,和配置文件的默认位置。你可以在安装之后改变这些文件的位置,但假如你现在决定,事情更容易。 

默认的安装位置是/usr/local/.将文件放在prefix 指定目录下面的7 个子目录: 

% ls -l /usr/local/ 
total 5 
drwxr-x--- 2 wessels wheel 512 Apr 28 20:42 bin 
drwxr-x--- 2 wessels wheel 512 Apr 28 20:42 etc 
drwxr-x--- 2 wessels wheel 512 Apr 28 20:42 libexec 
drwxr-x--- 3 wessels wheel 512 Apr 28 20:43 man 
drwxr-x--- 2 wessels wheel 512 Apr 28 20:42 sbin 
drwxr-x--- 4 wessels wheel 512 Apr 28 20:42 share 
drwxr-x--- 4 wessels wheel 512 Apr 28 20:43 var 

Squid 使用bin,etc,libexec,man,sbin,和share 目录存放一些相对较小的文件(或其他目录),这些文件不经常改变。但var目录的文件别有洞天。这里你可以发现 的日志文件,它增长得非常大(数十或数百兆)。var 也是实际磁盘cache 的默认位置。你也许想将var 目录放在磁盘空间足够的位置,这样做较容易的方法是使用--localstatedir 选项: 
% ./configure --localstatedir=/bigdisk/var 

当配置 时,你不必对这些路径名称担心太多。你以后可以在.conf文件里改变这些路径名。 

3.4.1 configure 选项 

./configure 脚本有大量的不同选项,它们以-开始。当你敲入./configure --help 时,能看到选项的完整列表。一些选项对所有configure 脚本是通用的,还有一些是 专有的。下面是你可能用得到的标准选项: 
--perfix =PREFIX 

如前面描述的一样,这里设置安装目录。安装目录是所有可执行文件,日志,和配置文件的默认目录。在整本书中,$prefix 指你选择的安装目录。 

--localstatedir =DIR 
该选项允许你改变var 目录的安装位置。默认是$prefix/var,但也许你想改变它,以使 的磁盘缓存和日志文件被存储在别的地方。 

--sysconfdir =DIR 
该选项允许你改变etc 目录的位置。默认的是$prefix/etc。假如你想使用/usr 作为安装位置,你也许该配置--sysconfdir为/etc. 

以下是 的专有./configure选项: 

--enable-dlmalloc[=LIB] 
在一些系统上,内建的内存分配机制(malloc)在使用 时表现不尽人意。使用--enable-dlmalloc 选项将 源代码包中的dlmalloc 包编译和链接进来。假如你的系统中已安装dlmalloc,你能使用=LIB 参数指定库的路径。请见更多关于dlmalloc 的信息。 

--enable-gnuregex 
在访问控制列表和其他配置指令里, 使用正则表达式作为匹配机制。GNU 的正则表达式库包含在 的源代码包里;它可以在没有内建正则表达式的操作系统中使用。./configure脚本侦察你系统中的正则表达式库,假如必要,它可以激活使用GNU正则表达式。如果因为某些理由,你想强制使用GNU正则表达式,你可以将这个选项加到./configure命令后。 

--enable-carp 
Cache数组路由协议(CARP)用来转发丢失的cache到父cache的数组或cluster。在10.9章有更多关于CARP的细节。 

--enable-async-io[=N_THREADS] 
同步I/O 是 技术之一,用以提升存储性能。aufs 模块使用大量的线程来执行磁盘I/O 操作。该代码仅仅工作在linux 和solaris 系统中。=N_THREADS 参数改变 使用的线程数量。aufs 和同步I/O 在8.4 章中被讨论。 
请注意--enable-async-io 是打开其他三个./configure 选项的快捷方式,它等同于: 
--with-aufs-threads=N_THREADS 
--with-pthreads 
--enable-storeio=ufs,aufs 
--with-pthreads 

该选项导致编译过程链接到你系统中的P 线程库。aufs 存储模块是 中唯一需要使用线程的部分。通常来说,如果你使用--enable-saync-io 选项,那么不必再单独指定该选项,因为它被自动激活了。 

--enable-storeio=LIST 
Squid 支持大量的不同存储模块。通过使用该选项,你告诉 编译时使用哪个模块。在-2.5 中,支持ufs,aufs,diskd,和null 模块。通过查询src/fs 中的目录,你能得到一个模 
块列表。 
LIST 是一个以逗号分隔的模块列表,例如: 
% ./configure --enable-storeio=afus,diskd,ufs 

ufs 模块是默认的,看起来问题最少。不幸的是,它性能有限。其他模块可能在某些操作系统中不必编译。关于 存储模块的完整描述,请见第8章。 
--with-aufs-threads=N_THREADS 

指定aufs 存储机制使用的线程数量(见8.4章)。 默认根据缓存目录的数量,自动计算需要使用多少线程。 

--enable-heap-replacement 
该选项不再使用,但被保留用于向后兼容性。你该使用--enable-removal-policies 来代替。 

--enable-removal-policies=LIST 
排除策略是 需要腾出空间给新的cache目标时,用以排除旧目标的机制。-2.5支持3个排除策略:最少近期使用(LRU),贪婪对偶大小(GDS),最少经常使用(LFU)。 

然而,因为一些理由,./configure 选项使指定的替代策略和需要执行它们的基本数据结构之间的差别模糊化。LRU是默认的,它以双链表数据结构执行。GDS和LFU使用堆栈的数据结构。 

为了使用GDS 或LFU 策略,你指定: 
% ./configure --enable-removal-policies=heap 

然后你在 的配置文件里选择使用GDS或LFU。假如你想重新使用LRU,那么指定: 
% ./configure --enable-removal-policies=heap,lru 
更多的关于替换策略的细节请见7.5 章。 

--enable-icmp 
如在10.5 章中描述的一样, 能利用ICMP消息来确定回环时间尺寸,非常象ping程序。你能使用该选项来激活这些功能。 

--enable-delay-pools 
延时池是 用于传输形状或带宽限制的技术。该池由大量的客户端IP 地址组成。当来自这些客户端的请求处于cache 丢失状态,他们的响应可能被人工延迟。关于延时池的更多细节请见附录C。 

--enable-useragent-log 
该选项激活来自客户请求的HTTP 用户代理头的日志。更多细节请见13.5 章。 

--enable-referer-log 
该选项激活来自客户请求的HTTP referer 日志。更多细节请见13.4 章。 

--disable-wccp 
Web cache 协调协议(WCCP)是CISCO 的专有协议,用于阻止或分发HTTP 请求到一个或多个caches。WCCP默认被激活,假如你愿意,可以使用该选项来禁止该功能。 

--enable-snmp 
简单网络管理协议(SNMP)是监视网络设备和服务器的流行方法。该选项导致编译过程去编译所有的SNMP相关的代码,包括一个裁切版本的CMU SNMP库。 

--enable-cachemgr -hostname[=hostname] 
cachemgr 是一个CGI程序,你能使用它来管理查询。默认cachemgr的hostname值是空的,但你能使用该选项来指定一个默认值。例如: 
% ./configure --enable-cachemgr-hostname=mycache.myorg.net 

--enable-arp-acl 
 在一些操作系统中支持ARP,或者以太地址访问控制列表。该代码使用非标准的函数接口,来执行ARP访问控制列表,所以它默认被禁止。假如你在linux或solaris上使用,你可能用的上这个功能。 

--enable-htcp 
HTCP 是超文本缓存协议--类似于ICP的内部缓存协议。更多细节请见10.8 章。 

--enable-ssl 
使用该选项赋予 终止SSL/TLS 连接的能力。注意这仅仅工作在web加速器中用以加速请求。更多细节请见15.2.2 章节。 

--with-openssl[=DIR] 
假如必要,你使用该选项来告诉到哪里找到OpenSSL库或头文件。假如它们不在默认位置,在该选项后指定它们的父路径。例如: 
% ./configure --enable-ssl --with-ssl=/opt/foo/openssl 
在这个例子中,你的编译器将在/opt/foo/openssl/include目录中找头文件, 在/opt/foo/openssl/lib 中找库文件。 

--enable-cache-digests 
Cache 消化是ICP 的另一个替代,但有着截然不同的特性。请见10.7 章。 

--enable-err-languages="lang1 lang2 ..." 
支持定制错误消息,错误消息可以用多种语言报告。该选项指定复制到安装目录($prefix/share/errors)的语言。假如你不使用该选项,所有可用语言被安装。想知道何种语言可用,请见源代码包里errors目录下的目录列表。如下显示如何激活多种语言: 
% ./configure --enable-err-languages="Dutch German French" ... 

--enable-default-err-language=lang 
该选项设置error_directory 指令的默认值。例如,假如你想使用荷兰语,你能这样指定: 
% ./configure --enable-default-err-language=Dutch 
你也能在.conf 里指定error_directory 指令,在附录A 中有描述。假如你忽略该选项,英语是默认错误语言。 

--with-coss-membuf-size=N 
循环目录存储系统(coss)是 的试验性存储机制。该选项设置coss 缓存目录的内存缓冲大小。注意为了使用coss,你必须在--enable-storeio 选项里指定存储类型。 
该参数以字节形式赋值,默认是1048576 字节或1M。你能指定2M 缓冲如下: 
% ./configure --with-coss-membuf-size=2097152 

--enable-poll 
unix 提供两个相似的函数用以在I/O 事件里扫描开放文件描述符:select() 和poll()。./configure 脚本通常能非常好的计算出何时使用poll()来代替select().假如你想强制使用poll(),那么指定该选项。 
--desable-poll 
类似的,如果不使用poll(),那么指定该选项。 

--disable-http-violations 
 默认可以被配置成违背HTTP协议规范。你能使用该选项来删除违背HTTP协议的代码。 

--enable-ipf-transparent 
在第9章中,我将描述如何配置来拦截缓存。一些操作系统使用IP Filter包来协助拦截缓存。在这些环境下你应该使用该./configure 选项。如果你使用了该选项,但是编译器提示src/client_side.c文件出错,那是因为IP Filter包没有或没有正确的安装在你的系统中。 

--enable-pf-transparent 
你可能需要指定该选项,使用PF包过滤器在操作系统中拦截HTTP。PF是OpenBSD的标准包过滤器,也可能被发布到其他系统中。假如你使用该选项,但是编译器提示src/client_side.c 文件出错,那是因为PF 没有实际安装到你的系统中。 

--enable-linux-netfilter 
Netfilter 是linux 2.4 系列内核的包过滤器名字。假如你想在linux2.4或以后的版本中使用HTTP拦截功能,那么激活该选项。 

--disable-ident-lookups 
ident是一个简单的协议,允许服务器利用客户端的特殊TCP连接来发现用户名。假如你使用该选项,编译器将把执行这些查询的代码排除出去。即使你在编译时保留了这些代码,除非你在.conf文件里指定,不会执行ident查询。 

--disable-internal-dns 
 源代码包含两个不同的DNS 解决方案,叫做“内部的”和“外部的”。内部查询是默认的,但某些人可能要使用外部技术。该选项禁止内部功能,转向使用旧的方式。 
内部查询使用自己的DNS协议执行工具。也就是说,产生未完成的DNS查询并且将它们发送到一个解析器。假如超时,它重新发送请求,你能指定任意数量的解析器。该工具的有利处之一是,获得准确无误的DNS响应的TTLs。 
外部查询利用C库的gethostbyname()和gethostbyaddr()函数。使用一个外部进程池来制造并行查询。使用外部DNS 解析的主要弊端是你需要更多的辅助进程,增加的负载。另一个麻烦是C 库函数不在响应里传输TTLs,这样使用postive_dns_ttl 指令提供的一个常量值。 

--enable-truncate 
truncate()系统调用是unlink()的替代品。unlink()完全删除cache 文件,truncate()将文件大小设为零。这样做释放了分配给该文件的磁盘空间,但留下适当的目录接口。该选项存在的理由是,某些人相信(或希望)truncate()比unlink()性能表现更好。然而,压力测试显示两者有很少的或根本没有区别。 

--disable-hostname-checks 
默认的,要求URL主机名在一定程度上遵守古老的RFC 1034 规范: 
标签必须遵循下列ARPANET 主机名规则。它们必须以字母开始,以字母或数字结尾,仅仅包含字母,数字和下划线。 
这里字母意味着ASCII字符,从A到Z。既然国际域名日益流行,你可能希望使用该选项来移除限制。 

--enable-underscores 
该选项控制针对主机名里下划线的行为。通用的标准是主机名里不包含下划线字符,尽管有些人不赞成这点。默认会对URL主机名里带下划线的请求产生一条错误消息。你能使用该选项,让信任它们,把它们当作合法的。然而,你的DNS解析器也许强迫使用非下划线请求,并且对带下划线的主机名解析失败。 

--enable-auth[=LIST] 
该选项控制在的二进制文件里支持哪种验证机制。你能选择下列机制的任意组合: 
basic,digest,ntlm。假如你忽略该选项, 仅仅支持basic 验证。假如你使用不带参数的--enable-auth选项,编译进程将增加对所有验证机制的支持。你可以使用以逗号分隔的验证机制列表: 
% ./configure --enable-auth=digest,ntlm 
我在第六章和第十二章里会谈得更多。 

--enable-auth-helpers=LIST 
这个旧选项现在已舍弃了, 但为了保持向后兼容性仍保留着。你可以使用--enable-basic-auth-helperes=LIST 来代替。 

--enable-basic-auth-helpers=LIST 
使用该选项,你能将helpers/basic_auth 目录的一个或多个HTTP Basic验证辅助程序编译进来。请见12.2章找到它们的名字和描述。 

--enable-ntlm-auth-helpers=LIST 
使用该选项,你能将helpers/ntlm_auth 目录的一个或多个HTTP NTLM验证辅助程序编译进来。请见12.4章找到它们的名字和描述。 

--enable-digest-auth-modules=LIST 
使用该选项,你能将helpers/digest_auth 目录的一个或多个HTTP Digest验证辅助程序编译进来。请见12.3章找到它们的名字和描述。 

--enable-external-acl-helpers=LIST 
使用该选项,你能编译一个或多个扩展ACL辅助程序,这些在12.5章中讨论。例如: 
% ./configure --enable-external-acl-helpers=ip_user,ldap_group 

--disable-unlinkd 
unlinkd 是另一个的外部辅助进程。它的基本工作是对cache文件执行unlink()或truncate()系统调用。通过在外部进程里执行文件删除工作,能给带来明显的性能提升。使用该选项来禁止外部unlink进程功能。 

--enable-stacktrace 
某些系统支持在程序崩溃时,自动产生数据追踪。当你激活该功能后,如果崩溃,数据追踪信息被写到cache.log文件。这些信息对开发和程序bug调试有用。 

--enable-x-accelerator-vary 
该高级功能可能在被配置成加速器时使用。它建议在响应请求时,从后台原始服务器中寻找X-Accelerator-Vary头。请见15.5章。 

3.4.2 运行configure 

现在我们准备运行./configure 脚本。进入源代码的顶级目录敲入./configure,后面跟上前面提到过的任意选项,例如: 
% cd -2.5.STABLE4 
% ./configure --enable-icmp --enable-htcp 

./configure 的工作就是侦察你的操作系统,以发现什么东西可用,什么不可用。它首先做的事情之一就是确认你的C编译器可用。假如./configure检测到你的C编译器有问题,脚本会退出,返回如下错误: 
configure: error: installation or configuration problem: C compiler 
cannot create executables. 

很可能你从不会看到这个消息。假如看到了,那意味着你的系统中没有C 编译器存在,或者编译器没有正确安装。请见config.log文件找到解决问题的建议。假如你的系统中有多个C编译器,你可以在运行./configure 之前设置CC环境变量,来告诉./configure使用哪个: 
% setenv CC /usr/local/bin/gcc 
% ./configure ... 

在./configure 检查完该编译器后,它查找头文件,库文件和函数的长列表。通常你不必担心该部分。在某些实际情况中,./configure会终止以引起你的注意,某些事情可能有问题,例如没有足够的文件描述符。假如你指定不完整的或不合理的命令行选项,它也会终止。假如有错误发生,请检查config.log 输出。./configure 的最终任务是创造Makefiles和其他文件,这些文件基于从你系统中了解到的知识。到此为止,你准备做编译工作。 

3.5 编译 

一旦./configure 完成了它的工作,你简单的敲入make 开始编译源代码: 
%make 

正常来说,该过程很顺利,你可以见到大量的滚动行。 
你也许见到一些编译器警告。大多数情况下,可以安全的忽略这些。假如这些警告非常多,并且一些看起来非常严重,请将它们报告给开发者,在第16.5 章中有描述。 
假如编译过程没有错误,你可以转移到下一节,描述如何安装你刚才编译的程序。 
为了验证编译是否成功,你可以再次运行make。你将看到如下输出: 
% make 
Making all in lib... 
Making all in scripts... 
Making all in src... 
Making all in fs... 
Making all in repl... 
'' is up to date. 
'client' is up to date. 
'unlinkd' is up to date. 
'cachemgr.cgi' is up to date. 
Making all in icons... 
Making all in errors... 
Making all in auth_modules... 

因为许多理由,编译步骤也许会失败,包括: 

源代码bugs 

通常源代码是完整的调试过的。然而,你也许会遇到某些bugs或问题从而阻止你编译。这种问题在新的开发版本中更容易出现,请将它们报告给开发者。 


编译器安装问题 

不正确安装的C编译器不能够编译或其他软件包。通常编译器随着操作系统预安装,所以你不必担心它。然而,假如你在操作系统安装完后,试图升级编译器,那么可能会犯错误。绝对不要把已经安装好的编译器从一台机器拷贝到另一台,除非你绝对清楚你在做什么。我觉得在每台机上独立的安装编译器总是最好的。 

请确认你的编译器的头文件总是与库文件同步。头文件通常在/usr/include目录,而库文件在/usr/lib目录。Linux的流行RPM系统允许它去升级其中之一,但并非另一个。假如库文件基于不同的头文件,不能编译。 

假如你想在开源BSD 变种之一中升级编译器,请确认在/usr/src目录中运行make world,这好过从/usr/src/lib 或/usr/src/include 中运行。 


如下是一些通用的编译器问题和错误消息: 

Solaris: make[1]: *** [libmiscutil.a] Error 255 
这意味着./configure 不能发现ar程序。请确认/usr/ccs/bin位于你的PATH环境变量里。假如你没有安装Sun 的编译器, 那么需要GNU 的工具。(). 

Linux: storage size of 'rl' isn't known 
这是因为头文件和库文件不匹配所致,象前面描述的一样。请确认同时升级两者。 

Digital Unix: Don't know how to make EXTRA_libmiscutil_a_SOURCES. Stop. 
Digital Unix的make 程序不能兼容automake 包产生的Makefile文件。例如,lib/Makefile.in包含如下行: 
noinst_LIBRARIES = \ 
@LIBDLMALLOC@ \ 
libmiscutil.a \ 
libntlmauth.a \ 
@LIBREGEX@ 
在替换后,当lib/Makefile 被创建时,它看起来如下: 
noinst_LIBRARIES = \ 

libmiscutil.a \ 
libntlmauth.a \ 
 
象上面显示的一样,最后一行包括一个不可见的TAB字符,它阻止了make。通过安装和使用GNU make,或者手工编辑lib/Makefile 如下,来解决这个问题: 
noinst_LIBRARIES = \ 

libmiscutil.a \ 
libntlmauth.a 


假如你在编译时遇到问题,请先检查FAQ。你也许该在Squid的web站点上搜索(使用主页里的搜索栏)。最后,假如你仍有问题,请发邮件到-users@-cache.org列表。 

3.6 安装 

在编译完后,你需要把程序安装到指定的目录。可能需要超级用户权限来把它们放置到安装目录。所以,请先切换到root: 
%su 
password: 
#make install 

假如你通过使用--enable-icmp 选项,激活了 的ICMP衡量功能,那么必须安装pinger程序。pinger 程序必须以超级用户权限安装,因为仅仅允许root 来发送和接受ICMP 消息。 

下列命令以相应的许可来安装pinger 程序: 
#make install-pinger 

在安装完后,你将在 的安装目录里(默认是/usr/local/)见到下列目录和文件: 

sbin 
sbin 目录的程序正常只能被root 启动 

sbin/ 
Squid 的主程序 

bin 
bin 目录包含对所有用户可用的程序 

bin/RunCache 
RunCache是一个shell脚本,你能用它来启动。假如死掉,该脚本自动重启它,除非它检测到经常的重启。RunCache是一个时间遗留的产物,那时Squid还不是后台服务进程。在最近的版本里,RunCache很少用到,因为Squid自动重启它自身,当你不使用-N选项时。 

bin/RunAccel 
RunAccel 与RunCache 几乎一致,唯一的不同是它增加了一个命令行参数,告诉在哪里侦听HTTP 请求。 

bin/client 
client 是个简单的HTTP 客户端程序,你能用它来测试。它也有一些特殊功能,用以对运行的 进程发起管理请求。 

libexec 
libexec 目录传统的包含了辅助程序。有一些命令你不能正常的启动。然而,这些程序通常被其他程序启动。 

libexec/unlinkd 
unlinkd是一个辅助程序,它从cache目录里删除文件。如你后面看到的一样,文件删除是个性能瓶颈。通过在外部进程里执行删除操作,Squid提升了一些执行性能。 

libexec/cachemgr.cgi 
cachemgr.cgi是Squid管理功能的CGI接口。为了使用它,你需要拷贝该程序到你的WEB服务器的cgi-bin目录。在14.2章中有更多描述。 

libexec/diskd(optional) 
假如你指定了--enable-storeio=diskd,你才能看到它。 

libexec/pinger(optional) 
假如你指定了--enable-icmp,你才能看到它。 

etc 
etc 目录包含 的配置文件。 

etc/.conf 
这是的主要配置文件。初始的该文件包含了大量的注释,用以解释每一个选项做什么。在你理解了这些配置指令后,建议你删除这些注释,让配置文件更小和更容易阅读。注意假如该文件存在,安装过程不会覆盖该文件。 

etc/.conf.default 
这是从源代码目录中拷贝过来的默认配置文件。在升级了安装后,你也许发现有一份当前默认配置文件的拷贝是有用的。可能会增加新的配置指令,一些存在的旧指令可能有所改变。 

etc/mime.conf 
mime.conf文件告诉 对从FTP和Gopher服务器获取的数据使用何种MIME类型。该文件是一个关联文件名扩展到MIME类型的表。正常而言,你不必编辑该文件。然而,你可能需要增加特殊文件类型的接口,它们在你的组织内使用。 

etc/mime.conf.default 
这是从源代码目录里拷贝过来的默认mime.conf文件。 

share 
share目录通常包括的只读数据文件。 

share/mib.txt 
这是的SNMP管理信息基础(MIB)文件。自身不使用该文件,然而,你的SNMP客户端软件(例如snmpget和多路由走向图(MRTG))需要该文件,用以理解来自的SNMP对象可用。 

share/icons 
share/icons目录包含大量的小图标文件,用在FTP和Gopher目录列举里。正常而言,你不必担心这些文件,但如果需要,你可以改变它们。 

share/errors 
share/errors目录包含了显示给用户看的错误消息模板。这些文件在你安装时,从源代码目录拷贝而来。如果需要你可以编辑它们。然而,在每次运行make install时,安装过程总会覆盖它们。所以假如你想定制错误消息,建议你把它们放在不同的目录。 

var 
var目录包含了不是很重要的和经常变化的文件。这些文件你不必正常的备份它们。 

var/logs 
var/logs目录是 不同日志文件的默认位置。当你第一次安装 时,它是空的。一旦开始运行,你能在这里看到名字为access.log,cache.log和store.log这样的文件。 

var/cache 
假如你不在.conf文件里指定,这是默认的缓存目录(cache_dir)。第七章有关于缓存目录的所有细节。 

3.7 打补丁 

在你运行一段时间后,你可能发现需要打源代码补丁,用以修正bug或者增加试验性的功能。在-cache.org站点上,对重要的bug修正会发布补丁。假如你不想等到下一个官方发布版本,你能下载补丁,并且打到你的源代码中。然后你需要重新编译。 

为了打补丁-或者有时候叫差别文件-你需要一个叫做"patch"的程序。你的操作系统必须有该程序。如果没有,你可以从GNU工具集里下载(). 

注意假如你在使用匿名CVS(见2.4 节),你不必担心补丁文件。当你升级源代码树时,CVS系统自动升级了补丁。 

为了打补丁,你必须把补丁文件存放在系统中某处。然后进入到的源代码目录,运行如下命令: 

% cd -2.5.STABLE4 
% patch < /tmp/patch_file 

默认的,在patch程序运行时,它告诉你它正在做什么。通常输出滚动非常快,除非有问题。你能安全的忽略它输出的offset NNN lines警告。假如你不想见到所有这些输出,使用-s选项选择安静模式。 

当补丁更新了源代码后,它创造了原始文件的拷贝。例如,假如你对src/http.c 打一个补丁,备份文件名就是src/http.c.orig。这样,假如你在打了补丁后想撤销这个操作,简单的重命名所有的.orig 文件到它们以前的格式。为了成功的使用该技术,建议你在打补丁之前删除所有的.orig 文件。 

假如patch 程序遇到问题,它停止运行并且给出建议。通常问题如下: 

在错误的目录运行patch程序——解决的方法是,进入到正确的目录,或者使用patch的-p选项。 

补丁已打过——patch会告诉你是否已打过补丁文件。在这样的情况下,它会问你是否撤销这个文件的补丁。 

patch 程序不能理解你赋给它的文件——补丁文件通常有三个风格:正常的,context的和unified的。旧版本的patch 程序可能不理解后两者的差异输出。从GNU的FTP站点获取最近的版本能解决该问题。 

损坏的补丁文件——假如你在下载和存储补丁文件时不小心,它有可能被损坏。有时候人们以email消息发送补丁文件,在新的窗口里,它们被简单的剪切和粘贴。 

在这样的系统中,剪切和粘贴能将Tab字符改变为空格,或者不正确的捆绑长行。这些改变混乱了patch。-l选项也许有用,但最好是正确的拷贝和存储补丁文件。 

某些时候patch不能应用部分或所有的差别文件——在这样的情况下,你能见到类似于Hunk 3 of 4 failed的消息。失败的部分被存储在命名为.rej的文件里。例如,假如在处理src/http.c时失败,patch 程序将该差别文件片断存为src/http.c.rej。在这样的情况下,你也许能手工修正这些问题,但它通常不值得这么做。假如你有大量的"failed hunks"或者.rej文件,建议你去下载最近源代码版本的完整新拷贝。 

在你打完补丁后,你必须重新编译。make的先进功能之一就是它仅仅编译改变了的文件。但有时候make不能理解错综复杂的依赖关系,它没有完整的重编译所需文件。为了安全起见,通常建议你去重编译所有文件。最好的方法是在开始编译之前清除源代码树: 

%make clean 
%make 

3.8 重运行configure 

有时候你可能发现有必要重新运行./configure。例如,假如你调整了内核参数,你必须再次运行./configure以使它能发现新设置。当你阅读本书时,你也发现你必须使用./configure选项来激活所需的功能。 

以相同的选项重运行./configure,使用如下命令: 
%config.status --recheck 

另一个技术是`touch config.status`文件,它更新了该文件的时间戳。这导致make在编译源代码之前,重新运行./configure脚本: 
% touch config.status 
% make 

如果增加或删除./configure选项,你必须重新敲入完整的命令行。假如你记不住以前的选项,请查看config.status文件的顶部。例如: 
% head config.status 
#! /bin/sh 
# Generated automatically by configure. 
# Run this file to recreate the current configuration. 
Squid 中文权威指南 16 
# This directory was configured as follows, 
# on host foo.life-gone-hazy.com: 

# ./configure --enable-storeio=ufs,diskd --enable-carp \ 
# --enable-auth-modules=NCSA 
# Compiler output produced by configure, useful for debugging 
# configure, is in ./config.log if it exists. 

在运行./configure之后,你必须再次编译和安装。安全起见,建议先运行make clean: 
%make clean 
%make 

请回想一下,./configure会缓存它在你系统中发现的东西。在这样的形式下,你可能想清除这些缓存,从头开始编译过程。假如喜欢,你可以简单的删除config.cache 文件。然后,下一次./configure运行时,它不会使用以前的数值。你也能恢复源代码树到它的configure之前的状态,使用如下命令: 
%make distclean 

这将删除所有的目标文件和其他被./configure和make程序产生的文件。 
 
第4章 快速配置向导 

4.1 .conf 语法 

Squid 的配置文件相对规范。它与其他许多unix 程序相似。每行以配置指令开始,后面跟着数字值或关键字。在读取配置文件时, 忽略空行和注释掉的行(以#开始)。如下是一些配置行示例: 
cache_log //var/cache.log 
# define the localhost ACL 
acl Localhost src 127.0.0.1/32 
connect_timeout 2 minutes 
log_fqdn on 

某些指令取唯一值。在这些情形下,重复赋予该指令不同的值,将覆盖前面的值。例如, 
下面是一个连接超时值。第一行无效,因为第二行覆盖了它: 
connect_timeout 2 minutes 
connect_timeout 1 hour 

另外,某些指令取列表值。在这些情形下,每一个新增的值都有效。"扩展方式"指令以这种方法工作: 
extension_methods UNGET 
extension_methods UNPUT 
extension_methods UNPOST 

对这些基于列表的指令,你通常能在同一行中赋予多个值: 
extension_methods UNGET UNPUT UNPOST 

许多指令有通用类型。例如,连接超时值是一个时间规范,在数字后面跟着时间单元。例如: 
connect_timeout 3 hours 
client_lifetime 4 days 
negative_ttl 27 minutes 

类似的,大量的指令指向文件大小或者内存额度。例如,你可以这样编写大小规范:十进制数字后面跟bytes,KB,MB 或GB.例如: 
minimum_object_size 12 bytes 
request_header_max_size 10 KB 
maximum_object_size 187 MB 

另一种值得提起的类型是触发器,它的值是on 或者off。许多指令使用该类型。例如: 
server_persistent_connections on 
strip_query_terms off 
prefer_direct on 

通常,配置文件指令能以任何顺序出现。然而,如果某个指令指向的值被其他指令所定义,那么顺序就很重要。访问控制列表是个好的例子。acl 被用在http_access 规则之前必须被定义: 
acl Foo src 1.2.3.4 
http_access deny Foo 

.conf 文件里的许多东西是大小写敏感的,例如指令名。你不能将http_port 写成HTTP_port。 

默认的.conf 文件包含了对每个指令的大量注释,以及指令的默认值。例如: 
# TAG: persistent_request_timeout 
# How long to wait for the next HTTP request on a persistent 
# connection after the previous request completes. 

#Default: 
# persistent_request_timeout 1 minute 

每次安装 后,当前默认配置文件存放在$prefix/etc 目录下的.conf.default。既然指令每次都有所改变,你能参考该文档,以获取最近的更新。 

该章剩下的部分是关于在开始运行 之前,你必须知道的少数指令。 


4.2 User IDs 

你可能知道,unix 进程和文件拥有文件和组属主的属性。你必须选择某个用户和组给。该用户和组的组合,必须对大部分 相关的文件和目录有读和写的权限。 

我高度推荐创建名为""的用户和组。这避免了某人利用 来读取系统中的其他文件。假如不止一个人拥有对 的管理权限,你可以将他们加到 组里。 

unix 进程继承了它们父进程的属主属性。那就是说,假如你以joe 用户来启动, 也以joe 来运行。假如你不想以joe 来运行,你需要预先改变你的用户ID。这是su 命令的典型功能。例如: 
joe% su -  
% /usr/local//sbin/ 

不幸的是,运行 并非总是如此简单。在某些情况下,你必须以root 来启动,这依赖于你的配置。例如,仅仅root 能绑定TCP 套接字到特权端口上,如80。假如你必须以root 来启动,你必须设置cache_effective_user 指令。它告诉,在执行完需要特别权限的任务后,变成哪个用户。例如: 
cache_effective_user  

你提供的该名字必须是有效用户(在/etc/passwd 文件里)。请注意仅仅当你以root 来启动 时,你才需要用到该指令。仅仅root 有能力来随意改变用户身份。假如你以joe 来启动,它不能改变到 用户。 

你可能尝试不设置cache_effective_user,直接以root 来运行。假如你试过,你会发现 拒绝运行。这违背了安全规则。假如外部攻击者有能力危及或利用,他能获取对系统的全部访问权。尽管我们努力使 安全和少bug,但还是稳重点好。 

假如你没有设置cache_effective_user,以root 来启动, 使用nobody 作为默认值。不管你选择什么用户ID , 请确认它有对下面目录的读访问权:$prefix/etc,$prefix/libexec,$prefix/share。该用户ID 也必须有对日志文件和缓存目录的写访问 
权。 

 也有一个cache_effective_group 指令,但你也许不必设置它。默认的, 使用cache_effective_user 的默认组(从/etc/passwd 文件读取)。 


4.3 端口号 

http_port 指令告诉 在哪个端口侦听HTTP 请求。默认端口是3128: 
http_port 3128 

假如你将 作为加速器运行(见15 章),你也许该将它设为80。 

你能使用附加的http_port 行,来指示 侦听在多个端口上。假如你必须支持客户组(它们被配置得不一致),这点就经常有用。例如,来自某个部门的浏览器发送请求到3128, 
然而另一个部门使用80 端口。简单的将两个端口号列举出来: 
http_port 3128 
http_port 8080 

你也能使用http_port 指令来使 侦听在指定的接口地址上。当 作为防火墙运行时,它有两个网络接口:一个内部的和一个外部的。你可能不想接受来自外部的http 请求。为了使 仅仅侦听在内部接口上,简单的将IP 地址放在端口号前面: 
http_port 192.168.1.1:3128 


4.4 日志文件路径 

我将在第13 章讨论所有 的日志细节。你现在你关注的唯一事情是, 将它的日志放在何处。默认的日志目录是 安装位置下的logs 目录。例如,假如你在./configure 
时没有使用--prefix=选项,那么默认的日志文件路径是/usr/local//var/logs。 

你必须确认日志文件所存放的磁盘位置空间足够。在 写日志时如果接受到错误,它会退出和重启。该行为的主要理由应引起你的注意。 想确认你不会丢失任何重要的日志信息,特别是你的系统被滥用或者被攻击时。 

 有三个主要的日志文件:cache.log,access.log,store.log.第一个文件即cache.log,包含状态性的和调试性的消息。当你刚开始运行 时,你应密切的关注该文件。假如拒绝运行,理由也许会出现在cache.log 文件的结尾处。在正常条件下,该文件不会变得很大。也请注意,假如你以-s 选项来运行,重要的cache.log 消息也可被送到你的syslog进程。通过使用cache_log 指令,你可以改变该日志文件的路径: 
cache_log //logs/cache.log 

access.log 文件包含了对 发起的每个客户请求的单一行。每行平均约150 个字节。也就是说,在接受一百万条客户请求后,它的体积约是150M。请使用cache_access_log 指令来改变该日志文件的路径: 
cache_access_log //logs/access.log 

假如因为某些理由,你不想 记录客户端请求日志,你能指定日志文件的路径为/dev/null. 

store.log 文件对大多数cache 管理员来说并非很有用。它包含了进入和离开缓存的每个目标的记录。平均记录大小典型的是175-200 字节。然而, 不在store.log 里对cache点击创建接口,所以它比access.log 包含少得多的记录。请使用cache_store_log 指令来改变它的位置: 
cache_store_log //logs/store.log 

通过指定路径为none,你能轻易的完全禁止store.log 日志: 
cache_store_log none 

假如你不小心, 的日志文件增加没有限制。某些操作系统对单个文件强制执行2G的大小限制,即使你有充足的磁盘空间。超过该限制会导致写错误,这样 就会退出。为了保证日志文件大小合理,你应创建任务来有规律的重命名和打包日志。 有内建功能来使这个容易做到。请见13.7 章关于日志轮循的解释。 


4.5 访问控制 

在第6 章里有更多的关于访问控制的描述。现在,我只讲述少量的访问控制方法,以使热心的读者能快速开始使用。 

 默认的配置文件拒绝每一个客户请求。在任何人能使用代理之前,你必须在.conf 文件里加入附加的访问控制规则。最简单的方法就是定义一个针对客户IP 地址的ACL 和一个访问规则,告诉 允许来自这些地址的HTTP 请求。 有许多不同的ACL类型。src 类型匹配客户IP 地址, 会针对客户HTTP 请求检查http_access 规则。这样,你需要增加两行: 
acl MyNetwork src 192.168.0.0/16 
http_access allow MyNetwork 

请将这些行放在正确的位置。http_access 的顺序非常重要,但是acl 行的顺序你不必介意。你也该注意默认的配置文件包含了一些重要的访问控制,你不应该改变或删除它们,除非你完全理解它们的意义。在你第一次编辑.conf 文件时,请看如下注释: 
# Insert YOUR OWN RULE(S) HERE TO ALLOW ACCESS FROM YOUR CLIENTS 

在该注释之后,以及"http_access deny all"之前插入你自己的新规则。 

为了彻底说明,如下是一个合理的初始访问控制配置,包括推荐的默认控制和早先的例子: 
acl All src 0/0 
acl Manager proto cache_object 
acl Localhost src 127.0.0.1/32 
acl Safe_ports port 80 21 443 563 70 210 280 488 591 777 1025-65535 
acl SSL_ports 443 563 
acl CONNECT method CONNECT 
acl MyNetwork src 192.168.0.0/16 
http_access allow Manager Localhost 
http_access deny Manager 
http_access deny !Safe_ports 
http_access deny CONNECT !SSL_ports 
http_access allow MyNetwork 
http_access deny All 


4.6 可见主机名 

希望你不必担心visible_hostname 指令。然而,假如 不能发现它所运行的机器的主机名,你就必须设置它。如果发生这样的事, 抱怨和拒绝运行: 
%  -Nd1 
FATAL: Could not determine fully qualified hostname. Please set 'visible_hostname' 

有大量的理由使 需要知道主机名: 
+ 主机名出现在 的错误消息里,这帮助用户验证潜在问题的源头。 
+ 主机名出现在 转发的cache 单元的HTTP Via 头里。当请求到达原始主机时,Via头包含了在传输过程中涉及的代理列表。 也使用Via 头来检测转发环路。我将在第10章里讨论转发环路。 

 对特定事务使用内部URL,例如FTP 目录列表的图标。当 对FTP 目录产生HTML 页面时,它插入小图标用以指明该目录中的文件类型。图标URL 包含了cache 的主机名,以便web 浏览器能直接从 请求它们。 

每个从 响应的HTTP 回复包含了X-Cache 头。这并非官方HTTP 头。它是一个扩展头,用以指明该响应是cache 点击还是cache 丢失。既然请求和响应可能经过多个cache,每个X-Cache 头包含了cache 报告点击或丢失的名字。如下是一个通过2 个cache 的响应示例: 
HTTP/1.0 200 OK 
Date: Mon, 29 Sep 2003 22:57:23 GMT 
Content-type: text/html 
Content-length: 733 
X-Cache: HIT from bo2.us.ircache.net 
X-Cache: MISS from bo1.us.ircache.net 

 在启动时试图自动获取主机名。首先它调用gethostname()函数,这通常能返回正确的主机名。接着, 调用gethostbyname()函数尝试对主机名进行DNS 查询。该函数典型的返回IP 地址和系统的规范名。假如gethostbyname()成功, 在错误消息里,Via 头里等地方使用这个规范名。 

因为大量的理由, 可能不能检测到它的规范主机名,包括: 
+ 主机名可能未设置。 
+ 主机名可能从DNS 区域或/etc/hosts 文件里丢失。 

 系统的DNS 客户端配置可能不正确或丢失。在unix 系统上,你该检查/etc/resolv.conf 和/etc/host.conf 文件。 

假如你看到上述的致命错误,你必须修正主机名和DNS 信息,或者显式的给 指明主机名。在大多数情况下,请确认"hostname"命令返回一个完全规范的主机名,并且在/etc/hosts 文件里增加这个接口。假如这样不成功,请在.conf 里设置可见主机名: 
visible_hostname .packet-pushers.net 


4.7 管理联系信息 

你应该设置cache_mgr 指令作为对用户的帮助。它是一个email 地址,假如问题发生,用户能写信给它。cache_mgr 地址默认出现在 的错误消息里。例如: 
cache_mgr @web-cache.net 


4.8 下一步 

在创建了初步的配置文件后,你多少准备首次运行 了。请遵循下面章节的建议。 

当你掌握了启动和停止 后,你该花费一些时间来改善配置文件。你可能想增加更高级的访问控制,这在第6 章里有描述。既然我在这里没有讨论磁盘cache,你该花些时间阅读第7 和第8 章。 
 
第5章 运行Squid 

5.1  命令行选项 

在开始其他事情之前,让我们先看一下 的命令行选项。这里的许多选项你从不会使用,另外有些仅仅在调试问题时有用。 

-a port 
指定新的http_port 值。该选项覆盖了来自.conf 的值。然而请注意,你能在.conf里指定多个值。-a 选项仅仅覆盖配置文件里的第一个值。(该选项使用字母a 是因为在Harvest cache 里,HTTP 端口被叫做ASCII 端口) 

-d level 
让 将它的调试信息写到标准错误(假如配置了,就是cache.log 和syslog)。level参数指定了显示在标准错误里的消息的最大等级。在多数情况下,d1 工作良好。请见16.2章关于调试等级的描述。 

-f file 
指定另一个配置文件。 

-h 
显示用法。 

-k function 
指示 执行不同的管理功能。功能参数是下列之一:reconfigure,rotate,shutdown,interrupt,kill,debug,check,or parse。 
+ reconfigure 导致运行中的 重新读取配置文件。 
+ rotate导致 滚动它的日志,这包括了关闭日志,重命名,和再次打开它们。 
+ shutdown 发送关闭 进程的信号。 
+ interrupt 立刻关闭,不必等待活动会话完成。 
+ kill 发送KILL 信号给,这是关闭 的最后保证。 
+ debug 将 设置成完全的调试模式,假如你的cache 很忙,它能迅速的用完你的磁盘空间。 
+ check 简单的检查运行中的 进程,返回的值显示 是否在运行。 
+ 最后,parse 简单的解析.conf 文件,如果配置文件包含错误,进程返回非零值。 

-s 
激活将日志记录到syslog 进程。 使用LOCAL4 syslog 设备。0 级别调试信息以优先级LOG_WARNING 被记录,1 级别消息以LOG_NOTICE 被记录。更高级的调试信息不会被发送到syslogd.你可以在/etc/syslogd.conf 文件里使用如下接口: 
local4.warning /var/log/.log 

-u port 
指定另一个ICP 端口号,覆盖掉.conf 文件里的icp_port。 

-v 
打印版本信息。 

-z 
初始化cache,或者交换,目录。在首次运行,或者增加新的cache 目录时,你必须使用该选项。 

-C 
阻止安装某些信号句柄,它们捕获特定的致命信号例如SIGBUS 和SIGSEGV。正常的,这些信号被 捕获,以便它能干净的关闭。然而,捕获这些信号可能让以后调试问题困难。使用该选项,致命的信号导致它们的默认动作,通常是coredump。 

-D 
禁止初始化DNS 测试。正常情况下, 直到验证它的DNS 可用才能启动。该选项阻止了这样的检测。你也能在.conf 文件里改变或删除dns_testnames 选项。 

-F 
让 拒绝所有的请求,直到它重新建立起存储元数据。假如你的系统很忙,该选项可以减短重建存储元数据的时间。然而,如果你的cache 很大,重建过程可能会花费很长的时间。 

-N 
阻止 变成后台服务进程。 

-R 
阻止 在绑定HTTP 端口之前使用SO_REUSEADDR 选项。 

-V 
激活虚拟主机加速模式。类似于.conf 文件里的httpd_accel_host virtual 指令。 

-X 
强迫完整调试模式,如你在.conf 文件里指定debug_options ALL,9 一样。 

-Y 
在重建存储元数据时,返回ICP_MISS_NOFETCH 代替ICP_MISS.忙碌的父cache 在重建时,该选项可以导致最少的负载。请见10.6.1.2 章。 


5.2 对配置文件查错 

在开启 之前,你应该谨慎的验证配置文件。这点容易做到,运行如下命令即可: 
% -k parse 

假如你看不到输出,配置文件有效,你能继续后面的步骤。 

然而,如果配置文件包含错误, 会告诉你: 
.conf line 62: http_access allow okay2 
aclParseAccessLine: ACL name 'okay2' not found. 

这里你可以看到,62 行的http_access 指令指向的ACL 不存在。有时候错误信息很少: 
FATAL: Bungled .conf line 76: memory_pools 

在这个情形里,我们忘记了在76 行的memory_pools 指令后放置on 或off。 

建议你养成习惯:在每次修改配置文件后,使用 -k parse。假如你不愿麻烦,并且你的配置文件有错误, 会告诉你关于它们而且拒绝启动。假如你管理着大量的cache,也许你会编辑脚本来自动启动,停止和重配置。你能在脚本里使用该功能,来确认配置文件是有效的。 


5.3 初始化cache 目录 

在初次运行 之前,或者无论何时你增加了新的cache_dir,你必须初始化cache 目录。命令很简单: 
% –z 

对UFS 相关的存储机制(ufs,aufs,and diskd;见第8 章),该命令在每个cache_dir 下面创建了所需的子目录。你不必担心 会破坏你的当前cache 目录(如果有的话)。 

在该阶段属主和许可权是通常遇到的问题。 在特定的用户ID 下运行,这在.conf 文件里的cache_effective_user 里指定。用户ID 必须对每个cache_dir 目录有读和写权限。否则,你将看到如下信息: 
Creating Swap Directories 
FATAL: Failed to make swap directory /usr/local//var/cache/00: 
(13) Permission denied 

在这样的情形下,你该确认/usr/local//var/cache 目录的所有组成都可被.conf给定的用户ID 访问。最终的组件--cache 目录--必须对该用户ID 可写。 

cache 目录初始化可能花费一些时间,依赖于cache 目录的大小和数量,以及磁盘驱动器的速度。假如你想观察这个过程,请使用-X 选项: 
% –zX 


5.4 在终端窗口里测试 

一旦你已经初始化cache 目录,就可以在终端窗口里运行,将日志记录到标准错误。这样,你能轻易的定位任何错误或问题,并且确认 是否成功启动。使用-N 选项来保持 在前台运行,-d1 选项在标准错误里显示1 级别的调试信息。 
% -N -d1 

你将看到类似于以下的输出: 
2003/09/29 12:57:52| Starting Squid Cache 
version 2.5.STABLE4 for i386-unknown-freebsd4.8... 
2003/09/29 12:57:52| Process ID 294 
2003/09/29 12:57:52| With 1064 file descriptors available 
2003/09/29 12:57:52| DNS Socket created on FD 4 
2003/09/29 12:57:52| Adding nameserver 206.107.176.2 from /etc/resolv.conf 
2003/09/29 12:57:52| Adding nameserver 205.162.184.2 from /etc/resolv.conf 
2003/09/29 12:57:52| Unlinkd pipe opened on FD 9 
2003/09/29 12:57:52| Swap maxSize 102400 KB, estimated 7876 objects 
2003/09/29 12:57:52| Target number of buckets: 393 
2003/09/29 12:57:52| Using 8192 Store buckets 
2003/09/29 12:57:52| Max Mem size: 8192 KB 
2003/09/29 12:57:52| Max Swap size: 102400 KB 
2003/09/29 12:57:52| Rebuilding storage in /usr/local//var/cache (DIRTY) 
2003/09/29 12:57:52| Using Least Load store dir selection 
2003/09/29 12:57:52| Set Current Directory to /usr/local//var/cache 
2003/09/29 12:57:52| Loaded Icons. 
2003/09/29 12:57:52| Accepting HTTP connections at 0.0.0.0, port 3128, FD 11. 
2003/09/29 12:57:52| Accepting ICP messages at 0.0.0.0, port 3130, FD 12. 
2003/09/29 12:57:52| WCCP Disabled. 
2003/09/29 12:57:52| Ready to serve reques 

假如你看到错误消息,你该首先修正它。请检查输出信息的开始几行以发现警告信息。最普通的错误是文件/目录许可问题,和配置文件语法错误。假如你看到一条不引起注意的错误消息,请见16 章中关于 故障处理的建议和信息。如果还不行,请检查 FAQ,或查找邮件列表来获得解释。 

一旦你见到"Ready to serve requests"消息,就可用一些HTTP 请求来测试。配置你的浏览器使用 作为代理,然后打开某个web 页面。假如 工作正常,页面被迅速载入,就象没使用 一样。另外,你可以使用client 程序,它随 发布: 
% client -cache.org/" target="_blank">/ 

假如它正常工作, 的主页html 文件会在你的终端窗口里滚动。一旦确认 工作正常,你能中断 进程(例如使用ctrl-c)并且在后台运行。 


5.5 将 作为服务进程运行 

正常情况下你想将 以后台进程运行(不出现在终端窗口里)。最容易的方法是简单执行如下命令: 
% –s 

-s 选项导致 将重要的状态和警告信息写到syslogd。 使用LOCAL4 设备,和LOG_WARNING 和LOG_NOTICE 优先权。syslog 进程实际可能会或不会记录 的消息,这依赖于它被如何配置。同样的消息被写进cache.log 文件,所以假如你愿意,忽略-s 选项也是安全的。 

当你不使用-N 选项来启动, 自动在后台运行并且创建父/子进程对。子进程做所有的实际工作。父进程确认子进程总在运行。这样,假如子进程意外终止,父进程启动另外一个子进程以使 正常工作。通过观察syslog 消息,你能看到父/子进程交互作用。 
Jul 31 14:58:35 zapp [294]: Squid Parent: child process 296 started 

这里显示的父进程ID 是294,子进程是296。当你查看ps 的输出,你可以看到子进程以()形式出现: 
%ps ax | grep  
294 ?? Is 0:00.01  -sD 
296 ?? S 0:00.27 () -sD () 

假如 进程意外终止,父进程启动另一个。例如: 
Jul 31 15:02:53 zapp [294]: Squid Parent: child process 296 exited due to signal 6 
Jul 31 15:02:56 zapp [294]: Squid Parent: child process 359 started 

在某些情形下, 子进程可能立即终止。为了防止频繁的启动子进程,假如子进程连续5 次没有运行至少10 秒钟,父进程会放弃。 
Jul 31 15:13:48 zapp [455]: Squid Parent: child process 474 exited with status 1 
Jul 31 15:13:48 zapp [455]: Exiting due to repeated, frequent failures 

如果发生这样的事,请检查syslog 和 的cache.log 以发现错误。 


5.5.1 _start 脚本 

当 以后台进程运行时,它查找 执行程序目录下的名为_start 的文件。假如发现,该程序在父进程创建子进程之前被执行。你能使用该脚本完成特定的管理任务,例如通知某人 在运行,管理日志文件等。除非_start 程序存在, 不会创建子进程。 

_start 脚本在你使用绝对或相对路径启动 时才开始工作。换句话说, 不使用PATH 环境变量来定位_start.这样,你应该养成习惯这样启动: 
% /usr/local//sbin/ –sD 

而不要这样: 
% –sD 


5.6 启动脚本 

通常你希望 在每次计算机重启后自动启动。对不同的操作系统,它们的启动脚本如何工作也很不同。我在这里描述一些通用的环境,但对你自己的特殊操作系统,也许该有特殊的处理方法。 


5.6.1 /etc/rc.local 

最容易的机制之一是/etc/rc.local 脚本。这是个简单的shell 脚本,在每次系统启动时以root 运行。使用该脚本来启动 非常容易,增加一行如下: 
/usr/local//sbin/ –s 

当然你的安装位置可能不同,还有你可能要使用其他命令行选项。不要在这里使用-N选项。 

假如因为某些理由,你没有使用cache_effective_user 指令,你可以尝试使用su 来让以非root 用户运行: 
/usr/bin/su nobody -c '/usr/local//sbin/ -s' 


5.6.2 init.d 和rc.d 

init.d 和rc.d 机制使用独立的shell 脚本来启动不同的服务。这些脚本通常在下列目录之中:/sbin/init.d, /etc/init.d, /usr/local/etc/rc.d.脚本通常获取单一命令行参数,是start 或stop。某些系统仅仅使用start 参数。如下是启动 的基本脚本: 
#!/bin/sh 
# this script starts and stops Squid 
case "$1" in 
start) 
/usr/local//sbin/ -s 
echo -n ' Squid' 
;; 
stop) 
/usr/local//sbin/ -k shutdown 
;; 
esac 

Linux 用户可能在启动 之前需要设置文件描述符限制。例如: 
echo 8192 > /proc/sys/fs/file-max 
limit -HSn 8192 

为了使用该脚本,先找到脚本存放的目录。给它一个有意义的名字,类似于其他的系统启动脚本。可以是S98 或.sh。通过重启计算机来测试该脚本,而不要假想它会正常工作。 


5.6.3 /etc/inittab 

某些操作系统支持另一种机制,是/etc/inittab 文件。在这些系统中,init 进程启动和停止基于运行等级的服务。典型的inittab 接口类似如此: 
sq:2345:once:/usr/local//sbin/ –s 

使用该接口,init 进程启动 一次并且随后忘记它。 确认它驻留在运行状态,象前面描述的一样。或者,你能这样做: 
sq:2345:respawn:/usr/local//sbin/ –Ns 

这里我们使用了respawn 选项,假如进程不存在init 会重启。假如使用respawn,请确认使用-N 选项。 

在编辑完inittab 文件后,使用下面的命令来使init 重新读取它的配置文件和启动: 
# init q 


5.7 chroot 环境 

某些人喜欢在chroot 环境运行。这是unix 的功能,给予进程新的root 文件系统目录。在 受安全威胁时,它提供额外等级的安全保护。假如攻击者在某种程度上通过获取了对操作系统的访问权,她仅仅能访问在chroot 文件系统中的文件。在chroot 树之外的系统文件,她不可访问。 

最容易在chroot 环境里运行 的方法是,在.conf 文件里指定新的root 目录,如下: 
chroot /new/root/directory 

chroot()系统调用需要超级用户权限,所以你必须以root 来启动。 

chroot 环境不是为unix 新手准备的。它有点麻烦,因为你必须在新的root 目录里重复放置大量的文件。例如,假如默认的配置文件正常在/usr/local//etc/.conf,并且你使用chroot 指令,那么文件必须位于/new/root/directory/usr/local//etc/.conf.你必须将位于$prefix/etc,$prefix/share,$prefix/libexec 下的所有文件拷贝到chroot 目录。请确认$prefix/var 和cache 目录在chroot 目录中存在和可写。 

同样的,你的操作系统需要将大量的文件放在chroot 目录里,例如/etc/resolv.conf 和/dev/null.假如你使用外部辅助程序,例如重定向器(见11 章)或者验证器(见12 章),你也需要来自/usr/lib 的某些共享库。你可以使用ldd 工具来查找给定的程序需要哪些共享库: 
% ldd /usr/local//libexec/ncsa_auth 
/usr/local//libexec/ncsa_auth: 
libcrypt.so.2 => /usr/lib/libcrypt.so.2 (0x28067000) 
libm.so.2 => /usr/lib/libm.so.2 (0x28080000) 
libc.so.4 => /usr/lib/libc.so.4 (0x28098000) 

你可以使用chroot 命令来测试辅助程序: 
# chroot /new/root/directory /usr/local//libexec/ncsa_auth 
/usr/libexec/ld-elf.so.1: Shared object "libcrypt.so.2" not found 

更多的关于chroot 的信息,请见你系统中chroot()的manpage。 


5.8 停止 

最安全的停止 的方法是使用 -k shutdown 命令: 
% -k shutdown 

该命令发送TERM 信号到运行中的 进程。在接受到TERM 信号后, 关闭进来的套接字以拒收新请求。然后它等待一段时间,用以完成外出请求。默认时间是30 秒,你可以在shutdown_lifetime 指令里更改它。 
假如因为某些理由,.pid 文件丢失或不可读, -k 命令会失败。在此情形下,你可以用ps 找到 的进程ID,然后手工杀死。例如: 
%ps ax |grep  

假如你看到不止一个 进程,请杀死以()显示的那个。例如: 
% ps ax | grep  
294 ?? Is 0:00.01  -sD 
296 ?? S 0:00.27 () -sD () 
% kill -TERM 296 

在发送TERM 信号后,你也许想查看日志,以确认 已关闭: 
% tail -f logs/cache.log 
2003/09/29 21:49:30| Preparing for shutdown after 9316 requests 
2003/09/29 21:49:30| Waiting 10 seconds for active connections to finish 
2003/09/29 21:49:30| FD 11 Closing HTTP connection 
2003/09/29 21:49:31| Shutting down... 
2003/09/29 21:49:31| FD 12 Closing ICP connection 
2003/09/29 21:49:31| Closing unlinkd pipe on FD 9 
2003/09/29 21:49:31| storeDirWriteCleanLogs: Starting... 
2003/09/29 21:49:32| Finished. Wrote 253 entries. 
2003/09/29 21:49:32| Took 0.1 seconds (1957.6 entries/sec). 
2003/09/29 21:49:32| Squid Cache (Version 2.5.STABLE4): Exiting normally. 

假如你使用 -k interrupt 命令, 立即关闭,不用等待完成活动请求。这与在kill 里发送INT 信号相同。 


5.9 重配置运行中的 进程 

在你了解了更多关于 的知识后,你会发现对.conf 文件做了许多改动。为了让新设置生效,你可以关闭和重启,或者在 运行时,重配置它。 

重配置运行中的 最好的方法是使用 -k reconfigure 命令: 
% -k reconfigure 

当你运行该命令时,HUP 信号被发送到运行中的 进程。然后 读取和解析.conf 文件。假如操作成功,你可以在cache.log 里看到这些: 
2003/09/29 22:02:25| Restarting Squid Cache (version 2.5.STABLE4)... 
2003/09/29 22:02:25| FD 12 Closing HTTP connection 
2003/09/29 22:02:25| FD 13 Closing ICP connection 
2003/09/29 22:02:25| Cache dir '/usr/local//var/cache' size remains unchanged 
at 102400 KB 
2003/09/29 22:02:25| DNS Socket created on FD 5 
2003/09/29 22:02:25| Adding nameserver 10.0.0.1 from /etc/resolv.conf 
2003/09/29 22:02:25| Accepting HTTP connections at 0.0.0.0, port 3128, FD 9. 
2003/09/29 22:02:25| Accepting ICP messages at 0.0.0.0, port 3130, FD 11. 
2003/09/29 22:02:25| WCCP Disabled. 
2003/09/29 22:02:25| Loaded Icons. 
2003/09/29 22:02:25| Ready to serve requests. 

在使用reconfigure 选项时你须谨慎,因为所做的改变可能会导致致命错误。例如,请注意 关闭和重新打开进来的HTTP 和ICP 套接字;假如你将http_port 改变为 不能打开的端口,它会发生致命错误并退出。 

在 运行时,某些指令和和选项不能改变,包括: 
+ 删除cache 目录(cache_dir 指令) 
+ 改变store_log 指令 
+ 改变coss cache_dir 的块大小数值。事实上,无论何时你改变了该值,你必须重新初始化coss cache_dir。 
+ coredump_dir 指令在重配置过程中不被检查。所以,在 已经启动了后,你不能让 改变它的当前目录。 

solaris 用户在重配置 过程中可能遇到其他问题。solaris 的stdio 执行组件里的fopen()调用要求使用小于256 的未用文件描述符。FILE 结构以8 位值存储该文件描述符。正常情况下这不构成问题,因为 使用底层I/O(例如open())来打开cache 文件。然而,在重配置过程中的某些任务使用fopen(),这就有可能失败,因为前面的256 个文件描述符已被分配出去。 


5.10 滚动日志文件 

除非你在.conf 里禁止, 会写大量的日志文件。你必须周期性的滚动日志文件,以阻止它们变得太大。 将大量的重要信息写入日志,假如写不进去了, 会发生错误并退出。为了合理控制磁盘空间消耗,在cron 里使用如下命令: 
% -k rotate 

例如,如下任务接口在每天的早上4 点滚动日志: 
0 4 * * * /usr/local//sbin/ -k rotate 

该命令做两件事。首先,它关闭当前打开的日志文件。然后,通过在文件名后加数字扩展名,它重命名cache.log,store.log,和access.log。例如,cache.log 变成cache.log.0,cache.log.0变成cache.log.1,如此继续,滚动到logfile_rotate 选项指定的值。 

 仅仅保存每个日志文件的最后logfile_rotate 版本。更老的版本在重命名过程中被删除。假如你想保存更多的拷贝,你需要增加logfile_rotate 限制,或者编写脚本用于将日志文件移动到其他位置。 

请见13.7 章关于滚动日志的其他信息。 
 
6.访问控制 

6.1 访问控制元素 

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

例如: 
acl Workstations src 10.0.0.0/16 

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

6.1.1 一些基本的ACL 类型 

Squid 大约有25 个不同的ACL 类型,其中的一些有通用基本类型。例如,src 和dst ACL使用IP 地址作为它们的基本类型。为避免冗长,我首先描述基本类型,然后在接下来章节里描述每种ACL 类型。 

6.1.1.1 IP 地址 

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

当你指定掩码时, 会检查你的工作。如果你的掩码在IP 地址的非零位之外,会告警。例如,下列行导致告警: 
acl Foo src 127.0.0.1/8 
aclParseIpData: WARNING: Netmask masks away part of the specified IP in 'Foo' 

这里的问题是/8 掩码(255.0.0.0)在最后三个字节里都是零值,但是IP 地址127.0.0.1不是这样的。 警告你这个问题,以便你消除歧义。正确的写法是: 
acl Foo src 127.0.0.1/32 
or: 
acl Foo src 127.0.0.0/8 

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

注意使用IP 地址范围,掩码只能取一个。你不能为范围里的地址设置多个不同掩码。 

你也能在IP ACL 里指定主机名,例如: 
acl Squid dst 

 在启动时,将主机名转换成IP 地址。一旦启动, 不会对主机名的地址发起第二次DNS 查询。这样,假如在 运行中地址已改变, 不会注意到。 

假如主机名被解析成多个IP 地址, 将每一个增加到ACL 里。注意你也可以对主机名使用网络掩码。 

在基于地址的ACL 里使用主机名通常是坏做法。 在初始化其他组件之前,先解析配置文件,所以这些DNS 查询不使用 的非阻塞IP 缓存接口。代替的,它们使用阻塞机制的gethostbyname()函数。这样,将ACL 主机名转换到IP 地址的过程会延缓 的启动。除非绝对必要,请在src,dst,和myip ACL 里避免使用主机名。 

 以一种叫做splay tree 的数据结构在内存里存储IP 地址ACL ( 请见)。splay tree 有一些有趣的自我调整的特性,其中之一是在查询发生时,列表会自动纠正它自己的位置。当某个匹配元素在列表里发现时,该元素变成新的树根。在该方法中,最近参考的条目会移动到树的顶部,这减少了将来查询的时间。 

属于同一ACL 元素的所有的子网和范围不能重迭。如果有错误, 会警告你。例如,如下不被允许: 
acl Foo src 1.2.3.0/24 
acl Foo src 1.2.3.4/32 

它导致 在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' 

在该情形下,你需要修正这个问题,可以删除其中一个ACL 值,或者将它们放置在不同的ACL 列表中。 


6.1.1.2 域名 

使用对象:srcdomain,dstdomain,和cache_host_domain 指令域名简单的就是DNS 名字或区域。例如,下面是有效的域名: 

-cache.org 
org 

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

表6-1 显示了 的匹配域和主机名的规则。第一列显示了取自URL 请求的主机名(或者srcdomain ACL 的客户主机名)。第二列指明是否主机名匹配lrrr.org。第三列显示是否主机名匹配.lrrr.org ACL。你能看到,唯一的不同在第二个实例里。 
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 
___________________________________________________________________ 
**说明:为了表现表格形状,“__”仅代表空格分隔符,没有任何实际意义(段誉 注释)。 

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

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

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

 使用splay tree 的数据结构来存储域名ACL,就像它处理IP 地址一样。然而,的域名匹配机制给splay tree 提供了一个有趣的问题。splay tree 技术要求唯一键去匹配任意特定搜索条目。例如,让我们假设搜索条目是i.am.lrrr.org。该主机名同时匹配.lrrr.org和.am.lrrr.org。事实上就是两个ACL 值匹配同一个主机名扰乱了splay 机制。换句话说,在配置文件里放置如下语句是错误的: 
acl Foo dstdomain .lrrr.org .am.lrrr.org 

假如你这样做, 会产生如下警告信息: 
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' 

在该情况下你应遵循 的建议。删除其中一条相关的域名,以便 明确知道你的意图。注意你能在不同的ACL 里任意使用这样的域名: 
acl Foo dstdomain .lrrr.org 
acl Bar dstdomain .am.lrrr.org 

这是允许的,因为每个命名ACL 使用它自己的splay tree. 


6.1.1.3 用户名 

使用对象:ident,proxy_auth 

该类型的ACL 被设计成匹配用户名。 可能通过RFC 1413 ident 协议或者通过HTTP验证头来获取用户名。用户名必须被严格匹配。例如,bob 不匹配bobby。 也有相关的ACL 对用户名使用正则表达式匹配(ident_regex 和proxy_auth_regex)。 

你可以使用单词"REQUIRED"作为特殊值去匹配任意用户名。假如 不能查明用户名,ACL 不匹配。当使用基于用户名的访问控制时, 通常这样配置。 


6.1.1.4 正则表达式 

使用对象: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 一书)。对 来说,最常使用的正则表达式功能用以匹配字符串的开头或结尾。例如,^字符是特殊元字符,它匹配行或字符串的开头: 


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

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

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

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


6.1.1.5 TCP 端口号 

使用对象:port,myport 

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


6.1.1.6 自主系统号 
使用对象:src_as,dst_as 
Internet 路由器使用自主系统(AS)号来创建路由表。基本上,某个AS 号指向被同一组织管理的IP 网络范围。例如,我的ISP 分配了如下网络块:134.116.0.0/16, 137.41.0.0/16, 206.168.0.0/16,和其他更多。在Internet 路由表里,这些网络被公布为属于AS 3404。当路由器转发包时,它们典型的选择经过最少AS 的路径。假如这些对你不重要,请不必关注它们。AS 基础的ACL 仅仅被网络gurus 使用。 

如下是基于AS 的类型如何工作的:当 首先启动时,它发送一条特殊的查询到某个whois 服务器。查询语句基本是:“告诉我哪个IP 网络属于该AS 号”。这样的信息被RADB收集和管理。一旦Squid 接受到IP 网络列表,它相似的将它们作为IP 基础的ACL 对待。 

基于AS 的类型仅仅在ISP 将他们的RADB 信息保持与日更新时才工作良好。某些ISP更新RADB 比其他人做得更好;而许多根本不更新它。请注意 仅仅在启动或者reconfigure 时才将AS 号转换为网络地址。假如ISP 更新了它的RADB 接口,除非你重启或者重配置, 不会知道这个改变。 

另外的情况是,在你的 启动时,RADB可能不可到达。假如Squid 不能联系上RADB服务器,它从访问控制配置里删除AS 接口。默认的whois 服务器是whois.ra.net,对许多用户来说太遥远了而不可信赖。 


6.1.2 ACL 类型 

现在我们能把焦点放在ACL 类型自身上。我在这里按照重要性的降序来列举它们。 


6.1.2.1 src 

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

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


6.1.2.2 dst 

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

这里,是主机名。当访问列表规则包含了dst 元素时, 必须找到该主机名的IP 地址。假如 的IP 缓存包含了该主机名的有效接口,这条ACL 被立即检测。否则,在DNS 查询忙碌时, 会延缓处理该请求。这对某些请求来说会造成延时。 

为了避免延时,你该尽可能的使用dstdomain ACL 类型来代替dst。 

如下是简单的dst ACL 示例: 
acl AdServers dst 1.2.3.0/24 

请注意,dst ACL 存在的问题是,你试图允许或拒绝访问的原始服务器可能会改变它的IP 地址。假如你不关心这样的改变,那就不必麻烦去升级.conf。你可以在acl 行里放上主机名,但那样会延缓启动速度。假如你的ACL 需要许多主机名,你也许该预处理配置文件,将主机名转换成IP 地址。 


6.1.2.3 myip 

myip 类型指Squid 的IP 地址,它被客户连接。当你在 机上运行netstat -n 时,你见到它们位于本地地址列。大部分 安装不使用该类型。通常所有的客户连接到同一个IP 地址,所以该ACL元素仅仅当系统有多个IP 地址时才有用。 

为了理解myip为何有用,考虑某个有两个子网的公司网络。在子网1的用户是程序员和工程师。子网2包括会计,市场和其他管理部门。这样情况下的 有三个网络接口:一个连接子网1,一个连接子网2,第三个连接到外部因特网。 

当正确的配置时,所有在子网1 的用户连接到 位于该子网的IP 地址,类似的,子网2 的用户连接到 的第二个IP 地址。这样你就可以给予子网1 的技术部员工完全的访问权,然而限制管理部门的员工仅仅能访问工作相关的站点。 

ACL 可能如下: 
acl Eng myip 172.16.1.5 
acl Admin myip 172.16.2.5 

然而请注意,使用该机制你必须特别小心,阻止来自某个子网的用户连接 位于另一子网的IP 地址。否则,在会计和市场子网的聪明的用户,能够通过技术部子网进行连接,从而绕过你的限制。 


6.1.2.4 dstdomain 

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

然而首先我想申明如下两行的不同: 
acl A dst 
acl B dstdomain 

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

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

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

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


6.1.2.5 srcdomain 

srcdomain ACL 也有点麻烦。它要求对每个客户IP 地址进行所谓的反向DNS 查询。技术上, 请求对该地址的DNS PTR 记录。DNS 的响应--完整可验证域名(FQDN)--是匹配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 


6.1.2.6 port 

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

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

我的态度比较保守,仅仅允许安全的端口。默认的.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如下:,会返回访问拒绝错误消息。在某些情形下,为了让你的用户满意,你可能需要增加另外的端口号。 

宽松的做法是,拒绝对特别危险的端口的访问。Squid FAQ 包括了如下示例: 
acl Dangerous_ports 7 9 19 22 23 25 53 109 110 119 
http_access deny Dangerous_ports 

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

(译者注:这里的意思是,两者都要对列表进行搜索和匹配。在第一种情况下,它搜索安全端口列表并匹配80,显然第一个元素就匹配成功了。而第二种情况中,会搜索危险端口列表并试图匹配80,当然危险端口不会包括80,所以每次对80 的请求都要搜索完整个列表,这样就会影响性能。) 


6.1.2.7 myport 

 也有myport ACL。port ACL 指向原始服务器的端口号,myport 指向 自己的端口号,用以接受客户请求。假如你在http_port 指令里指定不止一个端口号,那么 就可以在不同的端口上侦听。 

假如你将 作为站点HTTP 加速器和用户代理服务器,那么myport ACL 特别有用。你可以在80 上接受加速请求,在3128 上接受代理请求。你可能想让所有人访问加速器,但仅仅你自己的用户能以代理形式访问。你的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 


6.1.2.8 method 

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

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

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

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

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

关于从 的缓存里删除对象,请见7.6 章。 


6.1.2.9 proto 

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

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

默认的.conf 文件有许多行限制缓存管理访问: 
acl Manager proto cache_object 
acl Localhost src 127.0.0.1 
http_access allow Manager Localhost 
http_access deny Manager 

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


6.1.2.10 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 ... 

尽管 允许,你也不应该在同一个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 


6.1.2.11 ident 

ident ACL 匹配被ident 协议返回的用户名。这是个简单的协议,文档是RFC 1413。它工作过程如下: 

1.用户代理(客户端)对 建立TCP 连接。 

2. 连接到客户系统的ident 端口(113)。 

3. 发送一个包括两个TCP 端口号的行。 端的端口号可能是3128(或者你在.conf 里配置的端口号),客户端的端口号是随机的。 

4.客户端的ident 服务器返回打开第一个连接的进程的用户名。 

5. 记录下用户名用于访问控制目的,并且记录到access.log。 

当 遇到对特殊请求的ident ACL 时,该请求被延时,直到ident 查询完成。这样,ident ACL 可以对你的用户请求造成延时。 

我们推荐仅仅在本地局域网中,并且大部分客户工作站运行ident 服务时,才使用ident ACL。假如 和客户工作站连在一个局域网里,ident ACL 工作良好。跨广域网使用ident难以成功。 

ident 协议并非很安全。恶意的用户能替换他们的正常ident 服务为假冒服务,并返回任意的他们选择的用户名。例如,假如我知道从administrator 用户的连接总是被允许,那么我可以写个简单的程序,在回答每个ident 请求时都返回这个用户名。 

你可以使用ident ACL 拦截cache(请见第9 章)。当 被配置成拦截cache 时,操作系统假设它自己是原始服务器。这意味着用于拦截TCP 连接的本地socket 地址有原始服务器的IP 地址。假如你在 上运行netstat -n 时,你可以看到大量的外部IP 地址出现在本地地址栏里。当 发起一个ident 查询时,它创建一个新的TCP 套接字,并绑定本地终点到同一个IP 地址上,作为客户TCP 连接的本地终点。既然本地地址并非真正是本地的(它可能与原始服务器IP 地址相距遥远),bind()系统调用失败。 将这个作为失败的ident查询来处理。 

注意也有个特性,对客户端执行懒惰ident 查询。在该情形下,在等待ident 查询时,请求不会延时。在HTTP 请求完成时, 记录ident 信息,假如它可用。你能使用ident_lookup_access 指令来激活该特性,我将在本章后面讨论。 


6.1.2.12 proxy_auth 

 有一套有力的,在某种程度上有点混乱的特性,用以支持HTTP 代理验证功能。使用代理验证,客户的包括头部的http 请求包含了验证信用选项。通常,这简单的是用户名和密码。 解密信用选项,并调用外部验证程序以发现该信用选项是否有效。 

 当前支持三种技术以接受用户验证:HTTP 基本协议,数字认证协议,和NTLM。基本认证已经发展了相当长时间。按今天的标准,它是非常不安全的技术。用户名和密码以明文同时发送。数字认证更安全,但也更复杂。基本和数字认证在RFC 2617 文档里被描述。NTLM 也比基本认证更安全。然而,它是Microsoft 发展的专有协议。少数 开发者已经基本完成了对它的反向工程。 

为了使用代理验证,你必须配置 使用大量的外部辅助程序。 源代码里包含了一些程序,用于对许多标准数据库包括LDAP,NTLM,NCSA 类型的密码文件,和标准Unix密码数据库进行认证。auth_param 指令控制对所有辅助程序的配置。我将在12 章里讨论这些细节。 

auth_param 指令和proxy_auth ACL 是少数在配置文件里顺序重要的实例。你必须在proxy_auth ACL 之前定义至少一个验证辅助程序(使用auth_param)。假如你没有这样做, 打印出错误消息,并且忽略proxy_auth ACL。这并非致命错误,所以 可以启动,但所有你的用户的请求可能被拒绝。 

proxy_auth ACL 取用户名作为值。然而,大部分安装里简单的使用特殊值REQUIRED:auth_param ... 
acl Auth1 proxy_auth REQUIRED 

在该情况中,任何具有有效信用选项的请求会匹配该ACL。假如你需要细化控制,你可以指定独立的用户名: 
auth_param ... 
acl Auth1 proxy_auth allan bob charlie 
acl Auth2 proxy_auth dave eric frank 

代理验证不支持HTTP 拦截,因为用户代理不知道它在与代理服务器,而非原始服务器通信。用户代理不知道在请求里发送Proxy-Authorization 头部。见9.2 章更多细节。 


6.1.2.13 src_as 

该类型检查客户源IP 地址所属的具体AS 号(见6.1.1.6 关于 如何将AS 号映射到IP 地址的信息)。作为示例, 我们虚构某ISP 使用AS 64222 并且通告使用10.0.0.0/8,172.16.0.0/12,192.168.0.0/16 网络。你可以编写这样的ACL,它允许来自该ISP 地址空间的任何主机请求: 
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 

当然,你还可以这样写: 
acl TheISP src_as 64222 
http_access allow TheISP 

第二种写法不但更短,而且假如ISP 增加了新的网络,你不必更新ACL 配置。 


6.1.2.14 dst_as 

dst_as ACL 经常与cache_peer_access 指令一起使用。在该方法中, 使用与IP 路由一致的方式转发cache 丢失。考虑某ISP,它比其他ISP 更频繁的更换路由。每个ISP 处理他们自己的cache 代理,这些代理能转发请求到其他代理。理论上,ISP A 将ISP B 网络里主机的cache 丢失转发到ISP B 的cache 代理。使用AS ACL 和cache_peer_access 指令容易做到这点: 
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 章里讨论更多关于cache 协作。 


6.1.2.15 snmp_community 

snmp_community ACL 对SNMP 查询才有意义,后者被snmp_access 指令控制。例如,你可以这样写: 
acl OurCommunityName snmp_community hIgHsEcUrItY 
acl All src 0/0 
snmp_access allow OurCommunityName 
snmp_access deny All 

在该情况中,假如community 名字设置为hIgHsEcUrItY,SNMP 查询才被允许。 


6.1.2.16 maxconn 

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

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

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


6.1.2.17 arp 

arp ACL 用于检测cache 客户端的MAC 地址(以太网卡的物理地址)。地址解析协议(ARP)是主机查找对应于IP 地址的MAC 地址的方法。某些大学学生发现,在Microsoft Windows 下,他们可以改变系统的IP 地址到任意值,然后欺骗 的基于地址的控制。这时arp 功能就派上用场了,聪明的系统管理员会配置 检查客户的以太网地址。 

不幸的是,该特性使用非移植性代码。假如你运行Solaris 或Linux,你能使用arp ACL。其他系统不行。当你运行./configure 时增加--enable-arp-acl 选项,就可以激活该功能。 

arp ACL 有另一个重要限制。ARP 是数据链路层协议,假如客户主机和 在同一子网,它才能工作。你不容易发现不同子网主机的MAC 地址。假如在 和你的用户之间有路由器存在,你可能不能使用arp ACL。 

现在你知道何时去使用它们,让我们看看arp ACL 实际上是怎样的。它的值是以太网地址,当使用ifconfig 和arp 时你能看到以太网地址。例如: 
acl WinBoxes arp 00:00:21:55:ed:22 
acl WinBoxes arp 00:00:21:ff:55:38 


6.1.2.18 srcdom_regex 

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

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


6.1.2.19 dstdom_regex 

dstdom_regex ACL 也与dstdomain 相似。下面的例子匹配以www 开头的主机名: 
acl WebSite dstdom_regex -i ^www\. 

如下是另一个有用的正则表达式,用以匹配在URL 主机名里出现的IP 地址: 
acl IPaddr dstdom_regex [0-9]$ 

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


6.1.2.20 url_regex 

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


6.1.2.21 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 来捕获它们。 


6.1.2.22 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 与它们的来源相关。甚至 可以重写它转发的请求的User-Agent 头部。某些浏览器例如Opera 和KDE 的Konqueror,用户可以对不同的原始服务器发送不同的user-agent字串,或者干脆忽略它们。 


6.1.2.23 req_mime_type 

req_mime_type ACL 指客户HTTP 请求里的Content-Type 头部。该类型头部通常仅仅出现在请求消息主体里。POST 和PUT 请求可能包含该头部,但GET 从不。你能使用该类型ACL 来检测某些文件上传,和某些类型的HTTP 隧道请求。 

req_mime_type ACL 值是正则表达式。你可以这样编写ACL 去捕获音频文件类型: 
acl AuidoFileUploads req_mime_type -i ^audio/ 


6.1.2.24 rep_mime_type 

该类型ACL 指原始服务器的HTTP 响应里的Content-Type 头部。它仅在使用http_reply_access 规则时才有用。所有的其他访问控制形式是基于客户端请求的。该ACL 基于服务器响应。 

假如你想使用 阻塞Java 代码,你可以这样写: 
acl JavaDownload rep_mime_type application/x-java 
http_reply_access deny JavaDownload 


6.1.2.25 ident_regex 

在本节早些时讲过ident ACL。ident_regex 允许你使用正则表达式,代替严格的字符串匹配,这些匹配是对ident 协议返回的用户名进行。例如,如下ACL 匹配包含数字的用户名: 
acl NumberInName ident_regex [0-9] 


6.1.2.26 proxy_auth_regex 

该ACL 允许对代理认证用户名使用正则表达式。例如, 如下ACL 匹配 
admin,administrator 和administrators: 
acl Admins proxy_auth_regex -i ^admin 


6.1.3 外部ACL 

Squid 2.5 版本介绍了一个新特性:外部ACL。你可以指示 发送某些信息片断到外部进程,然后外部的辅助程序告诉,数据匹配或不匹配。 

 附带着大量的外部ACL 辅助程序;大部分用于确定命名用户是不是某个特殊组的成员。请见12.5 章关于这些程序的描述,以及关于如何编写你自己的程序的信息。现在,我解释如何定义和使用外部ACL 类型。 

external_acl_type 指令定义新的外部ACL 类型。如下是通用语法: 
external_acl_type type-name [options] format helper-command 

type-name 是用户定义的字串。你也可以在acl 行里引用它。 

Squid 当前支持如下选项(options): 

ttl=n 
时间数量,单位是秒,用以缓存匹配值的时间长短。默认是3600 秒,或1 小时。 

negative_ttl=n 
时间数量,单位是秒,用以缓存不匹配值的时间长短。默认是3600 秒,或1 小时。 

concurrency=n 
衍生的辅助程序的数量,默认是5。 

cache=n 
缓存结果的最大数量。默认是0,即不限制cache 大小。 

格式是以%字符开始的一个或多个关键字。 当前支持如下格式: 

%LOGIN 
从代理验证信用选项里获取的用户名。 

%IDENT 
从RFC 1413 ident 获取的用户名。 

%SRC 
客户端IP 地址。 

%DST 
原始服务器IP 地址。 

%PROTO 
传输协议(例如HTTP,FTP 等) 

%PORT 
原始服务器的TCP 端口。 

%METHOD 
HTTP 请求方法。 

%{Header} 
HTTP 请求头部的值;例如,%{User-Agent}导致 发送这样的字串到验证器:"Mozilla/4.0 (compatible; MSIE 6.0; Win32)" 

%{Hdr:member} 
选择某些数量的基于列表的HTTP 头部,例如Caceh-Control;例如,给出如下HTTP头部: 
X-Some-Header: foo=xyzzy, bar=plugh, foo=zoinks 

对%{X-Some-Header:foo}的取值, 发送这样的字串到外部ACL 进程: 
foo=xyzzy, foo=zoinks 

%{Hdr:;member} 
与%{Hdr:member}相同,除了";"是列表分隔符外。你能使用任何非字母数字的字符作为分隔符。 

辅助命令是 为辅助程序衍生的命令。你也可以在这里包含命令参数。例如,整条命令可能类似如此: 
/usr/local//libexec/my-acl-prog.pl -X -5 /usr/local//etc/datafile 

将这些放在一个长行里。 不支持如下通过反斜杠分隔长行的技术,所以请记住所有这些必须放在单行里: 
external_acl_type MyAclType cache=100 %LOGIN %{User-Agent} \ 
/usr/local//libexec/my-acl-prog.pl -X -5 \ 
/usr/local//share/usernames \ 
/usr/local//share/useragents 

现在你知道如何定义外部ACL,下一步是编写引用它的acl 行。这相对容易,语法如下: 
acl acl-name external type-name [args ...] 

如下是个简单示例: 
acl MyAcl external MyAclType 

 接受在type-name 后面的任意数量的参数。这些在每个请求里被发送到辅助程序。 
请见12.5.3 章,我描述了unix_group 辅助程序,作为该功能的示例。 


6.1.4 处理长ACL 列表 

ACL 列表某些时候非常长。这样的列表在.conf 文件里难以维护。你也可能想从其他资源里自动产生 ACL 列表。在如此情况下,你可以从外部文件里包含ACL 列表。语法如下: 
acl name "filename" 

这里的双引号指示 打开filename,并且将它里面的内容分配给ACL。例如,如下的ACL 太长了: 
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//etc/BadClients" 

将IP 地址放在BadClients 文件里: 
1.2.3.4 
1.2.3.5 
1.2.3.6 
1.2.3.7 
1.2.3.9 
... 

文件可以包含以#开头的注释。注意在该文件里的每个IP 地址必须是一个单独的行。acl行里的任何地方,以空格来分隔值,新行是包含ACL 值的文件的分界。 


6.1.5 Squid 如何匹配访问控制元素 

理解 如何搜索ACL 元素去匹配是很重要的。当ACL元素有多个值时,任何单个值能导致匹配。换句话说,在检查ACL 元素值时使用OR逻辑。当 找到第一个值匹配时,它停止搜索。这意味着把最可能匹配的值放在列表开头处,能减少延时。 

让我们看一个特殊的例子,考虑如下ACL 定义: 
acl Simpsons ident Maggie Lisa Bart Marge Homer 

当 在访问列表里遇到Simpsons ACL时,它执行ident查询。让我们看一下,当用户ident 服务返回Marge 时,会发生什么呢? 的ACL 代码在成功匹配Marge 前,会先后将这个值与Maggie,Lisa,和Bart 对比。当搜索完成时,我们认为Simpsons ACL 匹配了这个请求。 

实际上,这有点欺骗。ident ACL 值并非存储在无序列表里。它们存储在splay tree 中。这意味着,在非匹配事件中, 不会搜索完所有的名字。对一个splay tree 搜索N 个条目需要记录N 个比较。许多其他的ACL 类型也使用splay tree。然而,基于正则表达式的类型不使用。 

既然正则表达式不能这样存储,它们以链表形式存储。这使得在大链表里它们特别低效,特别是不匹配链表里任何正则表达式的请求。为了改进这个形式,当匹配发生时, 将正则表达式移到列表的顶部。实际上,因为ACL 匹配代码的天然特性, 将匹配的条目移到列表的第二个位置。这样,普通的匹配值自然移到ACL 列表的顶部,这样会减少比较数量。 

让我们看另一个简单示例: 
acl Schmever port 80-90 101 103 107 1 2 3 9999 

该ACL 匹配到原始服务器80-90 端口,和其他独立端口的请求。对80 端口的请求,通过查看第一个值就匹配了该ACL。对9999 端口,其他每个值都先被检查。对某个不在列表里的端口, 要检查所有值才宣布它不匹配。就像我已经讲过的,将最常用的值放在第一位能优化ACL 匹配。 


6.2 访问控制规则 

前面提过,ACL 元素是建立访问控制的第一步。第二步是访问控制规则,用来允许或拒绝某些动作。在早先的例子里,你已见过http_access 规则。 有大量其他的访问控制列表: 

http_access 
这是最重要的访问控制列表。它决定哪些客户HTTP 请求被允许,和哪些被拒绝。假如http_access 配置错误, cache 容易遭受攻击或被不当利用。 

http_reply_access 
http_reply_access 与http_access 类似。不同之处是前者在 接受到来自原始服务器或上级代理的响应时,才会被检测。大部分访问控制基于客户请求的方式,对这些使用http_access 就够了。然而,某些人喜欢基于响应内容类型来允许或拒绝请求。更多信息请见6.3.9 章。 

icp_access 
假如你的 被配置来服务ICP 响应(见10.6 章),那么该使用icp_access 列表。大部分情况下,你该仅仅允许来自邻居cache 的ICP 请求。 

no_cache 
你能使用no_cache 访问列表来指示,它不必存储某些响应(在磁盘或内存里)。该列表典型的与dst,dstdomain,url_regex ACL 结合使用。 
对no_cache 使用"否"条件,这样的双重否定会导致某些混乱。被no_cache 列表拒绝的请求不被缓存。换句话说,no_cache deny...是让目标不被缓存。见6.3.10 章的示例。 

miss_access 
miss_access 列表主要用于 的邻居cache。它决定 怎样处理cache 丢失的请求。如果 使用集群技术,那么该功能必需。见6.3.7 的示例。 

redirector_access 
该访问列表决定哪个请求被发送到重定向进程(见11 章)。默认情况下,假如你使用重定向器,那么所有的请求都通过重定向器。你可以使用redirector_access 列表来阻止某些请求被重写。这点特别有用,因为这样的访问列表,使重定向器相对于访问控制系统,接受的请求信息要少一些。 

ident_lookup_access 
ident_lookup_access 列表与redirector_access 类似。它允许你对某些请求执行懒惰ident查询。 默认不发布ident 查询。假如请求被ident_lookup_access 规则(或ident ACL)允许,那么 才会进行ident 查询。 

always_direct 
该访问列表影响 怎样处理与邻居cache 转发cache 丢失。通常 试图转发cache 
丢失到父cache,和/或 使用ICP 来查找临近cache 响应。然而,当请求匹配always_direct规则时, 直接转发请求到原始服务器。 
使用该规则,对"allow"规则的匹配导致 直接转发请求,见10.4.4 章的更多细节和示例。 

never_direct 
never_direct 与always_direct 相反。匹配该列表的cache 丢失请求必须发送到邻居cache。这点对在防火墙之后的代理特别有用。 
使用该列表,对"allow"规则的匹配导致 转发请求到邻居cache。见10.4.3 章的更多细节和示例。 

snmp_access 
该访问列表应用到发送给 的SNMP 端口的查询。你能配合该列表使用的ACL 是snmp_community 和src。假如你确实想使用它,那也能使用srcdomain,srcdom_regex和src_as。见14.3 章的示例。 

broken_posts 
该访问列表影响 处理某些POST 请求的方法。某些老的用户代理在请求主体的结尾处发送一个特别的回车换行符。那就是说,消息主体比content-length 头部指示的长度要多2 个字节。更糟糕的是,某些老的HTTP 服务器实际上依赖于这种不正确的行为。当请求匹配该访问列表时, 模拟这种客户端并且发送特殊的回车换行符。 
Squid 有大量的使用ACL 元素的其他配置指令。它们中的某些过去是全局配置,后被修改来使用ACL 以提供更灵活的控制。 

cache_peer_access 
该访问列表控制发送到邻居cache 的HTTP 请求和ICP/HTCP 查询。见10.4.1 章的更多信息和示例。 

reply_body_max_size 
该访问列表限制对HTTP 响应主体的最大可接受size。见附录A 的更多信息。 

delay_access 
该访问规则列表控制是否延时池被应用到某个请求的cache 丢失响应。见附录C。 

tcp_outgoing_address 
该访问列表绑定服务端TCP 连接到指定的本地IP 地址。见附录A。 

tcp_outgoing_tos 
该访问列表能设置到原始服务器和邻居cache 的TCP 连接的不同TOS/Diffserv 值,见附录A。 

header_access 
使用该指令,你能配置 从它转发的请求里删除某些HTTP 头部。例如,你也许想Squid过滤掉发送到某些原始服务器的请求里的Cookie 头部。见附录A。 

header_replace 
该指令允许你替换,而不是删除,HTTP 头部的内容。例如,你能设置user-agent 头部为假值,满足某些原始服务器的要求,但仍保护你的隐私。见附录A。 


6.2.1 访问规则语法 

访问控制规则的语法如下: 
access_list allow|deny [!]ACLname ... 

例如: 
http_access allow MyClients 
http_access deny !Safe_Ports 
http_access allow GameSites AfterHours 

当读取配置文件时, 仅仅扫描一遍访问控制行。这样,在访问列表里引用ACL 元素之前,你必须在acl 行里定义它们。甚至,访问列表规则的顺序也非常重要。你以怎样的顺序编写访问列表,那么 就按怎样的顺序来检查它们。将最常用的ACL 放在列表的开始位置,可以减少 的CPU 负载。 

对大部分访问列表,deny 和allow 的意义明显。然而,它们中的某些,却并非如此含义清楚。请谨慎的编写always_direct,never_direct,和no_cache 规则。在always_direct 中,allow规则意味着匹配的请求直接转发到原始服务器。always_direct deny 规则意味着匹配的请求不强迫发送到原始服务器,但假如邻居cache 不可到达,那可能还是会这么做。no_cache 规则也有点麻烦。这里,你必须对不必被cache 的请求使用deny。 


6.2.2 Squid 如何匹配访问规则 

回想一下 在搜索ACL 元素时使用的“或”逻辑。在acl 里的任何单值都可以导致匹配。 

然而,访问规则恰好相反。对http_access 和其他规则设置, 使用“与”逻辑。考虑如下示例: 
access_list allow ACL1 ACL2 ACL3 

对该匹配规则来说,请求必须匹配ACL1,ACL2,ACL3 中的任何一个。假如这些ACL中的任何一个不匹配请求, 停止搜索该规则,并继续处理下一条。对某个规则来说,将最少匹配的ACL 放在首位,能使效率最佳。考虑如下示例: 
acl A method http 
acl B port 8080 
http_access deny A B 

该http_access 规则有点低效,因为A ACL 看起来比B ACL 更容易匹配。反转顺序应该更好,以便 仅仅检查一个ACL,而不是两个: 
http_access deny B A 

人们易犯的典型错误是编写永不正确的规则。例如: 
acl A src 1.2.3.4 
acl B src 5.6.7.8 
http_access allow A B 

该规则永不正确,因为某个源IP 地址不可能同时等同于1.2.3.4 和5.6.7.8。这条规则的真正意图是: 
acl A src 1.2.3.4 5.6.7.8 
http_access allow A 

对某个ACL 值的匹配算法是, 在访问列表里找到匹配规则时,搜索终止。假如没有访问规则导致匹配,默认动作是列表里最后一条规则的取反。例如,考虑如下简单访问配置: 
acl Bob ident bob 
http_access allow Bob 

假如用户Mary 发起请求,她会被拒绝。列表里最后的(唯一的)规则是allow 规则,它不匹配用户名mary。这样,默认的动作是allow 的取反,故请求被拒绝。类似的,假如最后的规则是deny 规则,默认动作是允许请求。在访问列表的最后加上一条,明确允许或拒绝所有请求,是好的实际做法。为清楚起见,以前的示例应该如此写: 
acl All src 0/0 
acl Bob ident bob 
http_access allow Bob 
http_access deny All 

src 0/0 ACL 表示匹配每一个和任意类型的请求。 


6.2.3 访问列表风格 

 的访问控制语法非常强大。大多数情况下,你可以使用两种或多种方法来完成同样的事。通常,你该将更具体的和受限制的访问列表放在首位。例如,如下语句并非很好: 
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 

假如你这样写,访问控制列表会更容易维护和理解: 
http_access allow Net4 
http_access deny !WorkingHours 
http_access allow Net1 
http_access allow Net2 
http_access allow Net3 
http_access deny All 

无论何时,你编写了一个带两个或更多ACL 元素的规则,建议你在其后紧跟一条相反的,更广泛的规则。例如,默认的 配置拒绝非来自本机IP 地址的cache 管理请求,你也许试图这样写: 
acl CacheManager proto cache_object 
acl Localhost src 127.0.0.1 
http_access deny CacheManager !Localhost 

然而,这里的问题是,你没有允许确实来自本机的cache 管理请求。随后的规则可能导致请求被拒绝。如下规则就产生了问题: 
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 

既然来自本机的请求不匹配MyNet,它被拒绝。编写本规则的更好方法是: 
http_access allow CacheManager localhost 
http_access deny CacheManager 
http_access allow MyNet 
http_access deny All 


6.2.4 延时检查 

某些ACL 不能在一个过程里被检查,因为必要的信息不可用。ident,dst,srcdomain 和proxy_auth 类型属于该范畴。当 遇到某个ACL 不能被检查时,它延迟决定并且发布对必要信息的查询(IP 地址,域名,用户名等)。当信息可用时, 再次在列表的开头位置检查这些规则。它不会从前次检查剩下的位置继续。假如可能,你应该将这些最可能被延时的ACL 放在规则的顶部,以避免不必要的,重复的检查。 

因为延时的代价太大, 会尽可能缓存查询获取的信息。ident 查询在每个连接里发生,而不是在每个请求里。这意味着,当你使用ident 查询时,持续HTTP 连接切实对你有利。DNS 响应的主机名和IP 地址也被缓存,除非你使用早期的外部dnsserver 进程。代理验 
证信息被缓存,请见6.1.2.12 章节的描述。 


6.2.5 减缓和加速规则检查 

Squid 内部考虑某些访问规则被快速检查,其他的被减缓检查。区别是 是否延迟它的决定,以等待附加信息。换句话说,在 查询附加信息时,某个减缓检查会被延时,例如: 
+ 反向DNS 查询:客户IP 地址的主机名 
+ RFC 1413 ident 查询:客户TCP 连接的用户名 
+ 验证器:验证用户信用 
+ DNS 转发查询:原始服务器的IP 地址 
+ 用户定义的外部ACL 

某些访问规则使用快速检查。例如,icp_access 规则被快速检查。为了快速响应ICP 查询,它必须被快速检查。甚至,某些ACL 类型例如proxy_auth,对ICP 查询来说无意义。下列访问规则被快速检查: 
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 类型可能需要来自外部数据源(DNS,验证器等)的信息,这样与快速的访问规则不兼容: 
srcdomain, dstdomain, srcdom_regex, dstdom_regex 
dst, dst_as 
proxy_auth 
ident 
external_acl_type 

这意味着,例如,不能在header_access 规则里使用ident ACL。 


6.3 常见用法 

因为访问控制可能很复杂,本节包含一些示例。它们描述了一些访问控制的普通用法。你可以在实际中调整它们。 

6.3.1 仅仅允许本地客户 

几乎每个 安装后,都限制基于客户IP 地址的访问。这是保护你的系统不被滥用的最好的方法之一。做到这点最容易的方法是,编写包含IP 地址空间的ACL,然后允许该ACL 的HTTP 请求,并拒绝其他的。 
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 

也许该访问控制配置过于简单,所以你要增加更多行。记住http_access 的顺序至关重要。不要在deny all 后面增加任何语句。假如必要,应该在allow MyNetwork 之前或之后增加新规则。 


6.3.2 阻止恶意客户 

因为某种理由,你也许有必要拒绝特定客户IP 地址的访问。这种情况可能发生,例如,假如某个雇员或学生发起一个异常耗费网络带宽或其他资源的web 连接,在根本解决这个问题前,你可以配置 来阻止这个请求: 
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 


6.3.3 内容过滤 

阻塞对特定内容的访问是棘手的问题。通常,使用 进行内容过滤最难的部分,是被阻塞的站点列表。你也许想自己维护一个这样的列表,或从其他地方获取一个。 FAQ的“访问控制”章节有链接指向免费的可用列表。 

使用这样的列表的ACL 语法依赖于它的内容。假如列表包含正则表达式,你可能要这样写: 
acl PornSites url_regex "/usr/local//etc/pornlist" 
http_access deny PornSites 

另一方面,假如列表包含原始服务器主机名,那么简单的更改url_regex 为dstdomain。 


6.3.4 在工作时间的受限使用 

某些公司喜欢在工作时间限制web 使用,为了节省带宽,或者是公司政策禁止员工在工作时做某些事情。关于这个最难的部分是,所谓合适的和不合适的internet 使用之间的区别是什么。不幸的是,我不能对这个问题作出回答。在该例子里,假设你已收集了一份web站点域名列表,它包含已知的不适合于你的站点名,那么这样配置: 
acl NotWorkRelated dstdomain "/usr/local//etc/not-work-related-sites" 
acl WorkingHours time D 08:00-17:30 
http_access deny !WorkingHours NotWorkRelated 

请注意在该规则里首先放置!WorkingHours ACL。相对于字符串或列表,dstdomain ACL产生的性能代价较大,但time ACL 检查却很简单。 

下面的例子,进一步理解如何结合如下方法和前面描述的源地址控制,来控制访问。 
acl All src 0/0 
acl MyNetwork src 172.16.5.0/24 172.16.6.0/24 
acl NotWorkRelated dstdomain "/usr/local//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 

上面的方法可行,因为它实现了我们的目标,在工作时间内拒绝某些请求,并允许来自你自己网络的请求。然而,它也许有点低效。注意NotWorkRelated ACL 在所有请求里被搜索,而不管源IP 地址。假如那个列表非常长,在列表里对外部网络请求的搜索,纯粹是浪费CPU 资源。所以,你该这样改变规则: 
http_access deny !MyNetwork 
http_access deny !WorkingHours NotWorkRelated 
http_access Allow All 

这里,将代价较大的检查放在最后。试图滥用 的外部用户不会再浪费你的CPU资源。 


6.3.5 阻止 与非HTTP 服务器会话 

你必须尽可能不让 与某些类型的TCP/IP 服务器通信。例如,永不能够使用缓存来转发SMTP 传输。我在前面介绍port ACL 时提到过这点。然而,它是至关重要的,所以再强调一下。 

首先,你必须关注CONNECT 请求方法。使用该方法的用户代理,通过HTTP 代理来封装TCP 连接。它被创造用于HTTP/TLS 请求,这是CONNECT 方法的主要用途。某些用户代理也可以通过防火墙代理来封装NNTP/TLS 传输。所有其他的用法应该被拒绝。所以, 
你的访问列表,应该仅仅允许到HTTP/TLS 和NNTP/TLS 端口的CONNECT 请求。 

第二,你应该阻止 连接到某些服务,例如SMTP。你也可以开放安全端口和拒绝危险端口。我对这两种技术给出示例。 

让我们看看默认的.conf 文件提供的规则: 
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 
 

Safe_ports ACL 列举了所有的 有合法响应的特权端口(小于1024)。它也列举了所有非特权端口范围。注意Safe_ports ACL 也包括了安全HTTP 和NNTP 端口(443 和563),即使它们也出现在SSL_ports ACL 里。这是因为Safe_ports 在规则里首先被检查。假如你交换了两个http_access 行的顺序,你也许能从Safe_ports 列表里删除443 和563,但没必要这么麻烦。 

与此相似的其他方法是,列举已知不安全的特权端口: 
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 
 

假如你不熟悉这些奇特的端口号,也不要担心。你可以阅读unix 系统的/etc/services 文件,或者阅读IANA 的注册TCP/UDP 端口号列表: 
 


6.3.6 授予某些用户特殊的访问 

使用基于用户名进行访问控制的组织,通常需要授予某些用户特殊的权限。在该简单示例里,有三个元素:所有授权用户,管理员用户名,限制访问的web 站点列表。正常的用户不允许访问受限站点,但管理员有维护这个列表的任务。他们必须连接到所有服务器,去验证某个特殊站点是否该放到受限站点列表里。如下显示如何完成这个任务: 
auth_param basic program /usr/local//libexec/ncsa_auth 
/usr/local//etc/passwd 
acl Authenticated proxy_auth REQUIRED 
acl Admins proxy_auth Pat Jean Chris 
acl Porn dstdomain "/usr/local//etc/porn.domains" 
acl All src 0/0 
http_access allow Admins 
http_access deny Porn 
http_access allow Authenticated 
http_access deny All 

首先,有三个ACL 定义。Authenticated ACL 匹配任何有效的代理验证信用。Admins ACL匹配来自用户Pat,Jean,和Chris 的有效信用。Porn ACL 匹配某些原始服务器主机名,它们在porn.domains 文件里找到。 

该示例有四个访问控制规则。第一个仅仅检查Admins ACL,允许所有来自Pat,Jean,和Chris 的请求。对其他用户, 转移到下一条规则。对第二条规则,假如原始主机名位于porn.domains 文件,那么该请求被拒绝。对不匹配Porn ACL 的请求, 转移到第三条规则。第三条规则里,假如请求包含有效的验证信用,那么该请求被允许。外部验证器(这里的ncsa_auth)决定是否信用有效。假如它们无效,最后的规则出现,该请求被拒绝。 

注意ncsa_auth 验证器并非必需。你可以使用12 章里描述的任何验证辅助程序。 


6.3.7 阻止邻近cache 的滥用 

假如你使用了cache 集群,你必须付出多余的小心。cache 通常使用ICP 来发现哪些对象被缓存在它们的邻居机器上。你仅该接受来自已知授权的邻居cache 的ICP 查询。 

更进一步,通过使用miss_access 规则列表,你能配置 强制限制邻近关系。仅仅在cache 丢失,没有cache 命中时才检查这些规则。这样,在miss_access 列表生效前,所有请求必须首先通过http_access 规则。 

在本示例里,有三个独立的ACL。一个是直接连接到cache 的本地用户;另一个是子cache,它被允许来转发cache 丢失的请求;第三个是邻近cache,它必须从不转发导致cache丢失的请求。如下是它们如何工作: 
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.3.8 使用IP 地址拒绝请求 

我在6.1.2.4 章节里提过,dstdomain 类型是阻塞对指定原始主机访问的好选择。然而,聪明的用户通过替换URL 主机名成IP 地址,能够绕过这样的规则。假如你想彻底阻止这样的请求,你可能得阻塞所有包含IP 地址的请求。你可以使用重定向器,或者使用dstdom_regex ACL 来完成。例如: 
acl IPForHostname dstdom_regex ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ 
http_access deny IPForHostname 


6.3.9 http_reply_access 示例 

回想一下,当 检查http_reply_access 规则时,响应的内容类型是唯一的可用新信息。这样,你能保持http_reply_access 规则简单化。你只需检查rep_mime_type ACL。例如,如下示例告诉你如何拒绝某些内容类型的响应: 
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 列表里重复http_access 规则。这里的allow ALL 规则不意味着所有对 的请求被允许。任何被http_access 拒绝的请求,从来不会再被http_reply_access 检查。 


6.3.10 阻止对本地站点的cache 命中 

假如你有许多原始服务器在本地网络中,你也许想配置,以便它们的响应永不被缓存。因为服务器就在附近,它们不会从cache 命中里获益很多。另外,它释放存储空间给其他远程原始主机。 

第一步是定义本地服务器的ACL。你可能使用基于地址的ACL,例如: 
acl LocalServers dst 172.17.1.0/24 

假如服务器不位于单一的子网,你也许该创建dstdomain ACL: 
acl LocalServers dstdomain .example.com 

接下来,你简单的使用no_cache access 规则,拒绝这些服务器的cache: 
no_cache deny LocalServers 

no_cache 规则不会阻止客户发送请求到。没有办法配置 阻止这样的请求进来。代替的,你必须配置用户代理自身。 

假如你在 运行一段时间后增加no_cache 规则,cache 可能包含一些匹配新规则的对象。在2.5 之前的版本,这些以前缓存的对象可能以cache 命中返回。然而现在,清除掉所有匹配no_cache 规则的缓存响应。 


6.4 测试访问控制 
访问控制配置越长,它就越复杂。强烈建议你在将它们用于产品环境之前,先测试访问控制。当然,首先做的事是确认 能正确的解析配置文件。使用-k parse 功能: 
%  -k parse 

为了进一步测试访问控制,你需要安装一个用于测试的。容易做到的方法是,编译另一份 到其他$prefix 位置。例如: 
% tar xzvf -2.5.STABLE4.tar.gz 
% cd -2.5.STABLE4 
% ./configure --prefix=/tmp/ ... 
% make && make install 

在安装完后,你必须编辑新的.conf 文件,更改一些指令。假如 已经运行在 
默认端口,那么请改变http_port。为了执行简单的测试,创建单一的小目录: 
cache_dir ufs /tmp//cache 100 4 4 

假如你不想重编译,你也能创建一份新的配置文件。该方法的弊端是你必须设置所有的日志文件路径为临时目录,以便不会覆盖真正的文件。 

你可以使用client 程序来轻松的测试某些访问控制。例如,假如你有一条规则,它依赖于原始服务器主机名(dstdomain ACL),或者某些URL 部分(url_regex 或urlpath_regex),简单的输入你期望被允许或拒绝的URI: 
% client -p 4128  
or: 
% client -p 4128  

某些类型的请求难以控制。假如你有src ACL,它们阻止来自外部网络的请求,你也许需要从外部主机测试它们。测试time ACL 也很困难,除非你能改变系统时钟,或者等待足够长时间。你能使用client 的-H 选项来设置任意请求头。例如,假如你需要测试browser ACL,那么这样做: 
% client -p 4128  \ 
-H 'User-Agent: Mozilla/5.0 (compatible; Konqueror/3)\r\n' 

更多的复杂请求,包括多个头部,请参考16.4 章中描述的技术。 

你也许考虑制订一项cron,定期检查ACL,以发现期望的行为,并报告任何异常。如下是可以起步的示例shell 脚本: 
#!/bin/sh 
set -e 
TESTHOST="" 
# make sure Squid is not proxying dangerous ports 

ST=`client '$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=`client '$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=`client -l $EXT_ADDR '$TESTHOST/' | head -1 | awk '{print $2}'` 
if test "$ST" != 403 ; then 
echo "Squid allowed request from external address $EXT_ADDR" 
fi 
exit 0 
阅读(2563) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~