Docker竟然還能這麼玩?商業級4G代理搭建實戰!

時間過得真快,距離這個系列的上一篇文章《商業級4G代理搭建指南【準備篇】》發佈的時間已經過了兩個星期了,上個星期由於各種瑣事纏身,週二開始就沒空寫文章了,所以就咕咕咕了。

那麼在準備篇中,我們瞭解了一下搭建 4G 代理所需要的軟硬件,也知道了各種選擇的優劣勢。現在,我們就可以開始實際搭建了,相信大家也是期待已久了。


基本思路

從這篇文章的標題中我們可以看出,這一次的搭建方案主要用到的是 Docker,你可能會很好奇,Docker 跟搭建 4G 代理有什麼關係嗎?

嗯,關係很大,我們把整件事情梳理一下,先來看看搭建 4G 代理時的基本流程:

  1. 調用網卡撥號,撥號成功後會創建一個虛擬網卡。(正常情況下使用這個虛擬網卡就能上網了)

  2. 在多網卡的情況下,重複第一步,會得到多個虛擬網卡。

  3. 啓動代理服務器,使其使用虛擬網卡作爲出網網卡,並使用接入內網的實體網卡作爲入網網卡。

    使用起來差不多是這樣的

但是呢,有個問題,根據我之前的測試結果來看,目前在 Linux 環境下還沒有一個 HTTP 代理服務器是可以做到分別指定出網網卡和入網網卡的,嗯...這就很麻煩了,因爲如果我們無法這麼做的話,就會出現類似於下面這樣的問題:

  1. 出網和入網都在虛擬網卡上,使用代理服務器必須要走公網訪問。
  2. 入網爲實體網卡,但出網被代理服務器鎖定爲了某一個,無法利用到多網卡。

嗯...那麼不用 HTTP 代理服務器,用那些經常被用來做一些騷操作的 Socks5 代理服務器呢?如果可以指定網卡的話,再用像 Privoxy 之類的工具把 Socks5 代理轉成 HTTP 代理就好了。(某知名扶牆軟件的 Windows 版本就是這麼轉的 HTTP 代理)

在經過一番嘗試後,我發現雖然有些 Socks5 代理服務器的文檔中是說可以指定網卡,但按照說明操作後,似乎並不能直接做到我想要的效果(要麼還是鎖定在某一個上面、要麼上不了網),所以還是存在一些問題的。可能是需要配合路由表設置來進行操作吧,不過我對網絡工程的瞭解不怎麼深,搞了幾天也沒搞出來,於是乎還得想想別的辦法。

這時候,我想到了一個東西——Docker,它可以用來解決這個問題!

因爲 Docker 容器被創建後,不管外界的網卡有多少個,容器內部的網卡都只會有一個Docker自己的虛擬網卡(容器間通信用的)和一個本地環回接口(不用管它),而且我們在容器內進行撥號操作時,產生的那個新的虛擬網卡也不會影響到外界或其他容器,這樣的話,代理服務器就不需要指定網卡了,直接啓動就能跑!

那麼現在整個流程就跑通了,進入實際操作環節看看吧!


系統方面

這個 Docker 版的搭建方式,系統方面的選擇很多,由於我使用的樣例設備是樹莓派,所以這裏就選擇使用了 Raspbian(樹莓派專屬版 Debian)。如果你使用的是其他設備的話,直接選擇一個自己常用的系統就好。

那麼準備好之後的第一步當然是先下載並安裝 Docker,這裏我直接使用 Docker 官方提供的一鍵安裝腳本來進行安裝:

curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh
# 出自官方文檔:https://docs.docker.com/install/linux/docker-ce/debian/#install-using-the-convenience-script

這個一鍵安裝腳本理論上來講所有 Linux 發行版都可以使用,畢竟已經出來很長時間了,如果不行的話請自行使用搜索引擎查找相關資料。

裝好 Docker 之後,你有兩個選擇:

  1. 進入體驗模式,瞭解一下具體操作細節是怎麼樣的。
  2. 不看這一段,翻到本文最下方直接使用我寫好的輪子。

啓動容器

體驗的話,我們就直接這麼啓動一個 Docker 容器吧,執行以下命令:

sudo docker run -it --rm --privileged -p 3128:3128 ubuntu:18.04 bash
上面這條命令的意思是,啓動一個內部系統爲 Ubuntu18.04 的容器,並進入容器內部的 Shell 執行 bash 命令,如果退出 bash 就自動銷燬容器;然後映射容器內的端口3128到外界,映射出來的外界端口也是3128;最後 privileged 參數是開啓特權模式,用於將網卡設備映射進容器內。

如果下載鏡像很慢的話,可以搜一下“Docker 加速器”,也可以直接扶牆。

測試一下網卡是否正常

進入容器內部後,我們可以執行一下 ls /dev/ttyUSB* 看一下網卡有沒有正常被識別出來(在容器外也是一樣的,因爲開了特權模式),如果是和我買的同一款 4G 網卡的話,在只插入一張網卡的情況下你會看到4個 ttyUSB 設備。

插入了三張網卡的樣子,一共12個 ttyUSB 設備

不同 4G 網卡和硬件組合可能會有差異,請以實際情況爲準。

如果你可以看到4✖4G網卡個數個 ttyUSB 設備的話,就說明沒有問題,可以開始下一步了。

撥號上網

接下來要做的就是撥號了,撥號方面可以選擇使用 Wvdial 這種工具,也可以選擇使用像 Fanconn 這樣的商家提供的撥號腳本(直接調用 PPPD),使用起來的效果會有一些區別。如果商家沒有提供撥號腳本的話,就用 Wvdial 吧,它能自動生成配置,上手即用。

我這邊的話,由於 Fanconn 的技術人員直接提供了個撥號腳本,那我就用這個腳本了,Wvdial 的文檔網上有很多很詳盡的,這裏就不再多提,需要的朋友自行搜索即可。

如果你用的是 Fanconn 的這個撥號腳本(怎麼弄進容器內就不用我說了吧?),那麼直接在 apt install ppp 安裝好撥號工具之後,用 chmod +x quectel-pppd.sh 給撥號腳本加個運行權限,然後 ./quectel-pppd.sh /dev/ttyUSB3 即可。

撥號時使用的 /dev/ttyUSB3 是指 4G 網卡的第四個通信端口,文檔中的解釋爲:ttyUSB3→For PPP connections or AT command communication,翻譯一下就是用於 PPP 連接或 AT 命令通信。

撥號之後用 ifconfig 之類的工具即可看到類似下圖中的狀態:

可以看到,如前文所述,現在有三個網卡,一個是 Docker 自己的、一個是本地環回接口(這個不用管)、一個是撥號產生的虛擬網卡。

如果不是在 Docker 容器內使用的話,還會有個 wwan0(或其他名字),那個是 4G 網卡本體。

測試是否能正常上網

現在如果你用 curl 的 --interface 參數指定虛擬網卡進行請求的話(如:curl --interface ppp0 https://ip.cn),是已經可以請求成功的了,IP 也會是你所使用的 SIM 卡對應的運營商分配的。

由於 Docker 的鏡像通常都是極度精簡的,所以 Ubuntu 鏡像裏並沒有預裝像 net-tools、iputils-ping、vim、curl 之類的這些包,需要自行安裝。所以如果你發現 ifconfig、ping、curl、vim 用不了,不要驚慌,這是正常現象,執行 apt install 包名 命令安裝即可。

如果你無法直接請求成功的話,就可能是 DNS 解析出問題了,可以嘗試 ping 一個公網 IP(如:ping 1.1.1.1)和一個域名(如:ping ip.cn),如果 IP 能 ping 通但域名會報 DNS 解析失敗的話,就可以確認是 DNS 設置問題了。

4G 撥號時如果出現 DNS 設置問題,通常是因爲撥號工具沒有正常地將運營商返回的 DNS 服務器設置寫入到配置中,我們可以手動配置一下(你要強制指定某一個 DNS 也可以):

# 以下爲阿里雲的公共DNS
echo 'nameserver 223.5.5.5' >> /etc/resolv.conf
echo 'nameserver 223.6.6.6' >> /etc/resolv.conf
在 Docker 容器中,這個 /etc/resolv.conf 文件可能還會有兩條內容,是容器本身所需要的,建議不要刪除/覆蓋,否則會出現容器間無法使用容器名互相通信的情況。

啓動代理服務器

那麼在測試撥號後確實可以通過 4G 網卡上網了之後,我們就可以把代理服務器啓動了,這裏我使用的是 TinyProxy。

測試發現,Squid 對資源的佔用更大一些,不利於多網卡情況下的使用,會影響到 4G 網卡的數量上限。

apt install tinyproxy 一波,然後 vim /etc/tinyproxy/tinyproxy.conf 修改一下配置。

要修改的配置主要有:

  • Port 配置項改爲3128,因爲我們前面映射出來的端口是3128。
  • Listen 配置項改爲0.0.0.0,因爲我們需要在其他設備上使用這個代理服務器。
  • Allow 配置項註釋掉或改爲0.0.0.0/0,默認的127.0.0.1會導致其他設備無法訪問。

改完之後保存一波,然後就可以直接執行 tinyproxy 啓動了...嗎?

等等,還有一個操作要做!那就是將默認路由指向到虛擬網卡上,很簡單,執行以下命令即可:

route del -net 0.0.0.0 eth0
route add -net 0.0.0.0 ppp0

這兩條命令的意思是:先將默認的、指向 eth0 這個網卡的上網路由刪除,然後添加一個同樣的、指向 ppp0 這個網卡的路由。

改完默認路由後的效果就是,即使你不使用 curl 的 --interface 參數,也能直接使用 4G 網卡上網了。

如果沒有改默認路由的話,在不指定網卡的情況下,4G 網卡並不會被使用到,因爲默認路由指向的是 Docker 自身的虛擬網卡,那個網卡通向你原本的內網環境。也就是說,IP 不會變!

那麼現在,你可以執行 tinyproxy 啓動代理服務器了。

測試代理服務器

好了,代理服務器應該已經正常啓動了,現在我們可以在另一個設備上嘗試連接那個容器中的代理服務器,看看是否能正常通過它使用 4G 網卡上網。

例如我這裏樹莓派分配到的IP是:192.168.137.66,那麼我就可以用這樣的 curl 命令或 Python 代碼進行測試:

curl:

curl "https://ip.cn"
curl -x "192.168.137.66:3128" "https://ip.cn"

Python:

import requests
resp = requests.get("https://ip.cn", proxies={"https": "http://192.168.137.66:3128"})
no_proxy_resp = requests.get("https://ip.cn")
print(resp.text)
print(no_proxy_resp.text)

測試出來的結果應該與前面在容器內部測試時的一致,在使用代理後 IP 就變成了運營商分配的基站 IP。

更換 IP

那麼最核心的問題來了,怎麼更換 IP 呢?

其實和使用那些撥號 VPS 架設代理服務器一樣,我們只需要重新撥個號就能換 IP 了,直接 kill 掉 pppd 進程就可以讓它斷開撥號,斷開後重新執行一遍撥號腳本就是重新撥號了。

斷開撥號方面 Fanconn 的技術人員也提供了一個腳本,同樣在 chmod +x quectel-ppp-kill 賦予運行權限之後,執行 ./quectel-ppp-kill 就可以了。

但需要注意的是,蜂窩網絡的撥號在斷開後,IP 仍然會保留一段時間(具體多久不清楚,可能跟連接的基站也有關係),所以我們需要強制性地讓網卡重新搜網。

冷門小知識:手機上開啓關閉飛行模式的效果就是重新搜網,通常只是關閉“移動數據”的話,效果是與斷開撥號一致的。

怎麼做呢?很簡單,就兩行命令:

AT+CFUN=0
AT+CFUN=1

但注意哦,這是 AT 命令,不是 Linux 下的 Shell 命令,AT 命令是一種調制解調器命令語言,我們如果需要將它執行起來,需要這麼做:

echo "AT+CFUN=0" > /dev/ttyUSB2
# 中間間隔1秒左右
echo "AT+CFUN=1" > /dev/ttyUSB2
這裏使用的 /dev/ttyUSB2 是指 4G 網卡的第三個通信端口,文檔中的解釋爲:ttyUSB2→For AT command communication,與第四個通信端口類似,只是它不能用於 PPP 連接、只能用於 AT 命令通信而已。

不同樣使用第四個通信端口的原因是那個端口有被佔用的可能性,直接區分開最穩妥,本來網卡也就是提供了兩個 AT 命令通信渠道的。

在使網卡重新搜網後的幾秒至十幾/幾十秒內的時間裏,你無法正常撥號,需要等待它初始化完成後纔可以撥號成功,具體等待時間以信號強度爲準,我測試的時候通常5秒以內就可以了。

所以如果你在斷開後一直撥號失敗,不妨過一會兒再試。


總結

那麼現在操作流程也跑通了,我們也瞭解到了整個的內部細節,最後要做的就是把每個網卡都分別分配一個容器,這樣我們就能實現文章開頭所提到的——“使用虛擬網卡作爲出網網卡,並使用接入內網的實體網卡作爲入網網卡”的效果了。

實際操作起來的話,就是把指定網卡的部分給配置化,然後在啓動容器的時候傳入就好了,使用 Docker 的容器環境變量相關設置可以很輕鬆地實現這個功能。

最後,我們可以以這個思路,構建一個 docker-compose 模板,模板的核心內容一是做個簡易的4G網卡容器集羣,二是啓動個 Squid,用來聚合代理服務器,這樣我們使用的時候只需要指定一個代理服務器就能隨機更換了,操作起來更加方便。


好了,上面就是 Docker 版搭建方式的思路和整個的搭建流程,如果你懶得看的話,直接用我寫好的輪子也是可以的,只需要發送消息【Docker版4G代理】到公衆號【NightTeam】即可。

評價

最後的最後,我給這個搭建方式打個評價吧。

這個搭建方式並不完美,因爲變量太多,而且很多地方肯定不如系統級原生支持的那麼穩定,長期使用可能會出現各種奇奇怪怪的問題。

然後 Docker 的資源佔用其實挺高的,會浪費相當多的內存在啓動容器上,如果只是兩三個網卡還好,如果數量大一點的話,像樹莓派2B 這種小內存的設備根本就扛不住。

另外代理服務器本身對資源的消耗也是比較高的,高頻調用下對樹莓派2B 的小 CPU 壓力還是蠻大的,即使我對它的 CPU 進行了超頻,在併發測試時也還是會出現輕鬆打滿 CPU 的情況。

但是!截止目前,我還有兩種基於路由器系統的搭建方案沒寫出來!所以...敬請期待後續的其他搭建方案(斜眼笑)。


文章作者:「夜幕團隊 NightTeam」 - Loco

夜幕團隊成立於 2019 年,團隊包括崔慶才、周子淇、陳祥安、唐軼飛、馮威、蔡晉、戴煌金、張冶青和韋世東。

涉獵的編程語言包括但不限於 Python、Rust、C++、Go,領域涵蓋爬蟲、深度學習、服務研發、對象存儲等。團隊非正亦非邪,只做認爲對的事情,請大家小心。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章