第十五章 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