
引言
大约是2020年的时候,尚在就读大学的笔者就有了购买NAS的想法。教育网内有许多出名的PT,比如当年笔者在玩的西工大蒲公英及东北大学六维空间。而玩PT需要长期的保种以及大量的存储空间,这种需求催生了笔者购买NAS或者说一台服务器的需求。由于笔者是一个影音爱好者,偏爱各种高质量的电影及连续剧,爱优腾哔甚至是奈迪H疯都俨然无法满足笔者的需要。即使笔者由于客观原因,在2021年~2022年间尝试短暂地将整个观影动作切换到流媒体上,但在体验了国内外各大流媒体服务器后,笔者还是决定回归线下,将观影依赖在本地的设备上。这使得笔者于2022年开始真正购入NAS——或是说家用服务器,并在2年内逐步将这套家庭网络架构及服务器配置设计升级到现在的规模。
笔者最开始使用的是海康威视MAGE20双盘位NAS,这款机器本身是ARM机器,虽然内置了百度网盘和迅雷下载等功能,但显然无法满足笔者架设影音库的需求。为了实现存储以外的高阶功能,笔者额外搭配了联想ThinkCentre M73作为服务器使用。通过ESXi实现虚拟化后,笔者在里面安装了一个Debian的Linux服务器承载Docker服务,并安装了Jellyfin、qBittorrent等服务,同时安装OpenWRT作为旁路网关。
M73小主机使用的是酷睿4代的低压版处理器,性能只能勉强支撑起旁路网关和Jellyfin的基本功能,孱弱的集成显卡无法为Jellyfin服务提供硬解。这套系统使用一年后,M73小主机的硬盘突然挂掉。在这机缘巧合下,笔者换了倍控N5105小主机,并将Hypervisor平台更换成了PVE。笔者当时有个错误认知,认为CPU自带的核心显卡能随着CPU的虚拟化而虚拟化至不同的VM内,但后来才意识到CPU自带的显卡尽管与CPU刻在同一块芯片上,但结构上是完全独立的设备。得益于PVE的LXC容器功能,无需将CPU的核显虚拟化即可在Docker内调用核显,尽管LXC不是完全虚拟化,但从实际使用而言确实比KVM轻量而快速。
毕业后购入威联通TS-464C四盘位,后来陆续购买机柜并升级至现在的配置,各设备也逐渐升级更换成了可以上机架的款式,且架构整体从原先“存、算网分离”逐步演化成了现在的“存、算、网分离”。
硬件选型
网络架构基本思想是存、算、网分离,三个功能各有专用硬件,并通过虚拟化实现具体功能:
存储:QNAP TS-464C,老牌NAS厂威联通4盘位成品,从老设备迁移过来,之后陆续购买4块HC550 16T,只运行存储功能和PBS备份;
网络:Fisusen-J6421,标准1U高度小主机性能足够,跑若干个网络相关VM不在话下。如果不强求算网分离甚至可以跑下面的一些内部服务;
计算:i7-13700K,核心多,配合PVE在Web页面可以绑核,控制VM在小核和大核内跑很舒服,64G内存跑VM基本已经足够,安装显卡和多个SSD供直通。该机是从电脑城奸商配的DIY主机,使用标准4U机箱放托盘上;
交换机:杂牌的二层网管交换机,8电口2.5G+1光口10G,10G光口曾插猫棒用于电信宽带,后撤回用电信光猫;
WiFi:小米CR6608,魔改刷了爱快的。原本内网使用爱快VM做主路由配合该WiFi进行统一热点管理,现配合OpenWRT单独作为无线交换机使用。爱快的系统支持VLAN绑定到不同SSID,是少数支持VLAN绑定不同SSID功能的家用路由器系统,通过这个才实现多个网段发射不同WiFi。
网络规划
不同网段的配置,四个网段分别实现不同的业务功能:
- 服务器与管理网段:192.168.31.0/24(31段)
- 个人上网与配置网段:192.168.32.0/24(32段)
- 物联网设备专用网段:172.16.0.0/24(172段)
- 访客网段:10.10.20.0/24(10段)
通过杂牌二层网管交换机可以很轻松地划分VLAN。得益于网络功能虚拟化的缘故,来自交换机的Trunk数据进入各虚拟化宿主机时,可以轻松在宿主机系统配置虚拟交换机的方式Untag数据包,并转换为多个单独的Access端口虚拟交换机连接到各个VM的多个虚拟网卡内,在VM内就无需再配置繁杂的VLAN和拔插网线,便于VM快速接入各网段。
网络架构中主路由网关为VM,主路由的VM直通三个网口,分别接入电信WAN、移动WAN和内网LAN。内网LAN通过Trunk连接到二层网管交换机内,以单臂路由实现VLAN进行网段划分。主路由同时承担防火墙功能。配置DNS服务指向各VM,内网的服务全部通过域名访问。同时通过NGINX UI内网服务反代。而在外网的服务则使用Lucky,其同时支持反代、DDNS、Socat转发、STUN-NAT打洞,是家用路由器的好帮手。
直面IPv6 网上许多折腾软路由的网友都惧怕IPv6,担心IPv6公网IP引发黑客攻击,并希望配置某种IPv6的NAPT方案使自己躲藏于内网之中。但互联网本就应是P2P可连接的,NAT不应成为躲避入侵的灵丹妙药。直面P2P,并妥善配置防火墙,才是安全进行上网冲浪的根本之道。
下文的外部访问方案提及大量从外部联入内部的访问,同时内部不同网段也有权限限制,故需要谨慎配置防火墙:
- Linux的Netfilter/iptables防火墙支持IPv6后缀匹配,针对家用宽带IPv6前缀周期性更新,在SLAAC EUI64方案下无需频繁更改防火墙条目;
- 不同网段内限制访问:
- 31段无DHCP无WiFi,与32段可互访。
- 32段网关指向旁路网关。
- 172段不可访问31、32段设备,只开放路由器的DHCP和DNS端口,同时QoS出口WAN包以避免物联网设备偷带宽。
- 10段只可访问31段的部分Web服务端口,并通过NGINX的WAF控制访问部分Web服务(如只可访问Jellyfin影音库),不可接入QNAP的SMB等;
- 防火墙控制多WAN分流,部分设备限制走电信或移动出口。
软件服务
系统软件
计算和网络所在的主机均安装了PVE作为宿主系统,并通过配置不同的虚拟机实现不同的功能。
选择PVE而不是ESXi的原因主要有二:
- 开源免费
- 同时支持LXC容器和KVM虚拟机的管理。
LXC的好处 由于服务器中的部分服务需要利用核显加速,核显同时需要为PVE宿主系统提供显示输出以备不时维护之需。核显虚拟化或直通都会导致宿主机无法显示画面。而LXC容器中的系统与宿主机共享内核,实现于当年流行的OpenVZ虚拟机类似,在LXC容器内嵌套安装Docker后,Docker容器内的服务可直接调用核显,而无需为其配置核显直通或虚拟化。
NAS中的卷通过SMB协议挂载到不同的LXC和VM内进行访问。
内网的服务众多,笔者在此通过配置内网DNS服务器,管理内网各设备、VM以及Web服务。
笔者自用的内网域名遵循如下规则:
- 对于设备类,如上述提及的存储、计算、网络功能虚拟化设备,使用
型号.device.z.com
子域,如网络功能虚拟化宿主设备Fisusen-J6421小主机,使用域名fisusen-j6421.device.z.com
进行标识。 - 对于虚拟机类,使用
虚拟机系统+功能.vm.z.com
子域,如主路由OpenWRT虚拟机,使用域名opwrt-gateway.vm.z.com
标识。 - 对于Web服务类等,使用
Web服务名.app.z.com
子域,如Jellyfin服务使用jellyfin.app.z.com
标识。
网络功能虚拟化主机中的VM大部分使用了自编译的OpenWRT系统,计算功能虚拟化主机中的VM和LXC容器,则以Debian、Windows居多。
应用服务
两类应用服务的统一管理模式:
Web服务,不同的Web服务部署在不同的VM,如Jellyfin等面向内部的Web服务部署在了娱乐VM;而部分从云服务器迁移下来的Web服务(以域名samersions.net为主的服务),则部署于网站VM中。散落在各VM上的Web服务通过Docker进行部署并各自暴露端口到本地内网中,同时配置各VM防火墙只允许Web入口VM访问该端口。通过部署在Web入口VM的NGINX统一反代各个VM上的Web服务,并提供HTTPS支持。
Docker管理,如上文所言,Web服务通过各VM上的Docker运行在不同VM上,因此笔者使用安装在Web入口VM处的Portainer统一管理不同VM上的Docker,仅需在受控端VM上安装
Portainer Agent
,即可通过Portainer管理远程VM的Docker,提供统一的管理支持。
内部服务部署
在计算功能虚拟化和存储服务器中部署了多个服务,包括但不限于:
PBS:虚拟机部署于QNAP上,用于定期备份PVE各VM;
DSM-VM黑群晖:唯一的作用是用来做OneDrive的同步盘,将OneDrive上的Calibre库同步到本地,便于Calibre-Web挂载;
Jellyfin:影音库,使用可以硬解的镜像,重点在配置PVE的核显硬解,所以使用基于LXC上的Docker进行部署;
QBittorent-Web:BT下载,配合下文的外部访问方案实现真P2P直连访问,AutoBangumi依赖于此服务;
AutoBangumi:全自动当季时令动画下载,通过在某动画片订阅网站订阅动画片,可从该订阅网站抓取BT种子并送入QBittorrent-Web下载,重命名后送Jellyfin入库,全自动进行;
MC服务器:Minecraft私服,通过下文外部访问方案实现外部访问;
Git服务器:纯命令Git服务器,简单托管代码,GitLab CE太重了;
Windows-APP VM:Windows云桌面,方便从外部通过远程桌面RDP访问,笔者无Windows电脑需要用此云桌面实现Windows功能,同时实现外部iPad等设备回家等,配合下文外部访问方案实现外部访问;
Windows-Game VM:Windows游戏云桌面,同样是Windows云桌面,但使用Sunshine+Moonlight方式访问,因为这样才可以利用到显卡,直通了一张2TB的樊想SSD和RTX 4060Ti 16G,原计划用于游戏和跑一些桌面的AI应用如视频画质提升、硬字幕识别转写、声音伪造、SD AI画图等,但实际是游戏居多;
远程Linux空间:部署Code Server以及提供一个Linux的Shell供在外编写代码和验证Linux命令,本文大多数时间即通过该空间的Code Server网页在外利用碎片化时间撰写;
HAOS:用于部署Home Assistant以管理物联网设备。
外部访问方案
顺应从外部访问内部的需求,针对当前大陆家宽难以获取公网IPv4地址的情况,笔者使用了Cloudflare Tunnel、IPv6直连、IPv4 STUN NAT打洞、FRP中转等方式实现内部访问。
对外服务暴露与访问
Web页面:Cloudflare Tunnel;
Minecraft等私服协议:IPv6直连(配合DDNS+固定SRV记录实现固定网址访问)、IPv4 STUN NAT打洞(配合DDNS+Cloudflare API动态变更SRV记录端口实现固定网址访问)、FRP中转。
内部系统访问
Web页面:IPv6直连(高端口、配合DDNS+新的HTTPS DNS记录实现所谓“浏览器不显示端口”访问)、Cloudflare Tunnel(备用,受速度限制);
Bittorrent下载:IPv6直连+IPv4 STUN NAT打洞直连(使用Lucky打洞成功后触发Webhook,执行脚本动态修改OpenWRT防火墙设置及Qbittorrent监听端口设置以放行BT协议所使用的端口);
远程桌面等协议:IPv6直连、FRP中转;
内部系统访问间接接入:Tailscale(使用IPv6直连可获得良好的速度和延迟表现,Moonlight串流FPS游戏效果良好)。
未来展望
- 更统一的单点登录用户认证。
当前内网服务众多,每个Web服务都有自己的用户认证和授权系统,记忆多个密码极为麻烦。计划添加统一的单点登录用户认证系统,部分本身支持多用户+OAuth、OIDC认证的系统(如Jellyfin、Portainer等)引入SSO,其他不支持用户认证(如QBittorrent-Web、TinyMediaManager WebVNC版等)则通过WAF(如oauth2-proxy)实现OAuth2.0认证接入。 - 统一的证书管理器。
当前证书申请各自为政,除了用来反代内网Web服务的NGINX需要证书外,PVE的Web管理系统、QNAP系统的Web页面等需要使用证书,亟需一个统一的证书管理器、保管、分发。 - 对外服务侧的故障切换。
有了家用服务器后,部分原先运行在云服务器上的动态Web服务都转移到了线下,如笔者的短链接重定向服务。然而家宽SLA较低,发生短线时亟需一台廉价的云服务器做备份以临时应付流量。计划配置数据库同步和NGINX配置同步,并利用部分新式DNS记录以实现部分Web服务的故障转移。 - 更进阶的IPv6配置。
当前由于IPv6在部分互联网服务畅游上仍有不足,笔者暂时无暇顾及这部分业务的IPv6配置。目前仅有服务器与管理网段(31网段)配置下发IPv6前缀,未来需将IPv6配置到每个网段中。 - 严格限制个人上网与配置网段(32网段)对服务器网段(31网段)的访问。
当前32网段实际上充当了管理服务器的功能,因为31网段和32网段的防火墙配置上是完全可互访的。未来将进一步限制32网段对31网段的访问,如当前被反代的内部Web服务的原始HTTP服务端口目前可以被32网段直接访问,未来将只允许通过NGINX反代服务器访问32网段内,同时限制访问各服务器的各类配置端口如SSH端口等。