终于,终于,时隔多年之后,我又开始用基于XXX来做文章的标题了!!!

前言

  正如之前的预告,这篇文章作为我博客建立的重头戏,和大家见面了!内容的话,是对我目前家里的个人网络环境的介绍。应该会重点介绍搭建的过程。虽说可能充满了槽点,但是我觉得还是很有趣的。在CHH里面看了那么多奇怪的方案,大多数可能更加注重的是性能。而我,财力有限,又没有大house,就只能在趣味性上下手了。
  这篇文章并不是教程,只是一篇流水账式的介绍,所以并不会详细的写一些细节内容,比如配置文件什么的。

可能是虚假的需求?

  一般来说,个人的网络环境没什么好搭建的,一根网线,一个无线路由器,接上,配置一个密码,就能涵盖几乎所有正常需求了。不过嘛,一方面,在我们这个不正常的环境下,正常需求肯定是不够的,另一方面,需求这种东西,怎么能说满足就能满足呢,这样人类还怎么进步呢,对吧!所以说,没有需求,也要造出一些奇奇怪怪的需求,哪怕是虚假的,这样才能推动个人,啊,不,不对,是人类的进步。

  回归正题,首先,第一点需求就是可以随时随地的访问一些无法访问的网站。想要随时随地,肯定就需要一个7*24小时运行的服务了。去年的时候,做过一些前置的试验,购买了一台树莓派,在上面部署了SS的服务。树莓派接上家里的路由器,路由器通过DMZ把相应的端口暴露在公网上。用了一段时间,倒是没什么大问题。不过显然有很多不爽的地方。首先,所有的终端都需要SS的客户端。虽然说现在几乎所有的平台和系统都有SS的客户端,但是像iOS就很难搞,还需要切换一个非国区的账号才行。这样其实非常麻烦,想一想,如果有妹子想要借你的网络来用一用,你还要手把手教一教怎么注册和切换一个非国区的账号,是不是就觉得很烦(小声 其实我可以)。第二点,频繁的连接和断开让人很是恼火。当我想要访问某些不能访问的网站时,我可能需要连接我的树莓派,当我访问国内网站的时候,为了更快的速度,我又需要断开连接。那当我想要同时访问的时候呢,就只能保持连接硬着头皮上了,来怀念1M拨号上网时的美好回忆。这让上网体验充满了割裂感。虽说一些SS的客户端或者浏览器有解决方案,但依然只支持特定的平台或者软件。总结下来的话,关于这一方面的需求,我的底线是:

  • 对于外部终端来说,不需要下载额外的软件。
  • 网络内部实现透明代理
  • 内置类似PAC的功能

  第二点需求,就是目前大家看到,正在支持这个博客的Web服务。只不过除了博客之外,我还需要一个GitLab,来放自己的code和跑各种CI。因为最早在规划的时候,GitHub的私人仓库还没有完全开放,并且也没有GitHub action什么的。GitLab可以自己Host,就很吸引人了。

  最后一点需求是常见的,必不可少的NAS。随时随地,都能看下好的片子还是很吸引人的。

搭建的过程

基本网络环境的搭建

  首先从第一点需求开始,想要符合上面三点要求的话,最合适的方案应该是软路由了。也就是说需要一个单独的硬件。不过考虑到后面其它两点需求以及我的财力,做了一个大胆的方案,把软路由装到虚拟机里面。毕竟总不能每一个需求整一台电脑。虽然最后结果看着很爽,但是也问题多多……这个就是后话了。虚拟化环境选择了Proxmox ve(下面简称PVE),开箱即用,很舒服。硬件选择了华擎的Deskmini h310+9900T,核心数足够多,够开好几个虚拟机,功耗35W也在可以接受的范围内。这个选择纯属个人喜好,其实应该还有其它更好的选择。因为华擎的这块主板只有一个网口,就又搞了一块USB的千兆网卡。不得不说,现在的东西却是越来越方便了,USB网卡都是免驱的。软路由系统的选择上,我看网上不少人推荐使用ikuai在加上一个OpenWRT的旁路由,有些不能理解,OpenWRT不是万能的吗。一开始让我用ikuai我是拒绝的,就搞了OpenWRT+OpenWRT的方案,一个充当主路由,一个充当旁路由,也就是开启透明代理的网关。可惜中间遇到了这样那样的奇怪问题,折腾了太久……不得不拾起了网友们的成熟方案😭。最终采用了ikuai主路由,OpenWRT旁路由的方案。方案画出来的话大概如下图所示:
3.1
  系统里有两张网卡,我们称网卡0和网卡1,装好第一个虚拟机ikuai之后,首先把两张网卡都桥接给ikuai,在ikuai中设置,1网卡设置为WAN口,设置好后连接光猫,0网口设置为LAN口,连接充当AP的无线路由器(因为这里不需要它的路由功能,所以记得也要连无线路由器的LAN口)。网段我选择了192.168.100.0/24这个网段。(我这个光猫没有破解,没有办法选择桥接模式,只能选择路由模式,占了192.168.1.0/24这个网段)当然,PVE自己本身的IP需要静态设置,设置大概如下:
3.2
其中192.168.100.1就是ikuai的IP,PVE的IP静态设置为了192.168.100.2。当然,为了方便,我把充当AP的无线路由器IP也设置成了192.168.100.3。注意,这个无线路由器现在只有交换功能,没有路由功能,其它设备,包括无线和有线设备,都连接在它上边。

  设置好主路由,网络的一切功能应该就正常了。可以接下来设置充当网关的旁路由,安装OpenWRT,只需要把LAN口桥接过去就好。同样为了方便,OpenWRT我给设置了静态的IP地址192.168.100.4。
3.3
因为这里OpenWRT只充当了网关的作用,所以DHCP什么的一类功能都关掉。在ikuai里面设置好DHCP服务器就好了,把网关指向OpenWRT,如下:
3.4
都设置好之后可以tracert试一试:
3.5
可以看到走得路径正好和我们设置的一样,先去了OpenWRT,再去了ikuai,再去了我的光猫,之后走出了家里的网络。另外,大家也可以看到我给家里的设备都增加了域名映射,这也是OpenWRT的内置功能之一,非常方便。
3.6

  现在就可以在OpenWRT上搞透明代理了。虽然我个人不喜欢v2ray本身,但是还是很喜欢他的客户端以及OpenWRT上的v2ray插件的。我使用的方案是SS+kcptun,具体可以参考这里:https://github.com/xtaci/kcptun 。结构简单来说就是下面这张图:
3.7
kcptun的客户端虽然本来也可以跑在OpenWRT里面,但是既然我们都搞虚拟化了,为了方便维护和管理,以及性能上的考虑,就不把kcptun的客户端放在OpenWRT里面了。新建一个单独的Debian虚拟机,作为主服务器,在里面安装Docker,kcptun客户端可以跑在Docker里面。这样维护起来就很轻松了。后期升级什么的也方便。
  这一套虽然看上去有点复杂,至少目前看起来还算稳定。我有一台Vultr美国的VPS,又在阿里云上买了一台香港的轻量服务器,所以一个月是2.5美刀+24人民币。两台服务器做负载均衡,美国路线的话YouTube 720P没有问题,香港路线的话1080P没有问题。总之感谢OpenWRT上的v2ray插件,透明代理和流量的自动分流都可以很轻松的设置。
  这一部分设置完成后,大概的结构如下图:
3.8

  到目前为止,在局域网环境之下,所有的设备应该都可以自由访问外网,无论是通过WiFi连接还是通过有线连接。可是还没有一个对外的服务。不过这个时候,对外服务的搭建就简单多了,我只需要在Server里面再部署一个兼容各个平台的VPN服务就行了。目前看起来,对于L2TP这样一种古老的协议来说,Windows,Android,iOS还有Mac OS都提供了比较好的支持,正好也有现成的Docker image。如果说像L2TP这样的协议部署在外网的话,那肯定是不能用,但是部署在国内的话,看起来就基本没什么限制了。也不应该有什么限制,毕竟对于小企业的话,这也是正常需求之一。所以上面那幅图里面就要再加一部分了。
3.9
VPN服务暴露在了Server的500和4500端口上,在ikuai中设置端口映射,映射到ikuai的相应端口上,再在光猫中设置端口映射,映射到公网IP的相应端口上。

Web服务的搭建

  其实在上一节中,主要的框架都已经搭好了,所有的Web服务只需要像kcptun一样,部署在Docker里面就好了。不过这样就有了一个问题,外界该如何访问这些服务。先前的VPN服务倒还好,因为有自己特定的端口,直接把相应的端口层层映射到公网IP上就好。但是Web服务只有标准的80/443端口(在网站地址后面带端口号的话实在是太丑了),如果部署多个Web服务的话,必然会冲突。解决方案也是有的,毕竟这也算是一个常见的问题,比较合乎我心意的是通过host来进行反向代理。也就是说虽然不同的url解析到了同样的地址,但是作为入口的反向代理服务会根据访问的url来将请求转发到不同的Web服务上面,这样就解决了冲突。本来是想用Nginx来实现的,但是写配置文件实在麻烦。正好之前在浏览GitHub看到了一个项目,Traefix,配置简单,提供官方Docker image,可以完美解决我的问题。所以在Server上部署了Traefik,绑定80和443端口,暴露在公网上。而其它Web服务绑定其它端口,不需要暴露在外。以后每增加一个Web服务,就只要在Traefik里面增加一段配置,将相应url的访问转发到对应的端口上。对于Gitlab,官方有提供使用Docker部署的教程,而对于博客,我自己手动制作了Docker镜像。除了上面两个,我还部署了Portainer,一个可以方便管理Docker的Web服务:
3.10
  至此,是不是觉得很完美。但是有一个致命的问题被忽略了,网站没有备案的话是无法上线的!而且,我现在这样子也是没有办法备案的。在非专用的线路上开通Web服务本身就是不合规的,更不要说给一个不合规的东西备案。这几乎是一个无解的问题。想来想去,最后想到了一个折衷方案。对于在非大陆地区的Web服务来说,是不需要备案的(虽然有被墙的风险)。如果非要把服务部署在家里还不想开放80/443端口的话,就只能搞一台非大陆地区的服务器,通过内网穿透的方式让服务在境外“上线”了。结果就是我又搞了一台阿里云香港的轻量服务器(成本+24元/月)……好在主要几个地区测试的结果来看,延迟还可以接受,尤其是珠三角地区,基本和访问大陆网站的速度一样快。因为之前有朋友推荐过frp,看下来实现内网穿透也很方便,就又在Server里部署了frp。这样,家里就没有任何Web服务暴露在公网环境当中了,所有外部的Web请求都会走frp。网络结构变的越来越复杂了:
3.11
  关于Web服务,最后还有一点想说的就是TLS证书的问题。Gitlab比较好,把let’s encrypt整合进了自己的Docker image。自己的博客的话,也是用得let’s encrypt。本来想搞一个通配证书的,不过看到普通证书有方便使用的certbot,一键部署,一键刷新。那就没必要折腾自己了。

NAS的搭建

  相比与上面提到的两项服务,NAS其实应该是更常见的一种加用服务。如果说家里有多台设备,想在任何时间都可以访问同样的资源,那最好的做法就是把资源存储在服务器里面,然后通过网络进行访问,而不是在每一个终端里复制一份。

  传统上,一般有两种解决方案。对于需求比较简单的轻量用户来说,许多路由器就可以充当NAS,只需要在USB口上接上外接硬盘就可以。对于需求比较复杂,负载比较重的用户来说,会推荐使用单独的硬件解决方案。比如说在国内很流行的群晖,他们就出售包括硬件,软件在内的一整套解决方案。我的情况的话,大致介于两者之间。一方面,我希望我的NAS可以支持多种文件系统(NTFS、exFAT、ext4等),支持多种网络存储协议(Samba、FTP、NFS等),支持常规下载任务和BT下载任务,另一方面,因为只有我一个人使用,存储量,网络负载等都很小。所以还是采用了折衷的解决方案,像软路由那样,搞一个软NAS。其实就是再在PVE里面开一个虚拟机,并且把这块主板的两个SATA口和一个SD卡槽直通到这个虚拟机里面。系统上,在考察之后,选择了同样是基于Debian的openmediavault(后面简称OMV)。虽然黑群晖也很流行,但是毕竟是“黑”群晖,就像是黑苹果一样,不仅不能升级,还会遇到各种各样的问题,况且用起来还不怎么自由。图里就要再加上一部分了:
3.12
  因为是基于Debian,大部分内容都可以DIY,比如对NTFS和对exFAT的支持等。不过好歹OMV也是专门为NAS设计的,大部分功能还是有的,比如Samba,FTP,NFS等。下载也有基于Aria2和Transmission的插件,正好前不久度盘还推出了Linux版,加上前面两个插件基本上涵盖了所有的下载需求。(百度不是搞限速吗,那我就7*24小时给你挂着,哈哈)主板只有两个SATA口,就装了两块2T的硬盘。因为目前7nm的2.5寸机械硬盘最大就是2T的。固态硬盘的话倒是有4T的,可是实在是太贵太贵,并不适合做仓库盘。

其他一些杂项

  在上面几节中,提到了Gitlab的CI。除了Web服务之外,CI还需要专门的测试机,这个肯定也只能用虚拟机来搞了。好在Gitlab的CI支持在Docker里面跑任务,直接跑在真实的机子上和虚拟机里面倒没太大的区别。
  关于CI,后面我可能会单独写一篇文章来介绍。这次主要介绍的还是网络和硬件的架构。为了涵盖尽可能多的平台,总共创建了3个虚拟机,分别对应Linux,Windows,macOS。其中,Linux和Windows因为都支持Container,所以任务都是跑在Docker里面的。macOS比较特殊,本身它是不支持在Linux上虚拟化的。好在PVE底层是KVM,而有人专门做了KVM虚拟化macOS的方案,就被我拿来用了。现在这套方案甚至被做成了一键脚本。效果还是非常好的,系统升级也没有问题。可惜的是因为限制死了虚拟CPU类型,所以不支持嵌套虚拟化。再加上macOS不支持原生Container(macOS上的Container实际上是Linux Container),所以macOS上的任务只能直接跑在虚拟机上面了。期待后面Docker可以推出macOS的原生Container。除了上面那三个虚拟机,我还装了一台树莓派,用来支持ARM架构,系统当然是Linux。起初我是打算用QEMU来起ARM和MIPS的模拟器的,可惜怎么配都无法成功,就放弃了。最后还是用了廉价的ARM硬件来涵盖ARM平台。(性能实在太差了,还不如一个单核的x86虚拟机……)后期如果ARM版的Windows持续完善的话,比如有了本地的C++编译器,不排除再搞一台ARM设备来跑Windows。当然,MIPS也是一样,只要有合适的廉价开发板,也可以搞一台。加上这些东西之后,基本就是最后的成品了:
3.13

结语

  这篇文章基本上真实的记录了我整个搭建的过程,虽然顺序可能会稍微有点差别。说实话,整一套系统除了一次大故障之外,稳定运行到今天我还是很自豪的。因为前期经过了非常多的思考和验证,即使整个系统已经如此复杂,但是整体维护起来还算简单。唯独麻烦的是起步,尤其是在虚拟机里面装软路由这一步,相当有挑战,以至于我不太想再做第二次。
  因为条件和资源实在有限,我的需求又太多,最后不知不觉就变成了这样。回头在来看,有些设计还是非常蠢的。唯一的一次故障出在过年,家里的服务器突然连不上了,我在外地竟然束手无策,一度怀疑是不是停电了。后来回来才发现是机子的系统盘满了……这个时候就感受到把所有的东西都放在一台机器里的弊端了,尤其是我连整个网络的核心,路由器都装在了虚拟机里面,一旦作为host的PVE挂了,那所有东西都挂了。同时,我也深深感受到了IPMI的重要性,如果这个时候我的主板带IPMI,并且还可以访问的话,那我就可以远程解决这个问题了。
  后面这个结构会调整吗,当然还是会的。在体验了一把各种玩法之后,我也会逐渐回归理性……啊,不对,好像用理性这个词不太好,应该会回归合理方案。在条件允许的情况下,把路由器还有NAS都独立出来,不能再搞这样ALL in One的方案了。
  不过,前提是,我得先努力有一个大house。😂