基于虚拟机的单网口软路由实践

2022/03/15

背景

一直以来都很想搭建一台多功能家庭服务器,以实现软路由、NAS、媒体中心、下载机、远程桌面办公等功能的一体化。

刚好最近又添置了一台新的设备作为主力机,那么之前的主力机 NUC11 就“闲置”了。本来打算将这台机器出掉回回血,但转念一想,这台机器搭载了功耗相对较低的移动端处理器 i5-1135G7、16 GB DDR4 内存、一个 1TB NVME 硬盘、一个 1TB HDD 硬盘,以及一个 2.5G 网口,如果将其打造成一台多功能的家庭服务器,物尽其用的同时,作为一台小主机,其较强的性能也可保证未来相当长一段时间内不会落伍。

于是便有了这篇文章。

系统

这台服务器采用了 Windows 11 操作系统,通过各种软件以及 Hyper-V 虚拟机拓展使用场景。

windows_11.png

之所以做了这个非常规的违背祖宗的决定,也是基于多个因素综合考虑的结果。

家庭服务器的操作系统,大概有三个主流的选择:Linux、PVE/ESXI/unRaid 虚拟机、Windows Server 等。

关于 Linux,我个人是一个 Linux 桌面的长期使用者,使用经验也相对丰富,并且 Linux 也占据了服务器市场的绝大部分份额,使用 Linux 作为服务器是应有之义。但是 Linux 有一个致命的问题,那就是软件生态的匮乏(“家庭”服务器的使用场景)。举个例子,比如作为下载机,在国内很难完全绕开迅雷,虽然 Linux 桌面也有原生的迅雷(甚至 flatpak 版本还是我维护的),但是缺失了比如迅雷云盘等功能,实用性大打折扣。遂无奈放弃。

关于 PVE/ESXI/unRaid 等虚拟机,没有选择这个方案一方面是因为之前没接触过,还得从头研究,比较消耗脑细胞;最关键的一点是,如果不直通显卡等硬件(至少目前 NUC11 的显卡无法直通),图形性能严重不足,那么这颗 80EU 的 Xe 显卡性能就浪费了。遂果断放弃。

关于 Windows Server,这本来是我的首选方案,服务器系统相对稳定,也具备 Windows 软件生态最为丰富的优势,还能完美驱动各个硬件设备。可是折腾了半天,有线网卡驱动死活装不上,我知道一般是我自己操作的问题,但是最终还是没能解决,网卡驱动不起来,做服务器便是虚妄。遂自闭放弃。

于是选择了 Windows 11 作为服务器的操作系统。其实任何一台机器,任何一个系统,只要能够实现相应的目的,那么就可以作为一台“服务器”,条件没必要卡的那么死。像这样,直接在 host 上安装闪电下载、迅雷等实现下载机的功能;安装 Emby 实现家庭媒体中心的功能;使用自带的远程桌面实现远程办公的功能;使用自带的文件共享实现 NAS 的功能;最关键的,跑一个 Hyper-V 虚拟机装一个 OpenWrt 系统,实现软路由的各种功能,比如局域网内手机、平板、笔记本等其他设备的全局透明代理。

基于虚拟机的单网口软路由实践

前戏有点长,终于来到了本文题目的内容。

简单讲,是用一根网线连接 NUC 的 2.5G 网口和普通硬路由器的 LAN 口,再在 NUC 的 Windows 11 系统上启动一个装有 OpenWrt 路由器系统的 Hyper-V 虚拟机,并以桥接的方式连接。这样,原本连接普通硬路由 Wi-Fi 的设备如不做额外设置,则不会受到任何影响,而希望通过 OpenWrt 全局透明代理的设备,依旧是连接原本的 Wi-Fi,只需将网关和 DNS 改为此虚拟机,即可使网络流量穿过装有代理工具的虚拟机软路由。

home_network.png

需要注意的是,最好为 host 分配一个静态地址,以方便后续操作。

准备 OpenWrt 系统镜像

到 OpenWrt 的 releases 页面选择所需镜像(这里是 x86_64,注意选择正确的架构),这里我就选择 generic-ext4-combined-efi.img.gz,下载得到 openwrt-版本号-x86-64-generic-ext4-combined-efi.img.gz

将上述镜像解压,得到 openwrt-版本号-x86-64-generic-ext4-combined-efi.img。到这里,还需要将此 img 镜像转换为适用于 Hyper-V 虚拟机的 vhdx 格式。

这里我选择 StarWind V2V Converter 进行格式转换。下载完成后安装打开。

  1. 在 Select location of image to convert 界面,选择 Local file
  2. 在 Source image 界面,选择刚解压得到的 img 镜像
  3. 在 Select location of destination image 界面,选择 Local file
  4. 在 Select destination image format 界面,选择 VHD/VHDX
  5. 在 Select option for VHD/VHDX image format 界面,选择 VHDX growable image
  6. 在 Set destination file name 界面,选择文件保存地址,默认与源文件同目录

最终得到名为 openwrt-版本号-x86-64-generic-ext4-combined-efi.vhdx 的文件。

安装 Hyper-V 虚拟机

在开始菜单搜索“启用或关闭 Windows 功能”,找到 Hyper-V 勾选安装,重启以完成安装。此处不再赘述。

创建并配置 OpenWrt 虚拟机

在开始菜单搜索并打开“Hyper-V 管理器”,点击右侧的“虚拟交换机管理器”。

Hyper-V.png

在弹出的窗口中,“新建虚拟网络交换机”,在右侧窗口中选择“外部”,并点击“创建虚拟交换机”,之后为该虚拟交换机起一个名字,比如“Bridge Switch”,外部网络选择 host 正在使用的网卡,记得勾选“允许管理操作系统共享此网络适配器”。

new_switch_1.png

new_switch_2.png

回到 Hyper-V 管理器主界面,点击右侧的“新建-虚拟机”打开“新建虚拟机向导”。

new_vm_1.png

需要注意的是,在“指定代数”这一步,如果之前的镜像是含有 efi 字样的,那么选择“第二代”,否则选“第一代”;

new_vm_2.png

在“配置网络”这一步,选择刚刚建立的虚拟网卡;

new_vm_3.png

在“连接虚拟硬盘”这一步,选择“使用现有虚拟硬盘”并选择之前转换得到的拓展名为 vhdx 的文件。

new_vm_4.png

其他选项保持默认即可。

再次回到 Hyper-V 管理器主界面,在刚刚创建的虚拟机上“右键-设置”,打开该虚拟机的设置页面,在左侧找到“安全”,并禁用安全启动。

config_vm_1.png

config_vm_2.png

在设置完成的虚拟机上“右键-启动”、“右键-连接”,即可启动 OpenWrt 并看到输出。待输出内容稳定后,敲一下回车,即可输入后续命令。

首先,键入 passwd 以修改管理员密码;

之后,键入 vim /etc/config/network 以修改基本配置;

只需修改 config interface 'lan' 部分的内容。

option ipaddr '192.168.1.1' 代表路由器管理界面地址,默认为 192.168.1.1,建议修改为与 host 同一网段的其他可用固定 IP 地址; 之后,在后面增加两行:

option gateway '192.168.x.x'
list dns '192.168.x.x'

gateway 意为网关,dns 配置 DNS,将二者统一设置为 host 所连接的物理硬路由器的 IP 地址(比如我用的华为路由器,地址为 192.168.3.1)。参考配置如下图。

etc_config_network_eg.png

使用局域网内另一台设备的浏览器输入设置好的路由器管理地址,再输入账号密码即可打开 OpenWrt 软路由的管理页面了。

openwrt_main.png

安装 OpenClash

在这里,我选用 OpenClash 实现代理功能。

根据 OpenClash 的 Wiki 安装 OpenClash 所需依赖。

首先,更新软件包:

opkg update

之后,安装上文所述页面规定的依赖:

opkg install xxx

需要注意的是,OpenClash 所需的 dnsmasq-full 与系统自带的 dnsmasq 冲突,安装之前需要先卸载掉系统自带的包,所以这一步这样执行:

opkg remove dnsmasq && opkg install dnsmasq-full

安装其他包的时候也可能出现一些报错,忽略即可。

这里 下载相应架构的 Clash 内核。下载完成后会得到例如 clash-linux-amd64.gz 这样的压缩包,将解压得到的文件重命名为 clash

将该文件上传至 OpenWrt 虚拟机,比如我的虚拟机软路由地址为 192.168.3.199,在 macOS 下可执行:

scp /path/to/clash [email protected]:/tmp/clash

随后在虚拟机里执行:

mv /tmp/clash /etc/openclash/core/clash
chmod 777 /etc/openclash/core/clash

从而将内核文件放置在正确的位置并给予其可执行权限。

这里 下载 OpenClash 的安装包,比如 luci-app-openclash_0.44.29-beta_all.ipk,随后打开虚拟机路由器的管理页面,进入“System-Software”页面,并点击“Upload Package…”按钮上传并安装刚刚下载好的 OpenClash 安装包。

openwrt_software.png

openwrt_upload.png

稍等片刻,安装完成后(这里可能有报错,依旧忽略即可),重启 OpenWrt 虚拟机,并再次进入虚拟机路由器管理页面,此时,应该已经出现了 OpenClash 服务。

service_openclash.png

在“Config Update”标签页配置完成 Clash 订阅后,回到“Overviews”标签页,点击界面左下角的“启动 OpenClash”即可开启代理服务。

openclash_config_update.png

openclash_start_openclash.png

此时,打开同一局域网内其他设备的网络设置,将网关和 DNS 均配置成 OpenWrt 虚拟机软路由的地址,即可实现全局透明代理。

network_tcpip.png

network_dns.png

打开浏览器,输入 https://www.google.com/,完成~

google_success.png

最后

全局透明代理的体验真的非常棒,不用再单独为浏览器、Telegram、Spotify、终端等单独设置代理,也不用再为一些没有代理设置选项的软件所困扰。

此外,因为这台 NUC11 是以有线方式连接到路由器上的,所以局域网访问速度和稳定性都得到了一定程度的保障,使用远程桌面管理服务器时也十分流畅。不得不说,微软的 Microsoft Remote Desktop 可以称得上最好的远程桌面客户端,比如分辨率问题,只需勾选 Optimize for Retina displays 即可完美解决。

optimize_for_retina_displays.png

补充(2022.03.21)

最近几天一直使用全局代理,上网一切正常。然而,我发现不使用代理的时候,无法正常访问互联网。我本来以为旁路网关对局域网其他设备不会有影响,但事实证明我错了,不仅有影响,而且非常大。

OpenWrt 作为旁路由,需要注意两个坑:

  1. 局域网内禁止存在多个 DHCP 服务器。主路由已经提供了 DHCP 服务,故需关闭作为旁路由的 OpenWrt 的 DHCP 服务。

关闭方法:网络 - 接口 - 接口 - LAN - 编辑 - DHCP 服务器 - 常规设置 - 忽略此接口

OpenWrt - DHCP.png

需要注意的是,作为旁路网关使用时,不可完全停用 Dnsmasq,因而不能采用到 网络 - DHCP/DNS 选项卡中关闭的方法。

  1. 因为较新的系统会优先使用 IPv6 网络,所以需要禁用 LAN 口的 IPv6 服务,以避免局域网设备获得了多个临时 IPv6 地址从而导致无法正常联网。

禁用方法:网络 - 接口 - 设备 - br-lan - 配置… - 启用 IPv6(取消勾选)

OpenWrt - IPv6.png

参考文章:

等等…