Raspberry Pi 的應用 - 加快上網速度的 Squid 快取伺服器

by 3/13/2015 0 意見

在瀏覽器裡面,為了加快我們瀏覽網頁的速度,會自動將連線過的網頁暫時儲存起來,讓我們下次再開啟同一個網頁的時候,如果文字或圖片沒有改變的時候,可以直接從硬碟的快取空間裡讀取,借以減少頻寬的浪費,並加快顯示的速度。

那有沒有什麼方法,可以讓這種機制同時提供給很多人一同使用呢 ???


簡介


首先有個觀念一定要先提醒大家:「並不是自己的網路頻寬夠大夠快,上網就一定很快 !!!」

千萬別忘了,網路是雙向的,除了我們自己的網路之外,包括主機端和中間經過的節點全部都必須夠快,整體的速度才能一同提昇,這個原則不管是區域網路 (LAN) 或是廣域網路 (WAN) 全部都一樣。

我們看一下 Hinet 的官網的連線過程。

光是在台灣本地,就經過了 8 個節點來轉送,更別提國外的網站了,不管哪一個節點速度變慢,勢必都會影響整體的傳輸速度。

為了減少網路存取的時間,瀏覽器有快取 (Cache) 功能,以 Mac 版的 Firefox 為例,在「偏好設定」-「進階」-「網路」的窗格裡,就可以看到「已快取的網頁內容」的功能。

我們使用瀏覽器上網時,它會先檢查目標網站上的網頁內容是否已經存在快取區域裡,若有,就直接從硬碟讀取,沒有的話才會真的從網站下載。

代理伺服器 (Proxy Server) 也很簡單,我們就把瀏覽器的快取機制,放大到整個區域網路來用,只要任一個使用者透過它連上任意網站,它就會幫我們把這些內容快取在它的硬碟裡,之後不論是誰連上同一個網站,它會自動去比對內容,若已沒有變化,就直接從把快取資料傳給使用者,以區域網路常見的 100MB 速度,一定遠比重新下載還快。

事前準備

  • Raspberry Pi Type B / B+,Type A / A+ 必須自行插上 USB 網路卡。
  • Raspbian 作業系統。
  • 我們要實作的是 通透式代理 (Transparent Proxy),請先依照 Raspberry Pi 的實作 - Wi-Fi 無線基地台 的步驟,完成路由模式的設定。
  • 外接儲存設備,用來儲存快取檔案用的,強烈建議使用 USB 外接硬碟。
    如果我們直接用記憶卡或外接隨身碟來儲存也不是不行,只是由於讀寫次數頻繁,Flash IC  通常會受不了這樣子的操勞,很快就可以享受到「終身保固」的尊榮服務了。
    不過,用外接硬碟的話,由於 Raspberry Pi 的供電不足以推動外接硬碟,所以一定要有獨立電源。

安裝服務


我們會用 Squid 這個套件來實作代理伺服器的服務。

首先從 Raspbain 官方套件庫安裝 squid 套件。
sudo apt-get -y install squid

安裝完畢之後,服務就被啟動了,之後開機也會被自動啟動。

這裡以 A-Data 16GB 隨身碟來做示範。

先看一下分割表的狀態,目前只有一個分割區。
sudo fdisk -l

將原來的分割區全刪掉,請注意,fdisk 指令的目標是針對整個磁碟去處理,而不是分割區
sudo fdisk /dev/sda


只建立一個主分割區。

將結果寫入硬碟裡。

將檔案系統格式化成 ext4,別忘了,這個動作針對的目標變成分割區,而不是整個磁碟
sudo mkfs -t ext4 /dev/sda1

格式化的時候要稍等一下,所需的時間與容量成正比。完成後,檔案格式就被轉成了 LInux 的 ext4 了。

接著,我們建立一個掛載用的目錄。
sudo mkdir /mnt/squid-cache

確認一下啟動 squid 的使用者,發現啟動服務用的帳號是 proxy。
ps -ef | grep squid

調整一下權限,開放 proxy 這個使用者讀寫。
sudo chown proxy:proxy -R /mnt/squid-cache

把隨身碟掛載上來,準備成為快取的寫入目錄。
sudo mount -t ext4 /dev/sda1 /mnt/squid-cache

這樣子就完成前置動作了。


修改主設定檔


squid 的主設定值在 /etc/squid/squid.conf,詳細的設定說明可以參閱 squid-cache wiki
sudo vi /etc/squid/squid.conf

這邊介紹幾個重要的設定值。

acl localnet src 10.0.0.0/8
acl localnet src 172.16.0.0/12
acl localnet src 192.168.0.0/16
預設定義了 Class A、B、C 的 Private IP,請自行增加實際環境裡的 IP 網段。

http_access deny to_localhost
禁止 HTTP 連線要求存取 Raspberry Pi 本機。

http_access allow localnet
允許自訂定義的內部 IP 網段可以對外 HTTP 連線

http_port 3128 transparent
預設通訊埠為 Port 3128,transparent 代表啟用通透模式。

cache_dir ufs /mnt/squid-cache 8000 16 256
指定儲存快取檔案的目錄,這邊指定到 /mnt/squid-cache 去,可使用的容量為 8000,單位是 MB,也就大概是 8GB 左右。
如果這個目錄的可用空間不夠的話,也可以增加多個目錄來使用。

minimum_object_size 0 KB
maximum_object_size 10240 KB
可以儲存到快取的網頁、圖片、文字 ... 等檔案容量最小及最大的範圍,大於或小於這兩個數字就不儲存到快取裡面。

設定完成後,需要重新啟動服務讓設定值生效。
sudo service squid restart

第一次啟動時,Squid 會重新建立快取目錄的結構,啟用代理服務。


設定為通透代理模式


Proxy 主要有三種運作模式,說明請參閱 維基百科 - 代理伺服器
  • 正向代理 (Forward Proxy)
  • 反向代理 (Reverse Proxy)
  • 通透代理 (Transparent Proxy)

為什麼我們要使用的通透代理模式呢?目的是讓使用者透過 Wi-Fi 連上 Raspberry Pi,不需要額外的任何設定,就可以使用代理伺服器的功能了,避免造成使用者還要額外設定 Proxy 相關參數的困擾。

我們完成了 Raspberry Pi 的實作 - Wi-Fi 無線基地台 的路由模式之後,iptables 的規則是:
sudo iptables -F
sudo iptables -F -t nat
sudo iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
sudo iptables -A FORWARD -i eth0 -o wlan0 -m state --state RELATED,ESTABLISHED -j ACCEPT
sudo iptables -A FORWARD -i wlan0 -o eth0 -j ACCEPT

如果再加上 Raspberry Pi 的應用 - 讓 Wi-Fi 無線基地台隱藏我們的 IP 位址 之後,多了這三行。
sudo iptables -t nat -A PREROUTING -i wlan0 -p tcp --dport 22 -j REDIRECT --to-ports 22
sudo iptables -t nat -A PREROUTING -i wlan0 -p udp --dport 53 -j REDIRECT --to-ports 53
sudo iptables -t nat -A PREROUTING -i wlan0 -p tcp --syn -j REDIRECT --to-ports 9999

這次還要再增加 Squid 的通透模式的話,只要加上再加上兩行 iptables 指令,讓原本從 Port 80 連出的 HTTP 請求,以及 Port 443 連出的 HTTPS 請求,轉到 Port 3128 的 Proxy 統一對外連線即可。
sudo iptables -t nat -A PREROUTING -i wlan0 -p tcp --dport 80 -j REDIRECT --to-ports 3128
sudo iptables -t nat -A PREROUTING -i wlan0 -p tcp --dport 443 -j REDIRECT --to-ports 3128

此外,從區域網路內連上 Raspberry Pi 的 Web Server 時,跳過 Squid,直接連線即可。
sudo iptables -t nat -A PREROUTING -i wlan0 -p tcp -d 192.168.43.1 --dport 80 -j ACCEPT

最後變成了這樣子。
sudo iptables -F
sudo iptables -F -t nat
sudo iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
sudo iptables -A FORWARD -i eth0 -o wlan0 -m state --state RELATED,ESTABLISHED -j ACCEPT
sudo iptables -A FORWARD -i wlan0 -o eth0 -j ACCEPT
sudo iptables -t nat -A PREROUTING -i wlan0 -p tcp --dport 80 -j REDIRECT --to-ports 3128
sudo iptables -t nat -A PREROUTING -i wlan0 -p tcp --dport 22 -j REDIRECT --to-ports 22
sudo iptables -t nat -A PREROUTING -i wlan0 -p udp --dport 53 -j REDIRECT --to-ports 53
sudo iptables -t nat -A PREROUTING -i wlan0 -p tcp --syn -j REDIRECT --to-ports 9999
sudo bash -c 'iptables-save > /etc/network/iptables.squid'
sudo iptables-restore < /etc/network/iptables.squid



用戶端連線


這個以 iPhone 為例,只要我們從 Wi-Fi 連線到 Raspberry Pi。

打開 Safari 連上任一個網站。


可以從 access.log 檔的內容看到,Squid 已經開始運作了。
sudo more /var/log/squid/access.log

剛開始用的時候,因為還沒有任何的快取檔案,所以還不會有效果。
sudo more /var/log/squid/cache.log

等到快取檔案慢慢的開始累積之後,才會有明顯加速的感覺。


異常排除

  • 我可以在辦公室、教室給大家一起用嗎?

    Raspberry Pi 的硬體等級不足以負擔太重的 Proxy 流量,如果用戶端數量太多的話,還是直接用一台安裝 Linux 的 x86 或 x64 PC 來跑吧。
     
  • 為什麼我設定好了通透模式,HTTPS 協定可以連的上,HTTP 協定卻沒有反應呢?

    請檢查 Squid 主設定檔的 http_port 參數有沒有加上 transparent。


系列文章


參考資料


圖片來源


更新紀錄

  • 2015/03/13 撰文。

Heracles Jam,江湖人稱「海公公」

IT 技術家 - 創站部落客

一個常用 Windows、慣用 macOS、愛用 Linux 的 3C 阿宅
現職 MIS / 業界講師 / 資訊顧問 / 部落客

0 意見 :

張貼留言