目录

HomeLab 搭建指南 (三):网络中枢 —— OpenWrt 软路由配置与网络优化

在上一篇教程中,我们成功在小主机上搭建了 Proxmox VE (PVE) 虚拟化环境,为 HomeLab 打好了地基。而今天,我们要构建这栋大楼的“供水供电系统”——网络。

作为 HomeLab 的核心,网络环境的稳定性直接决定了所有服务的体验。本篇将介绍如何在高性能 x86 主机上,部署一个 “极致稳定、链路精简” 的 ImmortalWrt 软路由系统。我们将摒弃复杂的“双 AdGuard Home”等过度设计,回归路由器的本质,利用现代 CPU 强大的单核性能和 AES 指令集,实现秒级响应和无感分流。

在开始动手之前,想清楚“怎么连”比“怎么装”更重要。

为了最大化利用软路由的硬件性能,拒绝光猫带来的性能瓶颈,推荐采用 光猫桥接 + 软路由拨号 的高性能主路由方案:

  • 物理层流向光猫 (桥接模式) -> 主机网口 1 (直通给软路由做 WAN) -> 软路由处理 -> 主机网口 2 (虚拟网桥 LAN) -> 交换机 -> AP / 其他设备 (注:具体的网口分配逻辑会在后文详细说明)
  • 虚拟化层:PVE 9.1.1 (Linux 6.8 内核)。
  • 路由系统:ImmortalWrt 24.10.0 (基于 OpenWrt 的中国版优化分支)。
  • 做减法:路由器就是路由器。不安装 Docker,不跑 NAS 业务,不搞多层 DNS 转发。让软路由只专注于路由转发、分流和 VPN 服务。
  • Host 模式:虚拟化时直通 CPU 指令集,彻底释放 AES-NI 加密解密性能。
  • Fake-IP:利用 OpenClash 的 Fake-IP 模式接管 DNS,实现毫秒级的极速解析体验。

为什么我不推荐“旁路由”或者“软路由做二级路由”?

方案一:软路由做主路由(推荐) 这是性能天花板的选择。现代 x86 软路由的性能往往是普通光猫的几百倍。

  • 拒绝 NAT 瓶颈:光猫的 CPU 和内存(Session Table)非常有限,面对 BT 下载或数千个并发连接时容易死机。让高性能软路由负责 NAT(网络地址转换)和拨号,可以轻松处理数万并发连接,带机量几乎无限。
  • 网络层级少:没有双重 NAT(Double NAT),对 Switch/PS5/Xbox 等主机游戏联机、NAS 外网访问以及 P2P 下载最为友好。
  • 功能统管:分流、流控、IPv6 管理都在最顶层生效,全网设备即插即用。

方案二:子路由模式(不推荐) 即“光猫拨号 -> 软路由二级拨号”。这会带来双重 NAT,导致 UPnP 失效,游戏联机困难,且依然受限于光猫的性能短板——整个家庭网络的“上限”被降级到了光猫的水平。

方案三:旁路由模式(不推荐) 虽然这是一种“出了事不影响家人上网”的妥协方案,但配置复杂(需手动指定网关),且存在“流量回环”问题。作为 HomeLab 玩家,我们应该追求架构的完美,而不是为了怕坏而妥协。

关于“故障焦虑”: 很多人担心软路由挂了全家断网。其实,这类 Mini PC 只要电源稳定,连续运行一年不关机很正常。配合 PVE 的自动快照功能,玩坏了只需 30 秒即可回滚复活。实在遇到硬件故障,将 WAN 口网线从小主机插到后端的无线路由器并配置拨号,即可应急。


这是发挥硬件性能的关键步骤,很多教程容易忽略细节。

结论:坚决选择 虚拟机 (VM)。

虽然 LXC 性能损耗极低,但它与 PVE 宿主机共享内核。软路由本质上是一个操作系统,需要对网络栈、防火墙(iptables/nftables)、PPPoE 拨号等进行底层控制。

  • 稳定性:VM 拥有独立的内核,不会因为 PVE 宿主机内核更新而导致路由器挂掉,隔离性最好。
  • 兼容性:LXC 在处理 OpenClash 的 Tun 模式、WireGuard VPN 或复杂防火墙规则时,经常会出现权限不足或模块缺失的问题。
  • 性能:对于高性能主机来说,VM 的虚拟化损耗(VirtIO 模式下)完全可以忽略不计。

创建虚拟机时,关键参数的设置直接影响软路由的稳定性和性能。建议参照以下完整配置进行设置:

内存 (Memory): 2.00 GiB
处理器 (Processors): 2 (1 sockets, 2 cores) [类型: host]
BIOS: OVMF (UEFI)
显示 (Display): 默认 (Default)
机型 (Machine): q35
SCSI 控制器 (SCSI Controller): VirtIO SCSI single
CD/DVD 驱动器 (ide2): none, media=cdrom
硬盘 (scsi0): local-lvm:vm-101-disk-1, iothread=1, size=512M
EFI 磁盘 (EFI Disk): local-lvm:vm-101-disk-0, efitype=4m, size=4M
网络设备 (net0): virtio=BC:24:11:xx:xx:xx, bridge=vmbr0 (LAN口)
PCI 设备 (hostpci0): 0000:02:00 (直通 WAN 口网卡)

关键设置解读:

  • 机型 (Machine): 选择 q35。相比默认的 i440fx,它对 PCIe 直通的支持更稳定。
  • BIOS: OVMF (UEFI)。配合 EFI 磁盘启动,这是现代系统的标准。
  • 处理器: 类别必须选择 host。这是关键!它能透传 CPU 的所有指令集(包括 AES-NI),否则科学性能会大打折扣。
  • 内存: 2GB 足够。
  • SCSI 控制器: 推荐 VirtIO SCSI single 并勾选硬盘选项中的 IO thread,能显著提升磁盘 I/O 性能。
  • 网络设备 (net0): 这是虚拟 LAN 口,模型选 VirtIO (半虚拟化)。务必取消勾选 “防火墙”,防止 PVE 外层的防火墙干扰 DHCP 和 IPv6 数据包。
  • PCI 设备: 这里添加的是直通的物理网卡(作为 WAN 口),PCI 地址(如 0000:02:00)因硬件而异。

特别注意: 在创建虚拟机时,PVE 默认会创建一个 32GB 的硬盘。请在“硬盘”选项卡中将其删除(或者在创建向导中设置磁盘大小为 0),因为我们将在后续步骤中直接导入编译好的 OpenWrt 固件镜像作为启动盘。

如果你的小主机只有 2 个网口,如何分配 WAN 和 LAN 是个逻辑陷阱。

建议方案:

  • 网口 1 (eth0):作为 PVE 的管理口 + 软路由 LAN 口(半虚拟化 VirtIO,桥接 vmbr0)。
  • 网口 2 (eth1):PCIe 直通给软路由,作为 WAN 口(连接光猫)。

核心原因:PVE 的管理后台必须在 LAN 侧。 PVE 系统本身需要联网和被管理(访问 8006 端口)。如果网口 2 被直通给了软路由,PVE 系统就彻底“看不见”网口 2 了。此时 PVE 只能通过网口 1 来通信。既然你的电脑插在交换机上,需要通过局域网访问 PVE,那么网口 1 必须是 LAN。

避坑:千万不要试图把直通的网口作为 LAN 给局域网用,这会导致 PVE 管理口暴露在 WAN 侧或者直接失联,把你“锁在门外”。


参考教程

为了系统的纯净和安全,我强烈建议使用 ImmortalWrt Firmware Selector 在线构建固件,而不是去论坛下载来路不明的“大神整合版”。

  • 平台: x86/64 -> Generic x86/64
  • 镜像: 选择 COMBINED-EFI (SQUASHFS)
    • EFI: 完美支持 UEFI 引导。
    • SQUASHFS: 这是 OpenWrt 的精髓。系统分区是只读的,所有修改都存在 Overlay 层。这意味着无论你怎么把系统搞乱,只需要执行“恢复出厂设置”,系统就会瞬间回到刚刷好的纯净状态。

我们不需要在软路由里装 Docker(Docker 请在 PVE 里单独开个 LXC 跑,不要污染路由系统)。我们只保留核心功能和 PVE 增强工具:

# 基础工具与中文包
luci-i18n-base-zh-cn luci-i18n-firewall-zh-cn luci-i18n-package-manager-zh-cn luci-i18n-ttyd-zh-cn
curl wget htop nano bind-tools openssh-sftp-server

# PVE 增强 (显示 IP,支持 PVE 宿主发送关机指令)
qemu-ga

# 硬件监控 (在首页显示 CPU 频率温度)
luci-app-autocore

# 核心插件 (科学与回家)
luci-app-openclash
luci-i18n-homeproxy-zh-cn

# 依赖补充
libustream-openssl ca-bundle kmod-nft-tproxy

这样编译出来的固件体积小、启动快,且极其稳定。


固件编译完成后,我们需要将其部署到 PVE 虚拟机中。

在 Firmware Selector 编译完成后,你会看到多个下载选项。针对我们在 PVE 中创建的 UEFI (OVMF) 虚拟机,必须下载文件名包含 combined-efi 的版本。

  • 推荐文件immortalwrt-x86-64-generic-squashfs-combined-efi.img.gz
  • 文件解析
    • combined:包含引导分区和系统分区的完整镜像。
    • efi:支持 UEFI 引导(关键)。
    • squashfs:只读文件系统,支持“恢复出厂设置”,系统更稳。

注意:下载后是一个 .gz 压缩包,请务必先解压,得到 .img 后缀的原始镜像文件(例如 immortalwrt.img)。

为了方便操作,我们利用 PVE 自带的 Web 文件上传功能作为中转,无需额外下载 SCP 工具。

第一步:上传与导入

  1. 解压与重命名:将下载的 .img.gz 固件解压,并将解压后的 .img 文件重命名为简短名称(如 OP.img)。
  2. 上传:进入 PVE Web 界面 -> local (pve) 存储 -> ISO 镜像 -> 上传,将 OP.img 上传上去。(虽然它不是 ISO,但这里可以作为临时中转站)。
    • 注:上传后的默认路径通常在 /var/lib/vz/template/iso/OP.img
  3. 导入磁盘: 进入 PVE 节点 -> Shell,执行以下命令(将 101 替换为你的虚拟机 ID):
    # 语法:qm importdisk <VMID> <路径> <存储池>
    qm importdisk 101 /var/lib/vz/template/iso/OP.img local-lvm
    看到 Successfully imported disk as 'unused0:...' 即表示成功。

第二步:硬件挂载与引导

  1. 回到虚拟机(101) 的 硬件 (Hardware) 页面。
  2. 双击 “未使用的磁盘 0 (Unused Disk 0)”,总线选择 SCSI (推荐) 或 SATA,点击添加。
    • 可选:在此处点击“磁盘操作”->“调整大小”为系统盘扩容。
  3. 删除多余的 CD/DVD 驱动器。
  4. 进入 选项 (Options) -> 引导顺序 (Boot Order),将新硬盘 (scsi0) 勾选并拖到第一位。

第三步:初始化网络

  1. 启动虚拟机,点击 控制台 (Console)
  2. 系统启动完毕后按回车,进入命令行。
  3. 修改 LAN 口 IP
    vi /etc/config/network
    • i 键进入编辑模式。
    • 找到 config interface 'lan' 下的 option ipaddr,修改为你想要的网关 IP (例如 192.168.3.1)。
    • Esc 键,输入 :wq 保存并退出。
  4. 重启:输入 reboot 命令重启软路由。
  1. 确保你的电脑网线连接到了 PVE 的直通网口(或者通过虚拟交换机处于同一网段)。
  2. 电脑 IP 设置为自动获取(或者手动设为同网段,如 192.168.3.10)。
  3. 打开浏览器,访问 http://192.168.3.1
  4. 默认用户 root,默认密码通常为空(或者 password,视编译配置而定)。

参考教程

固件刷入并配置好 PPPoE 拨号后,我们进入核心的 OpenClash 配置环节。

  • 运行模式: 选择 Fake-IP (增强模式)。这是目前体验最好的模式。
  • 流量控制: 勾选 绕过中国大陆 IP。这利用了主机的高性能 CPU,让国内流量直接通过内核转发,不走代理核心,极大降低延迟。
sequenceDiagram
    participant PC as "电脑/手机"
    participant OC as "OpenClash (Fake-IP)"
    participant DNS as "运营商 DNS"
    participant Proxy as "代理节点"
    participant Web as "目标网站"

    Note over PC, OC: 阶段一:DNS 解析 (极速)
    PC->>OC: 请求 www.google.com
    OC-->>PC: 秒回假 IP (198.18.0.1)
    
    Note over PC, Web: 阶段二:流量转发 (分流)
    PC->>OC: 发送数据包 -> 198.18.0.1
    
    alt 命中规则:国内流量 (直连)
        OC->>DNS: 查询真实 IP
        DNS-->>OC: 返回 220.181.x.x
        OC->>Web: 直连访问 (不走代理)
    else 命中规则:国外流量 (代理)
        OC->>Proxy: 封装数据包
        Proxy->>Web: 代为访问
    end

  • 本地 DNS 劫持: 启用 (让 OpenClash 接管 53 端口)。
  • 禁止 Dnsmasq 缓存 DNS: 启用。这是为了避免 OpenWrt 自带的 Dnsmasq 与 OpenClash 的 Fake-IP 缓存冲突,防止解析异常。
  • 自定义上游 DNS:
    • NameServer (国内): 填入你的运营商 DNS (如 202.96.x.x) 或公共 DNS 如阿里 223.5.5.5
    • FallBack (国外): 填入 DoH/DoT,如 https://1.1.1.1/dns-query
    • 注意:这里不要填任何 127.0.0.1 的地址。

在很多软路由教程中,“OpenClash + 双 AdGuard Home”似乎是标配。但我强烈建议:不要折腾这个,除非你极度清楚自己在做什么。

为什么我反对“双 AdGuard Home”?

  1. 去广告效果有限:AdGuard Home 的 DNS 去广告只能拦截域名级别的广告。现在的广告商通常将广告和正常服务挂在同一个域名下,或者使用 HTTPS 加密传输,DNS 过滤对此无能为力。浏览器插件(如 uBlock Origin)的效果远好于 DNS 过滤。
  2. 所谓的“加速”是伪命题
    • 有些人认为加一个 AdGuard Home 做缓存能加速。但在高性能 CPU 面前,任何 DNS 转发延迟都是浮云。
    • 配置了优秀的国内运营商 DNS 后,响应通常在 10-30ms。所谓的“乐观缓存”把 20ms 变成 1ms,这 19ms 的差距在网页图片和脚本加载面前,体感几乎为零。
  3. 国外域名缓存无效:在 Fake-IP 模式下,OpenClash 对国外域名直接返回假 IP,根本不会去请求上游的 AdGuard Home,所以它的缓存对国外网站毫无意义。
  4. 增加故障点:多引入两个 DNS 服务环节,就多出两个故障点。架构越简单,你出差在外时,家里网络出故障的概率就越低。

结论:一个配置正确的 OpenClash + 运营商 DNS,就是最快、最稳的组合。

延伸阅读: 如果你依然对“双 AdGuard Home”方案感兴趣,或者需要深入研究其原理,可以参考此教程(仅供参考,不推荐生产环境使用):


折腾软路由最怕的不是“折腾坏了”,而是坏了之后“回不去”。建立完善的备份机制,是 HomeLab 稳定运行的基石。

这是最轻量的备份方式,只保存你的配置(网络、防火墙、插件设置等),生成的归档文件通常只有几十 KB。

  • 备份路径ImmortalWrt Web 管理页面 -> 系统 -> 备份/升级 -> 生成备份
  • 适用场景
    • 系统小版本升级(保留配置升级)。
    • 迁移配置到相同架构的其他机器。
    • 注:跨大版本更新(如 21.02 -> 23.05)建议不保留配置,重新手配以避免冲突。

这是 PVE 虚拟化的杀手锏。它能将整个虚拟机(包括系统盘、当前运行状态)完整保存下来,建议定期进行。

  • 备份路径PVE 管理页面 -> 选择虚拟机 -> 备份 -> 立即备份

如果你厌倦了记忆 192.168.3.x 这样的一串串 IP,或者想为局域网服务加上一把 HTTPS 的安全锁,那么这一章不容错过。

很多新手会尝试 .local.home 这样的私有后缀,但我强烈推荐使用 “公网域名 + 内部解析” 的方案。

为什么不用 .local

  • mDNS 冲突.local 被 mDNS 协议占用,可能导致 DNS 查询根本不走你的服务器。
  • HTTPS 证书不可用:Let’s Encrypt 等公共 CA 机构不会给 .local 签发证书,浏览器依然会报红。
  • 兼容性差:在 VPN 或跨网络环境下容易出现解析异常。

推荐方案: 申请一个正规的公网域名(如 example.com),配合内部 DNS 解析。这能让你在内网完美使用 HTTPS,且未来配合 VPN 也可以实现内外网统一的访问体验。

我们使用 Lucky 这个神器,它集成了 DDNS、反向代理和证书管理,非常适合运行在路由器上。

1. 安装 Lucky 登录 OpenWrt 终端,执行一键安装命令:

# 安装脚本 (参考 Lucky 官方文档)
URL="http://release.66666.host"; curl -o /tmp/install.sh "$URL/install.sh" && sh /tmp/install.sh "$URL"
  • 管理地址http://{路由器IP}:16601
  • 默认账号/密码666 / 666

2. 配置动态域名 (DDNS) 进入 动态域名 模块,配置你的域名服务商(Cloudflare/阿里云/腾讯云等)的 Token。

  • 添加任务,填写你的公网域名,例如 *.my.example.com(泛域名解析,方便后续扩展)。
  • 记录值默认 {ipv4Addr} 即可。

3. 配置 Web 服务 (反向代理) 进入 Web 服务 模块,这一步是为了让域名指向具体的内网端口。

  • 添加规则:例如将 https://op.my.example.com 转发到 http://192.168.3.1:80
  • 证书:Lucky 可以自动申请 Let’s Encrypt 证书,勾选即可实现 HTTPS。

为了让内网设备直接访问路由器,而不是绕一圈去公网,我们需要在 OpenWrt 的 DNSmasq 中添加一条记录。

  1. 打开路由器 Web 页面 -> 网络 -> DHCP/DNS -> 常规
  2. “地址 / 域名 (Addresses)” 列表中添加一行:
    • /my.example.com/192.168.3.1
  3. 保存并应用。

实现效果: 现在,你在家里浏览器输入 https://op.my.example.com,路由器会直接告诉你“就在我这儿(192.168.3.1)”,并且你可以看到浏览器地址栏那把绿色的小锁🔒。同理,以后部署的 NAS、Jellyfin 都可以通过 nas.my.example.com 这样优雅的方式访问。


经过第 7 步的配置,你的 *.my.example.com 已经能解析到家里的公网 IP 了。但如果你在公司尝试访问,会发现依然无法连接——因为路由器的防火墙像门卫一样,把所有来自外网的主动请求都拦截了。

本节我们将打通这最后“一公里”,介绍两种回家方案。

这是最传统的方式:在防火墙上开个洞,把外网端口映射到内网设备。

配置方法

  • 原生方式网络 -> 防火墙 -> 端口转发。将 WAN 口的 8080 转发到内网 NAS IP 的 80
  • Lucky 方式 (推荐):Lucky 的 Web 服务 模块其实自带了端口转发功能,且支持更高级的安全设置。

安全隐蔽 (关键): 直接暴露服务极其危险(很容易被扫描和爆破)。对于本身没有登录页面的服务(如某些监控页),必须加锁:

  • 在 Lucky Web 服务 -> 子规则 -> 安全设置 中,开启 “基本认证 (Basic Auth)”
  • 设置账号密码。这样在访问网页前,浏览器会弹窗要求输入密码,多了一层金钟罩。

方案一依然会暴露端口特征。更高级的玩法是搭建一条加密隧道(Shadowsocks/WireGuard),就像在公司和家之间拉了一条专线。

服务端配置 (软路由)

  1. 我们利用 HomeProxy 插件(或专门的 SS Server 插件)搭建一个 SS 服务器。
  2. 设置端口(如 8123)和强密码,加密方式推荐 AEAD 类(如 chacha20-ietf-poly1305)。
  3. 放行端口:在防火墙端口转发中,将 WAN 口的 8123 转发给路由器本机 LAN IP 的 8123(UDP/TCP)。

客户端配置 (手机/公司电脑)

  1. 在手机代理软件(如 Shadowrocket/Surge)中添加这个 SS 节点。
  2. 配置分流规则 (点睛之笔)
    • 不用全局代理,而是添加规则:DOMAIN-SUFFIX, my.example.com, PROXY
    • 或者直接分流内网 IP:IP-CIDR, 192.168.3.0/24, PROXY

实现效果: 你在星巴克连着 WiFi,不需要手动开关 VPN。当你访问 B 站时,流量走星巴克;当你访问 nas.my.example.com 或直接输入 192.168.3.10 时,流量会自动无感地经过加密隧道“回家”。这是目前最优雅、最安全的回家体验。


通过这套配置,我们成功榨干了软路由的硬件性能,获得了一个架构最简单、维护成本最低、且支持全家无感科学上网的网络中枢。

我们没有盲目堆砌功能,而是通过“做减法”来换取极致的稳定性。现在,你的家庭网络已经准备好承载更多服务了。在下一篇中,我们将探讨如何在 PVE 上部署媒体中心,并通过直通核显来实现硬件解码视频,提高视频播放的效率,敬请期待。