http代理伺服器

陳順吉發表於2018-12-31

做過運維的都知道一個常識,生產環境不能夠連線外網,主要還是為了安全。但是總有連線外網的需求,比如時間同步、映象站同步、郵件傳送、釘釘/微信告警什麼的,這些需求往往涉及到多臺伺服器,我們不能為這些伺服器都開通訪問外網的策略,所以最好的做法是將一臺服務開通外網訪問,其他有外網需求的通過它來上網。

這就是典型的代理伺服器了,客戶端請求傳送給代理器,由代理伺服器進行轉發,然後將響應的內容傳送給客戶端。可以用於代理伺服器的軟體有不少,squid 和 goproxy 都可以,它們都是開源軟體,也是今天要提到的,它們使用起來都非常簡單。

本次伺服器作業系統為 CentOS7。

squid

squid 是一個 http 代理伺服器,它還可以做靜態資源的快取,這裡就簡單介紹它的代理功能。它可以代理 http 協議,但是 tcp/udp 的就不知道行不行了。不過沒關係,而且這裡只是對它略作介紹,畢竟它不是今天的重點。

閒話不多說,首先安裝:

yum install -y squid
複製程式碼

啟動並設定開機自啟:

# CentOS6
/etc/init.d/squid start
chkconfig squid on

# CentOS7
systemctl start squid
systemctl enable squid
複製程式碼

關閉防火牆和 selinux:

# CentOS6
/etc/init.d/iptables stop
setenforce 0

# CentOS7
systemctl stop firewalld
setenforce 0
複製程式碼

預設監聽埠為 3128,確保未被其他服務所監聽。OK,服務端就配置好了,現在客戶端就可以通過它來上網了。客戶端要怎麼配置呢?非常簡單,Linux 上只需要配置 http_proxy 這個環境變數即可。

你先登入一臺需要上網的 Linux 伺服器(確保它可以連線 squid 所在伺服器),執行如下命令(將 SERVER_IP 替換成 squid 所在伺服器 ip):

export http_proxy=SERVER_IP:3128
export https_proxy=SERVER_IP:3128
複製程式碼

配置兩個環境變數,一個是 http 協議,一個是 https 協議,表示在當前 shell 環境下面啟動的所有服務、命令等傳送的 http/https 請求都轉發給代理伺服器,由代理伺服器幫忙請求。然後就可以測試了:

curl www.qq.com
複製程式碼

會返回 302,表示連線成功。

squid 配置檔案為 /etc/squid/squid.conf,從中可以看到這樣的內容:

acl localnet src 10.0.0.0/8     # RFC1918 possible internal network
acl localnet src 172.16.0.0/12  # RFC1918 possible internal network
acl localnet src 192.168.0.0/16 # RFC1918 possible internal network
acl localnet src fc00::/7       # RFC 4193 local private network range
acl localnet src fe80::/10      # RFC 4291 link-local (directly plugged) machines

http_access allow localnet
複製程式碼

從中可以看出,三個基本的內網網段都可以通過代理上網。如果有其他需求,可以自行修改,改完後記得重啟 squid 服務。OK,關於 squid 的內容就這麼多了,它畢竟不是專門做代理上網的軟體,只是它安裝方便、使用簡單、知名度廣、資格夠老所以就順便提提,重點還是 goproxy。

goproxy

goproxy 是國內作者開發的開源的、專業的代理軟體。作者的簡介是:golang 實現的高效能 http、https、websocket、tcp、防汙染 DNS、socks5 代理伺服器,支援內網穿透、鏈式代理、通訊加密、智慧 HTTP/SOCKS5 代理、域名黑白名單、跨平臺、KCP 協議支援、整合外部 API。

單從代理這塊,它可以實現了 squid 做不到的功能有:

  • 全平臺:windows/macos/linux 都一網打盡;
  • 限速:這個功能雖然不起眼,但是非常有用,尤其針對大量請求比如映象站同步時非常有用,你不能因為你搞同步就把頻寬打滿了吧,那你公司還開不開了?
  • tcp 代理:光是 http 代理並不能滿足需求,比如郵件/smtp、ftp 等都不是 http;
  • udp 代理:這就更不用說了,dns、ntp 走的都是 udp,沒它不行。tcp+udp 基本上就滿足了所有應用的代理需求了;
  • 多級代理:這個看起來好像也用不著,但是你想要生產環境實現科學上網就得靠它。
  • https:這個並不是代理 https 協議啊,而是這個代理到另一個代理伺服器之間的通訊內容都是通過 ssl 加密的。一般用不上,使用它和多級代理可以實現生產環境科學上網。

安裝

它的安裝非常簡單,因為是 go 語言寫的,它只依賴 glibc 而不限 Linux 發行版。所以只要 glibc 版本夠了,任何 Linux 發行版使用的二進位制檔案都一樣,當然 windows 和 macos 由於作業系統不一樣,版本肯定也是不一樣的。這裡只針對 Linux,如果有想法也可以在其他作業系統上執行,用法都一樣。

作者提供了一鍵安裝的指令碼,但是需要你伺服器可以科學上網才行,如果可以你可以直接使用:

curl -L https://raw.githubusercontent.com/snail007/goproxy/master/install_auto.sh | bash
複製程式碼

不行的話,你就只能手動下載安裝了。首先來到專案主頁,點選 release,選擇最上面也就是最新版本,點選 linux-amd64 進行下載。注意是 amd 而不是 arm,它們的 CPU 架構不同,一般伺服器都是 x86 也是 amd 架構,其他 Linux 架構不用管。如果 32 位系統選擇 32 位即可。

http代理伺服器

http代理伺服器

如果是 MacOS 選擇 darwin,windows 就選 windows,這些就不多提了。下載完成後隨便放在哪個目錄,並在當前目錄下執行下面的命令即可:

tar zxvf proxy-linux-amd64.tar.gz
cp proxy /usr/bin/
chmod +x /usr/bin/proxy
if [ ! -e /etc/proxy ]; then
    mkdir /etc/proxy
    cp blocked /etc/proxy
    cp direct  /etc/proxy
fi

if [ ! -e /etc/proxy/proxy.crt ]; then
    cd /etc/proxy/
    proxy keygen -C proxy >/dev/null 2>&1
fi
rm -rf /tmp/proxy
echo "install done"
複製程式碼

不排除這個指令碼不再適用於以後的版本,一切還是以官方文件為準,反正都有中文,看著也不費事。安裝完成後 proxy 命令就可以使用了(確保系統上之前沒有這個命令),代理服務就通過這個命令啟動,輸入 proxy help 就能看出這個命令的幫助資訊了。

啟動

官方文件說的還比較詳細,我們就拿 http 代理舉例,相信看完之後,tcp/udp 等代理你也會了。

首先啟動 http 代理服務:

/usr/bin/proxy http -t tcp -p :2121
複製程式碼

這就啟動服務,並且監聽在 tcp 2121 埠了,服務端也就完成了。客戶端的使用方式和 squid 一樣,只不過要將 3128 埠換成這裡的 2121。

限速

到這裡代理伺服器的就已經完成,下面提到的都是一些擴充套件的內容了。限速非常簡單,使用 -l 選項指定即可,比如 100K 2M 等,0 意味著無限制。作者舉例使用了 1.5M,大家不要這麼加 .,使用 1M 或者 2M 代替,不然會報錯。

/usr/bin/proxy http -t tcp -p :2121 -l 2M
複製程式碼

表示將速度限制在 2MB/s,可以使用 dstat 命令進行驗證。

認證

goproxy 啟動之後,預設什麼人都可以使用它進行代理,如果你覺得不安全,可以使用 basic 認證。雖然 basic 認證不安全,抓包之後 base64 解碼下就能拿到使用者名稱密碼,但是聊勝無於。使用方式為通過 -a 指定使用者名稱和密碼,文件在這裡

當然這種方式只能針對 http 代理,因為只有 http 協議才支援 basic 認證。

service 檔案

上面的啟動方式服務會執行在前臺,雖然可以使用 & 可以將之放入後臺,但是我們完全可以使用 systemd 對其進行管理。CentOS7 使用 systemd 代替了 init,因此我們可以使用 systemd 來管理 proxy 的啟動和停止。

首先建立 service 檔案:

# vim /etc/systemd/system/proxy.service
[Unit]
After=network.target

[Service]
ExecStart=/usr/bin/proxy http -t tcp -p :2121 -l 2M

[Install]
WantedBy=multi-user.target
複製程式碼

然後啟動:

systemctl daemon-reload
systemctl start proxy
systemctl enable proxy
複製程式碼

systemd 會自動將服務置於後臺執行,proxy 輸出的日誌可以這個檢視:

journalctl -u proxy
複製程式碼

journalctl 命令還有很多用法,這裡就不多提了。

goproxy 的用法就這麼多了,至於科學上網這裡就不多提了,反正很簡單,只需要注意兩個代理伺服器之間要使用 ssl 加密。

Linux 客戶端使用

伺服器搭建完成之後,那就要在客戶端使用起來了。前面講到了使用 http_proxy/https_proxy 進行代理上網的方式,這也是最常用的方式,不過它也有些注意事項。

我們使用 ssh 登入到伺服器之後,就相當於開啟了一個 shell,我們在當前 shell 下設定的環境變數 export http_proxy=SERVER_IP:3128 只對當前 shell 有效,在其他 shell 下是沒有效果的。因此當你要啟動一個要進行 http 代理的服務之前,可以先使用 echo $http_proxy 檢視環境變數是否設定,只有設定了服務才能載入到。

不建議將其寫入到 /etc/profile /etc/bashrc 等這樣的檔案讓其永遠生效,因為難保伺服器上還會跑其他應用,而這個應用不需要走代理。真遇到這樣的情況,排查起來也蠻費勁的。

最好的解決辦法是使用一個指令碼來封裝服務的啟動命令,將環境變數配置到指令碼中,這樣就不會產生干擾。

與 http_proxy 對應的是 no_proxy,我們雖然可以使用不同的 shell 來區別哪些應用使用代理,哪些不使用。但是難免會有這麼一個需求:一個應用會發出多個 http 請求,其中有一個不能使用代理,其他請求要使用代理。面對這樣的情況,只能使用 no_proxy 這個環境變數了,它用來排除不使用代理請求的 ip。它的是一個一堆用逗號分隔的 ip 列表,不能使用網段,不能使用域名。

比如我們訪問 10.0.0.1 和 10.2.2.2 不使用代理,就可以這麼做:

export no_proxy="10.0.0.1,10.2.2.2"
複製程式碼

有些應用啟動時不會載入 http_proxy 這樣的環境變數(比如 jenkins、Maven),即使你配置了也沒用。面對這樣的情況不要慌,服務本身是會提供配置代理的方式的。比如 jenkins 會在外掛管理中提供,Maven 會通過配置檔案提供。

還有一點需要注意的是,使用 systemd 啟動的服務同樣不會載入系統環境變數,它本身和 shell 就沒啥關係。這時你就可以在 service 檔案中進行配置。

[Service]
Environment="https_proxy=SERVER_IP:2121"
複製程式碼

在 Service 下面這麼配置就行。

windows 客戶端

windows 上的軟體基本上都可以配置代理,設定裡面找找 http 代理就可以,輸入 ip 和埠、使用者名稱和密碼(如何設定了的話)。如果你想設定全域性代理,也就是系統級別的話,在 win10 上是在網路 -> 網路和 Internet -> 代理 -> 手動設定代理。和 Linux 一樣,有些軟體可能不吃這一套,你還得去軟體中設定。

個人使用者在 windows 上使用還是科學上網居多。

相關文章