第十五章 Proxy Server

15.1 概论

Proxy 可以用来降低 WWW 及 FTP 的网络流量,它的运作原理简而言之就是当网域中其它计算机要浏览网页时,必须先通过 proxy 服务器,如果在 proxy 中已存有该网页时,就直接送出给网域中的计算机;如果没有,则连到该网页取回来存放,并送一份给提出要求的计算机,待下次再有相同要求时,就可以直接从 proxy 的存档中送出。

我们会在 proxy 服务器中设定数据要存放多久的时间并更新,以免使用者看到的都是存在 proxy 中的旧网页。这对于内部有大量的使用者时,可以明显降低网络流量。如果网域中只有十几台计算机,那么 proxy 就比较不能发挥它的功效了。我们也可以在 proxy 中设定使用者不可以浏览的网页,限制使用者连到某些网站。

一般而言,使用者要使用 proxy 时,必须先在自己计算机上做一些设定。我们也可以利用 proxy 结合防火墙,当使用者对外提出 HTTP 要求时,即自动转向到 proxy server,如此一来,使用者端便不需做任何设定,甚至不会发觉有 proxy 的存在。

在这里我们介绍一个被广为使用的 proxy 软件 「squid」。squid 的安装及设定很简单,我们会在下面几节中一一为大家介绍。

15.2 安装 Squid

感谢美好的 FreeBSD ports,可以让我们很简单的安装 squid。请使用下列指令:

# cd /usr/ports/www/squid24
# make install

如此便已安装 squid 了。接下来就必须要修改 /usr/local/etc/squid/squid.conf 了,squid.conf 是整个 squid 的设定所在,内容很多,我们下一章再做详细的介绍。这里我们只作简单的设定,也就是先定义谁可以使用 proxy,例如我要定义只有 192.168.0.* 及 *.alexwang.com 可以使用,则在 squid.conf 中找到 ACCESS CONTROLS 的区段中的 acl 部份,加入下面内容:

acl domain_allowed srcdomain .alexwang.com
acl ip_allowed src 192.168.0.0/24

在上面二行中,我们先将网址及 IP 定义一个名字,将所有在 *.alexwang.com 的网址定义名称为 domain_allowed;将 192.168.0.0-192.168.0.255 的 IP 命名为 ip_allowed。接着再找到 http_access 的部份,在 http_access deny all 之前加入下面有内容:

http_access allow domain_allowed
http_access allow ip_allowed

上面是允许名称为 domain_allowed 及 ip_allowed 的网址使用 proxy。关于上述设定的说明请参考 squid.conf 介绍。

修改完 squid.conf 之后,接着要建立 cache 目录结构,预设的 cache 目录在 /usr/local/squid/cache 中,如果要将它放在其它目录的话,必须修改 squid.conf 并建立所设定的目录。接着使用下列指定来改变档案权限并建立 cache 的目录结构:

# chown -R nobody:nogroup /usr/local/squid/cache
# chown -R nobody:nogroup /usr/local/squid/logs
# /usr/local/sbin/squid -z

当下达 squid -z 的指令时,必须等上几分钟的时间。安装好 squid 之后,在 /usr/local/etc/rc.d/ 有一个名为 squid.sh 的档案,表示在开机时便用自动启动 squid。当做好一切设定之后,我们只要执行下列指令即可启动 squid。

# /usr/local/etc/rc.d/squid.sh start

我们在这里的设定只是让你能立即使用 proxy,详细的设定必须再修改 squid.conf,一些相关的设定如某个时段禁止连到某个地址、数据保存期限等等。

接下来是 client 端的设定,以 MS Windows 为例:

对着桌面的 IE 按右键选 [内容] 或是在控制台中选 [因特网选项],出现图 15-1 的窗口:

图 15-1

选择上方 [联机] 的标签后,再点选 [局域网络设定],出现下面窗口。接着在Porxy 服务器的部份,在网址的部份输入 proxy server 的网址,连接端口默认值是 3128,接着按确定即可使用浏览器来试试看可不可以使用了:

图 15-2

15.3 Squid.conf 介绍

Squid 的设定档位于 /usr/local/etc/squid/squid.conf。在安装完 Squid 之后,我们必须修改它以期符合我们的需求。在 squid.conf 中,开头为 "#" 表示批注,每一个设定选项都有 TAG 表示选项名称、Usage 表示用法、Defaualt 表示默认值。如果不须改变默认值,我们不必将该行的批注 "#" 拿掉,否则可能会产生一些问题。在档案中有的 Default 写着 "none" 表示该选项没有默认值。

squid.conf 的详细说明可以到 www.squid-cache.org 参考设定手册。我们在这里介绍几个常用的选项设定方式:

选项名称: http_port

用法:

http_port port
http_port hostname:port
http_port 1.2.3.4:port

这是 Squid 要接收 HTTP 要求时所使用的 port。可以使用三种格式:只指定 port、使用 hostname 及 port、或是 IP 地址及 port。一般而言,我们只要指定 port 即可。我们也可以设定多行 http_port 来使用多个 port。

预设的 port 是 3128。

我们也可以在命令列下执行 squid 这个指令,并以参数 -a 来取代 squid.conf 中所设定的第一个 port。例如,我们要启动 squid 并将 port 改成 8080,可以下指令: /usr/local/sbin/squid -a 8080 使用 -a 来覆盖在 squid.conf 中所设定的第一个 port 只能适用于只指定 port 时,如果在 port 前有加上 ip 或 hostname 的话,这个指令就不会产生做用。

选项名称: icp_port

当 Squid 接收到 ICP 查询时,要响应时所使用的 port,可以设为 0 来停用 ICP 查询。也可以在命令列使用 -u 来覆盖这里的设定。 ICP 是 Squid cache 之间所使用的协议,用来交流多台 Squid 的 cache。目前 ICP 是使用 UDP 协议。

默认值: icp_port 3130

选项名称: mcast_groups

这个选项是用来指定这台服务器要加入 ICP 广播的群组,也就是指定 要收到的 ICP 查询的来源主机。 请注意!这个设定是 "接收" 查询而不是 "送出" 查询。如果要送出 ICP 广播查询是使用 cache_peer。 不可以将已加入别的群组的主机加入。

如果你想更深入了解 multcast 请参考 Squid FAQ (http://www.squid-cache.org/FAQ/)。

用法:

mcast_groups 239.128.16.128 224.0.1.20 

预设是不加入任何群组。

默认值:无

选项名称:cache_peer

用法:

cache_peer hostname type http_port icp_port [options]

这个选项可以让你设定上游的 proxy server,当本地没有该笔数据时,则向上游查询。

例如上游的 proxy 是 proxy.ncu.edu.tw,我们可以设定:

cache_peer proxy.ncu.edu.tw parent 3128 3130

选项名称:no_cache

设定不需要使用 cache 的项目。例如 CGI 不使用 cache,则可以做下列的设定:

acl QUERY urlpath_regex cgi-bin \?
no_cache deny QUERY

如果连 php、asp 都不要做 cache:

acl QUERY urlpath_regex cgi-bin \? \.php \.asp \.cgi
no_cache deny QUERY

选项名称:cache_mem

设定存放在内存中的数据大小,以 byte 为单位。这并不表示 squid 程序将在你内存中的所占的容量,除了 cache 的数据外,还有一些额外的东西会被放到内存中 (如 HD 的 index)。因此实际使用的内存大小可能是这里设定的二倍或三倍。建议设定为实际内存的三分之一。例如:

cache_mem 64 MB

选项名称:maximum_object_size

cache 对象的大小,超过此设定值则不存放于硬盘中。例如要设定档案大于 8 MB 则不储存:

maximum_object_size 8192 KB

选项名称:cache_dir

设定 cache 在硬盘中的目录、大小限制等。默认值是:

cache_dir ufs /usr/local/squid/cache 100 16 256

ufs 是 squid 的储存格式,一定要加。接下来的 /usr/local/squid/cache 是存放 cache 数据的地方。100 表示最多使用 100 MB 做为 cache 的空间,我们可以把它调大一点。而 16 256 是 cache 目录第一层及第二层的结构,建议不要更动。之前使用 /usr/local/sbin/squid -z 就是在建立 cache 目录的结构。

为了让 cache 的资料能存放多一点,我们可以将设定改成下面这样:

cache_dir ufs /usr/local/squid/cache 2000 16 256

选项名称:cache_access_log

cache 的使用记录存放的位置,内容包含了所有 HTTP 及 ICP 要求。默认值是:

cache_access_log /usr/local/squid/logs/access.log

选项名称:cache_log

这是设定另一个记录文件的位置,该文件中包含了 cache server 的一些信息、和 cache_peer 之间的联机等等。我们可以更改 "debug_options" 的选项来设定要记录的信息。默认值是:

cache_log /usr/local/squid/logs/cache.log

选项名称:cache_store_log

记录哪些数据被储存。可以使用 "none" 来停止这方面的记录。上面的 log 档,都可以用一些工具来分析 squid 的使用情形,但 store log 并没有,所以如果不想记录可以使用 "none" 来停止。

选项名称:pid_filename

设定存放 pid (process id) 的档案位置。

选项名称:ftp_user

设定当 proxy 以 anonymous FTP 联机时,要使用的 email。你可以设为:

ftp_user you@yourdomain.com

选项名称:cache_dns_program

squid 使用的 dns 查询程序的位置。squid 在查询 dns 时,会新增一个子程序 (process child) 来做查询,以免查询时间太长阻碍了 squid 的正常运作。

选项名称:dns_children

设定 dns 查询的 children 最大数量,默认值是 5,最大可以设为 32。以一个忙录的 squid server 而言,最小建议设为 10。

选项名称:acl

Access Control List。我们可以利用它来控制联机的权限及状态。用 acl 来搭配 http_access 等,可以让我们更方便管理。

用法:

acl aclname acltype string1 ...
acl aclname acltype "file" ...

aclname 是我们自己命名的标识符,要注意不要使用到 squid 的关键词。而 acltype 可以使用下列的选项:

更多的 acltype 关键词请看 squid.conf。

选项名称:http_access

用来控制要开放 squid 给哪些来源使用。预设是全部拒绝,最好不要不设防,例如使用 http_access allow all 就是一个不好的方式。

我们可以利用 http_access 搭配 acl 来控制使用情形。例如要开放给内部网域使用:

# INSERT YOUR OWN RULE HERE TO ALLOW ACCESS FROM
# YOUR CLIENTS
acl domain_allowed srcdomain .alexwang.com
acl ip_allowed src 192.168.0.0/24
http_access allow domain_allowed
http_access allow ip_allowed

在设定了可以使用的来源之后,最后再加上下列设定来拒绝其它联机:

http_access deny all

选项名称:icp_access

控制 squid 只响应哪些 sibling/child 的 ICP 询问。例如,只允许校内机器使用:

acl ncu src 140.115.0.0/255.255.0.0
icp_access allow ncu
icp_access deny all

选项名称:miss_access

控制只能做为 sibling 而不做 parent,例如:

acl localclients src 172.16.0.0/16
miss_access allow localclients
miss_access deny !localclients

选项名称:cache_peer_access

和 cache_peer 一样,只是这个选项可以使用 acl 来控制。

选项名称:cache_mgr

squid 管理者的 email。可以设定为本机的使用者,例如:

cache_mgr webmaster

或别台主机的 email:

cache_mgr jack@otherdomain.com

选项名称:cache_effective_user
选项名称:cache_effective_group

如果 squid 是以 root 的身份来执行,它会自动切换成这里所设定的使用者及群组。预设是 nobody,所以我们才会把 /usr/local/squid/cache/usr/local/squid/logs 的拥有者改成 nobody。

选项名称:visible_hostname

设定当 error message 显示时的 hostname。如果没有设定则以 gethostname() 所得到的 hostname 为主。

选项名称:httpd_accel_host
选项名称:httpd_accel_port

如果要以 Transparent Proxy 来执行,则设定:

httpd_accel_host virtual
httpd_accel_port 80

选项名称:httpd_accel_with_proxy on|off

如果要以 Transparent Proxy 及一般的 proxy 来执行则设为 on。

选项名称:httpd_accel_uses_host_header on|off

如果要以 Transparent Proxy 来执行,则设为 on。让 squid 可以经由 HTTP header 来判断 url。

选项名称:logfile_rotate

设定要保留的 log file 份数,让执行 squid -k rotate 来分析 squid 时使用。

选项名称:err_html_text

该你可以在指定要出现的 error page (就是会有 mailto 的网页)。

选项名称:deny_info

用法:

deny_info err_page_name acl

可以让你指定当拒绝联机时要使用的 HTML 档案。例如:

deny_info ERR_CUSTOM_ACCESS_DENIED bad_guys

这些 HTMl 档都放在 /usr/local/etc/squid/errors/,而且没有扩展名 .html。

选项名称:error_directory

如果自行建立一些 error message 的 HTML,我们可以放在预设的 /usr/local/etc/squid/errors 或是自行指定目录位置。

15.4 Transparent Proxy

有的使用者可能不想设定 Proxy,或者是管理者希望能不必设定 client 端即可使用 proxy,我们可以使用 Transparent Proxy 来强迫使用者使用 Proxy。只要在 Gateway 上使用防火墙来将对外的联机要求重导到 proxy server 即可。

这里我们假设 Proxy 就是 Gateway,它身兼 NAT 功能,我们内部的网域为 192.168.0.1/24。我们不提 NAT 的设定,只针对 Transparent Proxy 相关的设定加以说明。首先要先确认 kernel 中除了原有关于防火墙的设定外,有没有 FORWARD 封包的设定,如果没有必需自行加入并重编 kernel:

# 原有的防火墙设定
options IPFIREWALL
options IPDIVERT
options IPFIREWALL_VERBOSE
options IPFIREWALL_DEFAULT_TO_ACCEPT

# 新加入关于封包转向的设定
options IPFIREWALL_FORWARD

接着在 /etc/rc.firewall 中加入:

/sbin/ipfw add 50000 fwd 127.0.0.1,3128 tcp from 192.168.0.0/24 to any 80

上面那一行的设定表示凡是由 192.168.0.* 的 IP 要连到任何对于的 port 80 时,便转向到 127.0.0.1 这台机器(也就是本机) 的 port 3128。你可以依自己的情况加以修改。然后编辑 /usr/local/etc/squid/squid.conf,在最开头加入下面这几行:

httpd_accel_host virtual
httpd_accel_port 80
httpd_accel_with_proxy on
httpd_accel_uses_host_header on

完成后重新启动 squid 及 ipfw 即可使用。

15.5 Proxy 管理

15.5.1 log 档移转

log 档在频繁的使用下会一直成长,因此我们可以利用 crontab 来设定每天备份各个 log 档。执行 crontab -e 后,加入下列内容:

0 5 * * * /usr/local/sbin/squid -k rotate

这里我们设定为每天早上五点备份 log 档,如果您对于 crontab 的用法不熟悉,请 man crontab

15.5.2 关机注意事项

由于 squid 对于硬盘的读写十分频繁,而且有大量的数据在内存中。因此在关机前要先停止 squid:

# /usr/local/etc/rc.d/squid.sh stop