Docker竟然还能这么玩?商业级4G代理搭建实战!

Posted nightteam

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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 设备。

技术图片

不同 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,领域涵盖爬虫、深度学习、服务研发、对象存储等。团队非正亦非邪,只做认为对的事情,请大家小心。

技术图片

以上是关于Docker竟然还能这么玩?商业级4G代理搭建实战!的主要内容,如果未能解决你的问题,请参考以下文章

硬件断点还能这么玩?

CRUD 还能这么玩?

没想到 Hash 冲突还能这么玩,你的服务中招了吗?

当孩子遇上卢行知教育,STEAM智能机器人探索班还能这么玩!

原来还能这么玩

安全运维-Nginx服务器就该这么玩~