爬蟲代理大廠都封得差不多了,了解下商業級 4G 代理搭建方法吧!

  • 2019 年 10 月 5 日
  • 筆記

基本思路

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

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

  1. 調用網卡撥號,撥號成功後會創建一個虛擬網卡。(正常情況下使用這個虛擬網卡就能上網了)
  1. 在多網卡的情況下,重複第一步,會得到多個虛擬網卡。
  1. 啟動代理伺服器,使其使用虛擬網卡作為出網網卡,並使用接入內網的實體網卡作為入網網卡。

使用起來差不多是這樣的

但是呢,有個問題,根據我之前的測試結果來看,目前在 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 的情況。

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