一台家用多用途服务器的设计和配置

需求

一台用于非IT专业人士家的小服务器,需要运行诸如DNS分流和代理之类的软件供内网使用。它处于Full Cone NAT之后,并且需要能被远程管理和重新配置。它应当不发出噪音,并且尽量节约用电。

设备选型

考虑到这台设备上会跑一些网络应用,我需要一个比较能用的CPU加上多于一个的以太网端口。在淘宝上购买了某家专门做无风扇small form factor机器厂的产品,拆掉里面不靠谱的垃圾配件,组成了以下配置:

  • Intel Celeron J1900
  • 自己换的8G三星内存
  • HP拆机的Intel S3610 200G,存储Hypervisor和关键应用数据
  • Samsung 860 EVO mSATA 256G,存储非关键应用数据
  • 两个Intel I211网卡
  • 12V 3A外置电源

其实本来想选择一个支持ECC内存的CPU的,但是这个价格上确实也不好找,遂放弃。J1900让我不满的另一点是不支持SR-IOV,这样机子上自带的一块Intel 5100 Wi-Fi网卡就算是废了,只能把它拆掉了。不用的端口,例如COM和音频输入输出口可以用相应的防尘塞堵上;拆掉网卡以后露出来的天线口用黑色的电工胶布贴了一下,防止进灰。然后买了一个VGA的假负载用于绕过一个固件bug。

固件配置

这台设备因为是深圳小作坊出品,其UEFI固件基本上是Aptio提供给Bay Trail设备的参考固件,设置非常全面,一个都没隐藏。固件版本为GBYT9 V1.02,坑有几个:

  • 使用UEFI GOP的时候,HDMI输出不可用,只能用VGA
  • 如果没有连接显示器,固件会死机,无法启动系统
  • 如果设备上连接了多个USB键盘,只有第一个被枚举的能在固件中使用,因此尽量不要在机子上插没用的键盘或者无线接收器之类的玩意

固件里面需要修改的设置不多:

  • 关掉Legacy Option ROM(然后需要重启一下)
  • 关掉CSM
  • 打开Secure Boot(ESXi 6.7支持Secure Boot和TPM2.0了,虽然没有vCenter的话TPM用不上)
  • 在南桥设置中,设置掉电后自动开机
  • 在北桥设置中,把显卡的睿频关掉,显存分配全部设为最小

Hypervisor配置

考虑到设备后期扩展和维护的需要,这台服务器上会运行一个Hypervisor,所有应用软件放进虚拟机。那么常见的免费Hypervisor有这么几个选项:

  • Microsoft Hyper-V Server
  • Proxmox VE
  • VMWare ESXi

Proxmox VE的不稳定和设计糟糕是所有用过的人都明白的。Microsoft Hyper-V Server在非Active Directory域环境中很不好使,远程管理配置困难,命令行体验也非常糟糕。最后我决定用ESXi,相对来讲比较轻量级,对各种操作系统的支持都比较好,远程管理处于能用水平,并且免费版提供的功能对家用环境来说也够用。

VMWare ESXi安装

很幸运,Intel I211网卡是ESXi 6.7原生驱动支持的网卡。如果系统上没有ESXi自带驱动的网卡的话,你就得去第三方网站上找找有没有相应的驱动了。

安装过程感觉没什么好讲的,安装向导一步步走完就是了。唯一需要注意的是,ESXi默认会把管理网所在的vmk0挂到第一个枚举到的网卡下面,对于多网卡设备,可能需要试一下具体是哪个网卡。为了方便区分,我打印了一张贴纸贴在机器外壳上。

在我这个配置的机子上,全新安装的ESXi 6.7启动时间约2分钟。

另外ESXi 6.7 Build 13006603及之前的版本好像和Chrome 73及以上版本有一些兼容性问题,如果ESXi网页打不开,可以试一下Firefox或者其它非Chrome内核的浏览器。

内核参数

我这台设备比较诡异,安装程序启动和安装完成第一次重启的时候,需要在bootloader界面按Shift+O,在内核参数的末尾添加ignoreHeadless=TRUE,否则启动内核的时候会卡住。

第一次启动成功后,通过console shell或者SSH,把这个参数存入配置文件:

然后重启一下,确认系统能在无用户干预情况下自动启动。

主机名

前往Networking -> TCP/IP stacks -> Default TCP/IP stack -> Edit settings,在Basic DNS configuration里面选择Manually configure the settings for this TCP/IP stack,在Host name一项中输入你想要的主机名。应用配置后,再把设置改回Use DHCP DNS。这样网络中的DHCP设置会继续生效,但是主机名已经改成你自己设置的了。

如果你考虑给ESXi加Active Directory域的话,建议主机名长度不要超过15字符,不然和NetBIOS协议会有兼容性问题。

NTP

为了保证在中国大陆的可用性,设置了以下NTP服务器:

设置完以后需要手工启动一下NTP服务。同步需要过几分钟才会完成,不需着急。

第二块硬盘

前往Storage -> Datastores,新建一个datastore即可,也没有什么可以说的。

SFCBD

启用SFCBD(Small Footprint CIM Broker Daemon)我们才能读到一些硬件的健康数据。不过这个比较看机型,我这台机子上就基本上读不到有效信息。通过console shell或者SSH执行以下命令:

用户

如果有需要的话,前往Host -> Manage -> Security & users -> Users创建用户。需要注意的是,ESXi默认会禁止最近一段时间登录失败次数过多的用户登录,所以如果你只有默认的root用户并且机子还暴露在公网上的话,很可能因为有人爆破密码而把你自己关在外面,因此建议至少创建一个用户名不常见的用户。

虚拟机配置

我们只有8GiB内存,硬件会占用大概0.11GiB,ESXi本身会吃掉1.22GiB(如果打开swap会稍微少一点),那么满打满算剩下来的还有6.67GiB。在这点内存里面要塞进大量功能,那么每一点都不能浪费。FlexVPN之类的方案虽然非常好用,但是实在是太吃内存,暂时不予考虑。

远程管理方案1:RouterOS

选择RouterOS的唯一原因是,它能只用256MiB内存启动,并且有各种路由功能,非常省资源,如果应急需要用它来当路由器,它也能撑一阵子。RouterOS的缺点是bug多,而且修bug比较慢。除去应急时可以用的路由功能不谈,RouterOS的OpenVPN可以提供一个同地区不同站点之间稳定的站到站连接。

因为这台虚拟机是作为远程管理用的,它不应当依赖任何当前站点的服务。

安装RouterOS

前往官网下载最新的Cloud Hosted Router的VMDK镜像,传到ESXi上,然后把VMDK转成ESXi支持的flat格式:

这样会生成两个文件,一个结尾有flat(这个文件在网页管理面板上看不到),一个没有,这两个文件组成了整个flat格式的VMDK。如果觉得在ESXi上操作麻烦,qemu-img也可以做相应的格式转换。文件创建出来以后就不能重命名,否则会从系统中消失。

接下来只要正常创建一个Other Linux 3.x (64bit)类型的虚拟机,挂载现有硬盘启动就可以了。

配置网络

启用ipv6包,重启一下。然后在ether1上配一个DHCP客户端就完事了。

DNS和NTP服务器分别配置成公共服务,不要依赖本地服务。

设置远程管理

创建一个OpenVPN客户端,连接到我的服务器上。

自动更新

虽然RouterOS的更新没那么靠谱,但是如果你在long-term发行通道上的话,鉴于它漏洞那么多,还是自动更新比较好。

远程管理方案2:Linux + ZeroTier One

从节约资源的角度考虑,我选择了Debian 9,分配了2C/512MiB/32GB的资源,另外限制了30000IOPS。经验表明,在ESXi上,一旦你的Guest OS在疯狂IO(比如不小心开了swap然后不小心用完了内存),很有可能因为IO速度而把ESXi自己也一起拖死,因此一定要根据你的硬盘实际能力,对IOPS做相应的限制。

安装系统

需要安装standard system utilities + SSH server,然后关掉swap。

/etc/dhcp/dhclient.conf里写上:

/etc/systemd/timesyncd.conf里写上:

设置一下sysctl:

安装VMWare Tools

配置ZeroTier One

检查资源占用

应用容器:Linux + Docker

这一台虚拟机给了2C/2GiB/64GB。安装系统和初始配置的方法和上一台Linux虚拟机类似,不再赘述。

代理网关

TCP部分可以在iptables的nat表上做REDIRECT;UDP部分可以使用iptable/netfilter的TPROXY功能实现。TPROXY需要Linux内核版本4.18以上,所以我在这台机子上用了内核版本4.19的Debian Buster。实现很简单。

首先打开系统的转发功能(注意持久化):

TCP这边的话,简单设置所有公网流量重定向到代理所在端口:

UDP则是使用TPROXY规则在mangle上拦截一下:

然后分别在1919端口上启动相应代理程序的TCP和UDP监听即可。需要注意的是,代理程序自己的流量不能走这条规则,那么就要自行想办法做区分。调整iptables规则的时候要注意一下不要把Docker的默认NAT规则清掉了。另外如果你的IPv6是SLAAC配置的话,给用户下发网关可能比较麻烦,需要自己想一下办法。

DNS分流:dnsdist-autoconf + Pi-Hole

我们首先需要安装Docker。Docker有一个大坑就是它默认会把iptables的forwarding chain的默认规则改成DROP,这样你的路由器莫名其妙就坏了。我们需要配置Docker不要没事折腾iptables:

配置完以后重启一下Docker daemon。这样配置有安全风险,请自行考量。

安装dnsdist-autoconf很简单,写一个基础配置:

然后写一个简单的systemd服务来启动它:

(注意这里监听了5302端口,因为我们之后会用Pi-Hole来间接使用它。)

安装Pi-Hole,继续用Docker+systemd:

(注意这玩意设计很糟糕,需要硬编码本机IP地址。上游DNS必须写在环境变量里,不能用网页设置。我这里设了用dnsdist-autoconf开出来的localhost:5302和用另一个fallback程序开出来的localhost:5301。)

检查资源占用

测试

  • Hypervisor能够在不插键盘和显示器的情况下正常启动
  • 虚拟机能在Hypervisor启动之后自动启动
  • 虚拟机中各个应用程序工作正常,并且不依赖虚拟机的启动顺序
  • 所有远程访问方式能够正常工作

清理工作

  • 关掉不必要的Hypervisor服务:console shell,SSH
  • 给所有虚拟机做个snapshot

On site安装工作

  • 网关虚拟机需要固定IP
  • Pi-Hole需要设置网关IP

参考:

一台家用多用途服务器的设计和配置》有3个想法

  1. Ning Li

    折腾完事老婆说 不如原来tplink快。还费电。换回去吧。!!!!!!!
    哈哈
    软路由的坑

    回复
  2. Pingback引用通告: 在家也要玩BGP(2):可控地给部分局域网设备设置透明代理网关 | Drown in Codes

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据