以 Squid 架設 Web Cache Server

1、前言

Squid Web Proxy Cache目前為最多人使用的 Web Proxy Server ,本篇實作為利用 Squid 來架設 Web Proxy Server,關於 Web Proxy 如何運作可參考 WebProxy 伺服器的原理與運作流程



Squid 支援功能如下:
  • proxying and caching of HTTP, FTP, and other URLs
  • proxying for SSL
  • cache hierarchies
  • ICP, HTCP, CARP, Cache Digests
  • transparent caching
  • WCCP (Squid v2.3 and above)
  • extensive access controls
  • HTTP server acceleration
  • SNMP
  • caching of DNS lookups





文章目錄

1、前言
2、實作環境
3、安裝及設定
          步驟1.安裝 squid 套件
          步驟2.修改 squid.conf 設定檔
          步驟3.初始化 Squid cache dir 目錄結構
          步驟4.啟動 squid 服務
          步驟5.測試 squid 是否啟動成功
4、補充1.Transparent Proxy
          步驟1.修改 squid 設定檔
          步驟2.配合 RDR 設定
5、補充2.Squid 後續運作事宜
          步驟1.修改設定檔內容後,如何使 squid 重新讀取設定檔而不需重新啟動 squid 服務
          步驟2.重開機或關機前建議先停止 squid 服務
          步驟3.定期備份 squid log
          步驟4.定期查看及分析 squid log
6、參考
7、Me FAQ
          Q1.TCP_DENIED/403 1494 GET http://tw.yahoo.com/ - NONE/- text/html?
          Q2.無法使用 Transparent Proxy 功能 Invalid Request?
          Q3./usr/sbin/squid -k rotate 沒有作用?
          Q4.Squid Client 無法連 https (SSL) 及 FTP 網頁?
          Q5.FATAL: Could not determine fully qualified hostname. Please set 'visible_hostname'?
          Q6.access.log 不斷出現 TCP_MISS/503 的問題?
          Q7.squid: ERROR: No running copy?
          Q8.TCP_NEGATIVE_HIT/403?
          Q9.TCP_MISS/403?





2、實作環境

  • CentOS 5.1 (Linux 2.6.18-53.1.4.el5)
  • squid-2.6.STABLE6-5.el5_1.2





3、安裝及設定

步驟1.安裝 squid 套件

利用 yum 指令安裝 squid 套件。
yum -y install squid             //使用 yum 安裝 squid 套件



步驟2.修改 squid.conf 設定檔

因為我會習慣把相關的東西拉到 /home 下,以下是相關資料:
  • 自行建立 cache directory:/home/log/squid/cache (Default: /var/spool/squid),owner:group 皆為 squid 且目錄權限為 750。
  • 自行建立 log directory:/home/log/squid/ (Default: /var/log/squid),owner:group 皆為 squid 且目錄權限為 750。
  • 預設 squid 服務是全部拒絕的要允許的話就在設定檔內 http_access 加上吧。
  • 啟動 squid 服務前記得初始化 cache directory (squid -z)。
  • 啟動 squid 服務前記得檢查設定檔語法是否正確 (squid -f /path/to/squid.conf -k parse)。

squid.conf 設定檔內容跟用 FreeBSD 架設 Squid-Web Proxy Server 時有點不一樣,以下是實作時發現不一樣的地方有二個 http_access、logfile_rotate

http_access allow:這行內的 acl name 無法寫在同一行 (會不通 TCP_DENIED/403),而分開寫之後就會通了 (TCP_MISS/200),這個地方有點怪?
  • FreeBSD 使用 Ports 安裝 squid:http_access allow acl name 可寫在同一行且會通。
  • CentOS 使用 yum 安裝 squid:http_access allow acl name 寫在同一行是不通的,要分開才會通。

logfile_rotate:squid.conf 設定檔也說明預設值是 10 但安裝好之後卻是 0?
  • FreeBSD 使用 Ports 安裝 squid:設定檔內 logfile_rotate 10。
  • CentOS 使用 yum 安裝 squid:設定檔內 logfile_rotate 0 (而設定檔說明有提到 0 will disable the rotation)。
vi /etc/squid/squid.conf  //修改 squid 設定檔(僅列出與預設值不同處)
 http_port 3128                 //接受 HTTP 要求時使用的 Port
 maximum_object_size 5120 KB    //設定 cache 網頁資料最大值 (超過 5MB 就不 cache)
 acl QUERY urlpath_regex cgi-bin \? \.php \.asp \.cgi  //設定針對 CGI、PHP、ASP 檔案不作 cache
 no_cache deny QUERY  //定義名稱為 QUERY 的項目不作 cache
 cache_mem 32 MB      //設定存放在 RAM 裡面的 cache 大小 (通常為實體記憶體 1/4)
 cache_swap_low 75    //快取網頁佔用磁碟容量最低值(保留最新的快取資料為 2 GB 的 75%)
 cache_swap_high 95   //快取網頁佔用磁碟容量渡高值(佔用2GB的95 時砍掉舊快取資料至2GB的75%)
 cache_dir ufs /home/log/squid/cache 2048 16 256  //設定 cache 在 HDD 裡面的大小 (最多使用 2 GB、第一層 16 個目錄 、第二層 256 個目錄)
 cache_log /home/log/squid/cache.log              //記錄 squid 的執行狀況
 access_log /home/log/squid/access.log squid      //記錄 squid client 的 HTTP 及 IGP request
 cache_store_log /home/log/squid/store.log        //記錄 squid cache 哪些網頁資料
 acl all src 0.0.0.0/0.0.0.0       //Access Control List Source IP 0.0.0.0 Name all
 acl localhost src 127.0.0.1/255.255.255.255      //Source IP 127.0.0.1 Name localhost
 acl lanuser src 192.168.1.0/24    //Source IP Range 192.168.1.0 Name lanuser
 http_access allow localhost       //允許定義名稱 localhost 能使用 squid 服務
 http_access allow lanuser         //允許定義名稱 lanuser 能使用 squid 服務
 http_access deny all              //禁止其它 IP 使用 squid 服務
 logfile_rotate 10                 //預設為 0 (disable the rotation)




步驟3.初始化 Squid cache dir 目錄結構

修改完 squid 設定檔後若是新安裝的話,則在啟動 squid service 之前我們要先初始化 cache dir 目錄結構 (若是舊版升級的話就不用了,因為初始化會把 cache 資料夾清空),建立好之後可到 /home/log/squid/cache 查看,會發現建立很多 squid cache 目錄結構。
/usr/sbin/squid -z    //初始化 cache_dir (建立相關目錄結構)
 2008/01/11 15:30:48| Creating Swap Directories




步驟4.啟動 squid 服務

在啟動服務之前我們記得先執行 chkconfig 以便重開機能自動帶起 suqid 服務。
chkconfig --list |grep squid      //查尋 squid 的 runlevel 情況
 squid           0:off   1:off   2:off   3:off   4:off   5:off   6:off
chkconfig --levels 235 squid on   //設定在 runlevel 2,3,5 時會啟動服務
chkconfig --list | grep squid     //檢查設定是否生效
 squid           0:off   1:off   2:on    3:on    4:off   5:on    6:off

在啟動 squid 服務之前我們先確定設定檔的語法是否正確 (沒任何訊息就代表設定檔語法都正確!!)。
/usr/sbin/squid -f /etc/squid/squid.conf -k parse
啟動 squid service。
/etc/rc.d/init.d/squid start
 Starting squid: .              [OK]




步驟5.測試 squid 是否啟動成功

檢查 squid process 是否執行。
ps ax |grep squid
 3687 ?        Ss     0:00 squid -D
 3689 ?        S      0:00 (squid) -D

檢查 squid 是否 listen 設定的 http request port。
netstat -tnl |grep :3128
 tcp        0      0 0.0.0.0:3128      0.0.0.0:*        LISTEN

檢查 squid 是否作用了。
telnet localhost 3128   //假設 squid 為本機
 GET / enter               //輸入 GET 及反斜線後在按下 Enter

當 Enter 按入後,若你看到一堆 HTML 的輸出,代表你的 squid 服務啟動成功了 squid client 可設定瀏覽器來使用 web proxy 了,以下為 IE、Netscape、Firefox 等瀏覽器如何設定 Proxy 的相關參考網址:





4、補充1.Transparent Proxy

為何要使用 Transparent Proxy,若您設好 squid 但 user 端有一、二百台且在沒有 AD Directory 的架構下難道要一台一台去設定 user 端的 Brower?這時我們就可使用 Transparent Proxy 來達成讓 user 端不用設定也能使用 Web Proxy。

步驟1.修改 squid 設定檔

新的 squid 版本對於 Transparent Proxy 設定簡化了,詳細資料可以參考官網說明 Squid 2.6.STABLE8 release notes,簡單說就是把一些功能都整合到 http_port 的 option 內了。
vi /usr/local/etc/squid/squid.conf   //修改 squid 設定檔
 http_port 3128               //修改前
 http_port 3128 transparent   //修改後 (加上 transparent option)




步驟2.配合 RDR 設定

再來就是配合 RDR(Redirect) 設定了,簡單說就是 LAN User 要對外存取 HTTP (80) 時就導到 squid 主機的 3128 出去,以下列出 IPTables Rule (需依網路環境作調整)。此次實作環境如下:
  • squid ip 為 192.168.1.10
  • squid 網卡代號為 eth0
  • Lan user 網段為 192.168.1.0/24

若是下一行指令可這樣下:
iptables -t nat -A PREROUTING -i eth0 -p tcp -s 192.168.1.0/24 --dport 80 -j REDIRECT --to-port 3128
若是要寫入 /etc/sysconfig/iptables 就把如下幾行貼到 iptables 內在重啟 iptables 吧。
 *nat
 :PREROUTING ACCEPT 0:0
 :POSTROUTING ACCEPT 0:0     //設 drop 會不通
 :OUTPUT ACCEPT 0:0          //設 drop 會不通
 -A PREROUTING -i eth0 -p tcp -s 192.168.1.0/24 --dport 80 -j REDIRECT --to-ports 3128
 COMMIT

整個完整的 Transparent Proxy IPTables 規則如下 (記得 filter 內 FORWARD 必須為ACCEPT 否則 Client 連外 SSL(443)、FTP(21) 會不通。
 *nat
 :PREROUTING ACCEPT 0:0
 :POSTROUTING ACCEPT 0:0
 :OUTPUT ACCEPT 0:0
 -A PREROUTING -i eth0 -p tcp -s 192.168.1.0/24 --dport 80 -j REDIRECT --to-ports 3128
 COMMIT
 *filter
 :INPUT DROP 0:0
 :FORWARD ACCEPT 0:0   //設為 drop 則連外 SSL(443)、FTP(21) 會不通
 :OUTPUT ACCEPT 0:0
 -A INPUT -i lo -j ACCEPT
 -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
 -A INPUT -p icmp -m icmp --icmp-type any -j ACCEPT
 -A INPUT -i eth0 -p tcp --dport 53 -j ACCEPT
 -A INPUT -i eth0 -p udp --dport 53 -j ACCEPT
 -A INPUT -i eth0 -p tcp -s 192.168.1.0/24 --dport 3128 -j ACCEPT
 COMMIT

啟用 IP Forwarding 功能,也就是啟用剛才設定的 RDR (Redirect) Rules,修改的 sysctl.conf 檔案內容以代替內部網路的主機傳送封包 (重開機後 /proc/sys/net/ipv4/ip_forward 將由 0 -> 1)。
#vi /etc/sysctl.conf    
 net.ipv4.ip_forward=0->1   

修改 /proc/sys/net/ipv4/ip_forward 的檔案內容將 0 -> 1,並重新啟動 iptables 服務後立刻生效。
#echo 1 > /proc/sys/net/ipv4/ip_forward    //將 0 -> 1
#/etc/rc.d/init.d/iptables restart          //重新啟動 iptables 服務
 Flushing firewall rules:                                   [OK]
 Setting chains to policy ACCEPT: filter nat    [OK]   //啟用 RDR(Redirect) 設定
 Unloading iptables modules:                    [OK]
 Applying iptables firewall rules:              [OK]
 Loading additional iptables modules: ip_conntrack_netbios_n  [OK]  






5、補充2.Squid 後續運作事宜

步驟1.修改設定檔內容後,如何使 squid 重新讀取設定檔而不需重新啟動 squid 服務

若修改設定檔內容又不想重新啟動 squid 服務可以下此指令。
/etc/rc.d/init.d/squid reload    //squid 重新讀取設定檔 (方法一)
/usr/sbin/squid -k reconfigure   //squid 重新讀取設定檔 (方法二)
less /home/log/squid/cache.log   //可看到 squid 執行狀況




步驟2.重開機或關機前建議先停止 squid 服務

另外值得注意的是因為 squid 對硬碟讀寫 (I/O) 很頻繁且會有一堆資料 cache 在記憶體中,因此建議您若 Proxy Server 要重開機或關機前先把 squid service stop。
/etc/rc.d/init.d/squid stop



步驟3.定期備份 squid log

squid 相關 Logs (access.log、cache.log、store.log) 在不停運作中若不備份將會使硬碟空間很容易爆所以我們可使將入排程來定期將 squid log 備份。
 0 3 * * * /usr/sbin/squid -k rotate        //定期於每天早上三點備份 Logs



步驟4.定期查看及分析 squid log

安裝 Proxy Server 主要用意就是讓 Proxy Client 看網頁的速度加快,所以建議隨時查看 Squid Access.log 了解快取的命中率及效率,關於 access.log 內詳細 Result Codes 說明請參考 SquidLogs - Squid Web Proxy Wiki
cd /home/log/squid
cat access.log|gawk '{print $4}' |sort|uniq -c|sort -nr   //列出 Log 中各項數值
  16667 TCP_MEM_HIT/200   //代表 Client 從 Cache 中讀取網頁資料
  16662 TCP_HIT/200
   9439 TCP_REFRESH_HIT/200
   7856 TCP_REFRESH_HIT/304
   7200 TCP_MISS/200
 ...略...

若要查看更詳細的數據可使用 squidclient 指令。
  • Squid 快取分析 (mgr:info): squidclient -p 3128 mgr:info
  • Squid 記憶體使用分析 (mgr:mem): squidclient -p 3128 mgr:mem
  • Squid 硬碟使用分析 (mgr:diskd): squidclient -p 3128 mgr:diskd





6、參考






7、Me FAQ

Q1.TCP_DENIED/403 1494 GET http://tw.yahoo.com/ - NONE/- text/html?

Error Message:
修改好 squid 設定檔並啟動 squid 服務,但 Client 連結網站例如 http://tw.yahoo.com 都會出現如下圖 Access Denied 畫面。


查看 /home/log/squid/access.log 內容如下 (TCP_DENIED/403)。
 1200039848.482  0 192.168.203.1 TCP_DENIED/403 1494 GET http://tw.yahoo.com/ - NONE/- text/html
Ans:
http_access allow:這行內的 acl name 無法寫在同一行 (會不通 TCP_DENIED/403),而分開寫之後就會通了 (TCP_MISS/200),這個地方有點怪?
  • FreeBSD 使用 Ports 安裝 squid:http_access allow acl name 可寫在同一行且會通。
  • CentOS 使用 yum 安裝 squid:http_access allow acl name 寫在同一行是不通的,要分開才會通
  • 設定檔內容 http_access allow acl name 寫在同一行不通 (TCP_DENIED/403)。
 http_access allow localhost lanuser 
設定檔內容 http_access allow acl name 分開才會通 (TCP_MISS/200)
 http_access allow localhost
 http_access allow lanuser




Q2.無法使用 Transparent Proxy 功能 Invalid Request?

Error Message:
設好 IPTables 的 RDR 設定後,Client 連結網站卻出現如下錯誤訊息。


Ans:
自已耍小白忘了把 squid.conf 設定檔加入 transparent option,加入後記得 service squid reload 哦。
vi /usr/local/etc/squid/squid.conf   //修改 squid 設定檔
 http_port 3128               //修改前
 http_port 3128 transparent   //修改後 (加上 transparent option)




Q3./usr/sbin/squid -k rotate 沒有作用?

Error Message:
執行 /usr/sbin/squid -k rotate 想產生 squid rotate log 但卻像沒作用一般,但也沒有出現錯誤訊息?

Ans:
logfile_rotate:squid.conf 設定檔也說明預設值是 10 但安裝好之後卻是 0?
  • FreeBSD 使用 Ports 安裝 squid:設定檔內 logfile_rotate 10。
  • CentOS 使用 yum 安裝 squid:設定檔內 logfile_rotate 0 (而設定檔說明有提到 0 will disable the rotation)。



Q4.Squid Client 無法連 https (SSL) 及 FTP 網頁?

Error Message:
設定完 Transparent Proxy 後 Squid Client 無法連到 https (SSL) 網頁 (ex. Gmail、Yahoo mail、MSN mail....)、FTP 網頁,但若是在 IE 設定 Proxy 3128 又可連到 https (SSL) 網頁?

查看 access.log 得到如下訊息
tail access.log |grep 192.168.1.5
 1201139169.821      0 192.168.1.5 TCP_DENIED/400 1179 NONE error:unsupported-request-method - NONE/- text/html

IE 設 Porxy IP 及 Port 3128 可以 https 網頁
tail -f /home/log/squid/access.log  |grep 192.168.1.5
 1201144616.799    739 192.168.203.5 TCP_MISS/200 2931 CONNECT mail.google.com:443 - DIRECT/209.85.139.18 -

Ans:
原因在於未把 IPTables 的 IP Forwarding 功能給啟用造成的,開啟後 Squid Client 就可正常連結到 https (SSL) 網頁 (ex. Gmail、Yahoo mail、MSN mail....)、FTP 網頁了。整個完整的 Transparent Proxy IPTables 規則如下 (記得 filter 內 FORWARD 必須為ACCEPT 否則 Client 連外 SSL(443)、FTP(21) 會不通。
 *nat
 :PREROUTING ACCEPT 0:0
 :POSTROUTING ACCEPT 0:0
 :OUTPUT ACCEPT 0:0
 -A PREROUTING -i eth0 -p tcp -s 192.168.1.0/24 --dport 80 -j REDIRECT --to-ports 3128
 COMMIT
 *filter
 :INPUT DROP 0:0
 :FORWARD ACCEPT 0:0         //設為 drop 則連外 SSL(443)、FTP(21) 會不通
 :OUTPUT ACCEPT 0:0
 -A INPUT -i lo -j ACCEPT
 -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
 -A INPUT -p icmp -m icmp --icmp-type any -j ACCEPT
 -A INPUT -i eth0 -p tcp --dport 53 -j ACCEPT
 -A INPUT -i eth0 -p udp --dport 53 -j ACCEPT
 -A INPUT -i eth0 -p tcp -s 192.168.1.0/24 --dport 3128 -j ACCEPT
 COMMIT

啟用 IP Forwarding 功能,修改的 sysctl.conf 檔案內容以代替內部網路的主機傳送封包 (重開機後 /proc/sys/net/ipv4/ip_forward 將由 0 -> 1)。
vi /etc/sysctl.conf    
 net.ipv4.ip_forward=0->1   

修改 /proc/sys/net/ipv4/ip_forward 的檔案內容將 0 -> 1 (立刻生效)
echo 1 > /proc/sys/net/ipv4/ip_forward



Q5.FATAL: Could not determine fully qualified hostname. Please set 'visible_hostname'?

Error Message:
當啟動 Squid 服務時出現如下錯誤訊息?
 Squid Cache (Version 2.6.STABLE6): Terminated abnormally.
 CPU Usage: 0.004 seconds = 0.003 user + 0.001 sys
 Maximum Resident Size: 0 KB
 Page faults with physical i/o: 8
 FATAL: Could not determine fully qualified hostname.  Please set 'visible_hostname'

Ans:
原因是 /etc/hosts 設定不正確造成的,設定正常後就可正常啟動了 (visible_hostname 不須設定預設值即可)
/etc/rc.d/init.d/squid 
startStarting squid: .  [OK]  



Q6.access.log 不斷出現 TCP_MISS/503 的問題?

Error Message:
當 Client 連線至網頁 (例如: yahoo 股市)時 access.log 就會出現 TCP_MISS/503 的訊息,而 Client 端會遲遲無法開出網頁最後 time out 並出現 113 no route to host 訊息。

Squid Server access.log
 1207713302.230  51105 192.168.203.12 TCP_MISS/503 1514 GET http://tw.stock.yahoo.com/w/index - DIRECT/202.43.195.26 text/html
Squid Client 出現
 113 no route to host
Ans:
原因為我的 cache_swap_low、cache_swap_high 採用預設值 (90、95),這二個值的意思代表如何你設定的快取容量為 2 GB,則當快取資料量達到 2 GB 的 95% 時,Squid 會把快取資料內舊的資料刪除至 2 GB 的 90%,以便使 Squid 的資料保持新的快取資料,但這二個值設定太過接近時會使 Squid 在新的快取資料要寫入但 Squid 還來不及把舊的快取資料砍掉,此時當 Client 要求新的快取資料時便會出現 TCP_MISS/503 問題了,所以把二個數量拉大便可解決此一問題。
vi /etc/squid/squid.conf      //修改 squid 設定檔
 cache_swap_low 75   //快取網頁佔用磁碟容量最低值 (保留最新的快取資料為 2 GB 的 75%)
 cache_swap_high 95  //快取網頁佔用磁碟容量渡高值 (佔用 2 GB 的 95% 時砍掉舊快取資料至 2 GB 的 75%)




Q7.squid: ERROR: No running copy?

Error Message:
當我執行 -k rotate 時出現如下錯誤訊息。
 squid: ERROR: No running copy
查看 squid 的執行狀態時也出現如下錯誤訊息
/etc/rc.d/init.d/squid status
 squid is stopped
 squid: ERROR: No running copy

Ans:
原因似乎是出在我在關機前忘了先把 squid 服務停止導致的,記得有跑 squid 的機器關機前一定要先把 squid 服務停掉。
/etc/rc.d/init.d/squid stop



Q8.TCP_NEGATIVE_HIT/403?

Error Message:
Proxy Client 反應有些網站的圖看不到,查看 access.log 中發現 Cleint 存取該圖片資訊為 TCP_NEGATIVE_HIT/403。
 1244195183.491      0 192.168.1.5 TCP_NEGATIVE_HIT/403 503 GET ...略
Ans:
Squid result codes - TCP_NEGATIVE_HIT 簡單說就是對方 Web 回應你 ex. 404 not found 的回應,且在自身 Cache 中也無法使用該資源,您可透過設定 squid.conf 內 negative_ttl 選項來進行控制。
vi /etc/squid/squid.conf
 negative_ttl 5 minutes     //預設值
 negative_ttl 0 minutes     //修改後




Q9.TCP_MISS/403?

Error Message:
Proxy Client 反應有些網站的圖看不到,查看 access.log 中發現該圖片資訊為 TCP_MISS/403
 1244195183.491      0 192.168.1.5 TCP_MISS/403 503 GET ...略
Ans:
Squid result codes - TCP_MISS 簡單說就是 Squid Server 沒有 Cache 資源回應給 Squid Client,通常 Squid Server 就會嘗試出去抓取資源,而本次的 TCP_MISS/403 則是代表 Squid Server 嘗試存取遠端 Web 時得到存取被拒 (403 Forbidden) 的回應。

我們可嘗試修改在 squid.conf 內 reload_into_ims 選項 (預設值為 off) 來測試看看能否解決此一問題,將 reload_into_ims 調整為 on 也就是只有在瀏覽的網頁內容發生改變時 Squid 才放棄原來的 Cache 資源。
vi /etc/squid/squid.conf
 reload_into_ims off   //預設值
 reload_into_ims on    //修改後

修改後 access.log 內容則從 TCP_MISS/403 改變為 TCP_REFRESH_MISS/403,也就是 Squid Server 確實嘗試過發送 HTTP 請求到遠端 Web 而證明 Cache 資源確實是舊的,但遠端 Web 仍回應 Squid Server 存取被拒 (403 Forbidden) 的回應,所以答案是對方限制您 Squid 的存取行為。