UCG Fiber 主路由器 + OpenWrt 透明代理 + 高可用 方案和评测(对比ROS)

发布日期:分类:Linux & homelab UCG Fiber 主路由器 + OpenWrt 透明代理 + 高可用 方案和评测(对比ROS)无评论

背景和需求

直连流量尽量通过主路由直连,同时内网所有设备透明代理。为了代理性能和方便管理,OpenWrt 可以跑在再服务器的虚拟机中,因此有必要在其离线时实现自动 failover,将内网降级为正常全直连网络。

过去用 RouterOS (ROS) 主路由(CCR2004) + OpenWrt 网关 + VRRP 实现,不过 ROS 的问题是设备管理不直观,不像 Unifi 的系统一样有着很好的大屏,以及 DPI、IDS/IPS 等功能。同时 ROS 没有 PPPoE 硬件 offload 支持,在这一点上甚至不如几百块的家用无线路由器。

因此我购入了一台 Unifi Cloud Gateway Fiber(UCG Fiber),三个10G口(2光1电)+ 4个2.5G电口,本文将探讨将其代替 ROS 作为高可用魔法(代理)家用网络环境的主路由器的方案和局限性。

TLDR:Unifi与ROS优缺点对比

(这里的优缺点仅针对本场景)

Unifi UCG Fiber
优点:

  • 界面美观,对客户端识别更智能(比如常见手机型号),DPI 功能还能分析流量种类和记录客户端的网络活动历史
  • PPPoE hardware offload 支持,千兆宽带满速下载时 CPU 占用没什么变化,据其他人测试能完全跑满 10G PPPoE
  • 小体积、高颜值,非常静音的主动散热,还有个小屏幕能看实时网速

缺点:

  • 灵活性很低,不支持 VRRP(就算是Unifi的机架式设备也只能自己跟自己组HA),高可用代理方案配置麻烦,目前没找到可用的方法实现高可用的IPv6代理,只能强制让代理都走 IPv4
  • 自带功能有些很不完善:
    • IPv6 支持烂,任何情况下 IPv6 只会走主要 WAN,哪怕 IPv6 地址下发的都是备用 WAN 的 v6,且主要 WAN 都没启用 v6
    • 策略路由(PBR)不支持 IPv6
    • 策略路由只能指定出口 WAN,没法指定下一跳到内网机器。而且 Fallback 功能残废,只有在 WAN 接口 Down 了时才会生效,哪怕系统都检测到该 WAN 不可用了也不会切换
    • Wireguard Server + 双 WAN 支持差,无法在备用 WAN 上接受连接(回程路由有 bug),除非主要 WAN 不可用
  • 其他一些问题:端口转发的 NAT Loopback(在内网通过映射到公网的地址访问内部服务时)无法硬件加速,只能跑到1~3GBps,跑不满内网带宽
  • 开启 Smart Queue QoS 后 PPPoE offload 失效,只能跑到 600Mbps 不到,且无法只在一个方向上开启(比如只在上行开启 QoS)
  • 客户端管理功能很强,但没有一个地方能看当前所有的网络连接(Conntrack)和实时速度(类似ROS的IP -> Firewall -> Connections)

RouterOS

  • 优点:灵活性很高,可以直接跟 OpenWrt 组VRRP,且 VRRP 支持脚本,ROS 的脚本可以便利的修改所有网络设置,可以实现各种自动化功能
  • 缺点1:对于管理客户端流量不直观,Connections 里虽然能看到一个内网 IP 连了一个外网 IP,但还得去 DHCP 分配里查这个内网 IP 的主机名或MAC地址,可能还得上网查一下这个 MAC 地址的 vendor,才能确定这个客户端是谁;对于外网 IP 也没法跟 DNS 查询记录里的域名做关联,很不直观。
  • 缺点2:MikroTik 家的硬路由性能有限,在我的 CCR2004 上 PPPoE 硬跑倒是能跑满千兆宽带下行,但一开双向的 Cake QoS 就不行了(哪怕开了fasttrack),不过可以只开上行的 QoS,下行带宽够大也不需要 QoS 了

UCG Fiber 硬件分析

通过dmesg和拆解图分析得到内部拓扑:

SoC 为高通 IPQ9574,拥有 NSS / PPE 硬件加速功能,CPU 为4x A73 @ 2.2GHz,不算太强,还是比较依赖硬件加速的。

拓扑方面,两个 10G 光口直连 SoC,所有电口(4×2.5G + 10G)连接到内部的 RTL8372 交换芯片,共享一个 10G 链路到 SoC。由于有硬件加速,光口和电口的交换不会占用CPU,但电口侧确实存在带宽瓶颈(虽然一般遇不到)。

硬件方面,内存物理大小共4G,OS中可用3G(包括Unifi宣传的也是3G),大概是有1G被SoC其他组件占用,也可能是ECC。

另外UCG Fiber还有一个加速度传感器用来检测摆放姿态,可以根据姿态调整小屏幕的显示方向。(有时间搞这些能不能把 IPv6 搞完善点啊喂)

方案概述

为实现 Unifi 主路由 + OpenWrt 全局透明代理 + 高可用,首先 Unifi 作为主路由器,连接光猫进行 PPPoE 拨号,OpenWrt 连接到 Unifi 的 LAN 上作为客户端(类似二级路由,但不同的是终端设备不去连接 OpenWrt),然后利用 Unifi 的双 WAN 主备切换的功能,让 OpenWrt 再作为 Unifi 的一个 WAN,即OpenWrt WAN Loopback,具体如下:

  • 将 Unifi 的 WAN1 (使用DHCP,IPv6关闭)连接 OpenWrt 的 LAN ,OpenWrt 的 WAN 再连接到 Unifi 的 LAN
  • 将 Unifi 的 WAN2 接光猫拨号,开启IPv6,并把内网的 IPv6 前缀来源也设置为 WAN2
  • Unifi 上设置 WAN1(OpenWrt)为 Primary,WAN2(PPPoE)为 Backup,模式为Failover Only
  • Unifi 上设置策略路由:
    • 1. 目标 Region 为 China 的都走 WAN2(不用勾 Kill Switch,没啥用且会跟下面的DNS hijack有奇妙的冲突);
    • 2. 来自 OpenWrt 的流量都走 WAN2(避免循环,勾上Kill Switch)
  • OpenWrt 上和标准的路由+代理设置基本相同,WAN 为 DHCP,连接 Unifi 内网。然后要将 WAN 和 WAN6 接口高级设置中的“自动获取 DNS 服务器”禁用,并填入运营商的 DNS 地址,避免循环
  • 效果:正常情况下,客户端的 DNS 请求先到 Unifi 的 DNS 服务器上(对于 DPI 功能有帮助),然后走 WAN1 -> OpenWrt 的无污染 DNS,解析得到国外地址继续走 OpenWrt 做代理(OpenWrt 再通过 Unifi LAN -> PPPoE 连接代理服务器),国内地址直接走 PPPoE 发出。一旦 OpenWrt 挂掉,Unifi 检测到 WAN1 不通,会自动把全部路由和 DNS 都切换到 PPPoE,实现自动降级直连
  • (可选)此时 Unifi 上可以再设置一个 DNS hijack,让不遵守 DHCP 下发的 DNS 服务器的设备的所有 UDP 53 端口流量都强制发到 Unifi DNS 服务器:增加 DNAT 规则,匹配来源 IP 非 OpenWrt,目标 IP 非 Unifi,目标 UDP 53,将目标 IP 改写为 Unifi 的 IP

IPv6 与 WireGuard Server 问题

按上述方案配置后,你会发现两个问题:

  1. IPv6 不通:哪怕客户端已经具有了来自 PPPoE 的 v6 地址,但 v6 网络就是不通。这里来到了 Unifi 最逆天的地方了:除非主 WAN 断开,不然在任何情况下都试图让 IPv6 走主 WAN,哪怕主 WAN 都没配 IPv6,导致网络不通。
  2. Unifi 上运行的 WireGuard Server 不通:哪怕 WireGuard Server 上设置了监听的是 WAN2 (PPPoE),只要主 WAN 还在,所有回包都会走主 WAN,导致外界的客户端连不上。

这两个问题都是 Unifi 的双 WAN 功能不完善导致的,必须 SSH 进去并设置自启脚本来修正:

编辑 /data/internet_as_backup_wan_fix.sh ,内容为(按需调整IFACE和WG_PORT):

#!/bin/sh

# ================= Configuration =================
# backup WAN Interface (real Internet, e.g. PPPoE to ISP)
IFACE="ppp1"
# Routing Table ID for backup WAN (Usually 202 for WAN2)
TABLE="202"
# WireGuard Server Listen Port
WG_PORT="16384"
# Log Tag for syslog
LOG_TAG="UniFi_Network_Fixer"
# =================================================

# Function to clean up rules on exit or restart
cleanup() {
    # Remove IPv6 default route
    ip -6 route del default dev "$IFACE" metric 1 2>/dev/null

    # Remove Policy Routing rule based on Source Port
    ip rule del sport "$WG_PORT" lookup "$TABLE" 2>/dev/null

    # Remove Force-SNAT rule from NAT table
    iptables -t nat -D POSTROUTING -o "$IFACE" -p udp --sport "$WG_PORT" -j MASQUERADE 2>/dev/null
}

# Run cleanup on start to ensure a clean slate
cleanup

logger -t "$LOG_TAG" "Starting network fix script..."

while true; do
    # Check if the interface exists
    if ip link show "$IFACE" > /dev/null 2>&1; then

        # -----------------------------------------------------
        # Task 1: Fix IPv6 Direct Access
        # Problem: Unifi doesn't add a default IPv6 route for Secondary WAN.
        # Fix: Manually add a default route to Main Table via ppp1.
        # -----------------------------------------------------
        HAS_V6_ROUTE=$(ip -6 route show default dev "$IFACE" metric 1)
        if [ -z "$HAS_V6_ROUTE" ]; then
            ip -6 route add default dev "$IFACE" metric 1
            logger -t "$LOG_TAG" "IPv6: Added default route via $IFACE"
        fi

        # -----------------------------------------------------
        # Task 2: Fix WireGuard VPN Server on Secondary WAN
        # Problem: Local UDP traffic uses Primary WAN gateway & source IP.
        # Fix A: Policy Routing based on Source Port (Directs traffic to WAN2 Table)
        # -----------------------------------------------------
        if ! ip rule show | grep -q "sport $WG_PORT lookup $TABLE"; then
            # Priority 98 ensures it runs before Unifi's default rules
            ip rule add sport "$WG_PORT" lookup "$TABLE" priority 98
            ip route flush cache
            logger -t "$LOG_TAG" "VPN: Added Policy Routing for Source Port $WG_PORT"
        fi

        # -----------------------------------------------------
        # Fix B: Force SNAT (Masquerade)
        # Problem: Source IP might be internal (e.g., 192.168.x.x) even if routed correctly.
        # Fix: Force NAT on egress to ensure Source IP matches the Public IP.
        # -----------------------------------------------------
        if ! iptables -t nat -C POSTROUTING -o "$IFACE" -p udp --sport "$WG_PORT" -j MASQUERADE 2>/dev/null; then
            # Insert at top (1) to override any conflicting rules
            iptables -t nat -I POSTROUTING 1 -o "$IFACE" -p udp --sport "$WG_PORT" -j MASQUERADE
            logger -t "$LOG_TAG" "VPN: Added Force-SNAT rule for port $WG_PORT"
        fi

    fi

    # Check every 30 seconds to handle re-dials or IP changes
    sleep 30
done

加上执行权限:chmod +x /data/internet_as_backup_wan_fix.sh

然后使用 crontab -e 并添加以下内容,设置开机自启:

@reboot /data/internet_as_backup_wan_fix.sh > /dev/null 2>&1 &

注意:每次底层Unifi OS升级后需要重新添加crontab,因此建议关闭自动更新

为什么一定要用这种方案?

  1. 为什么不能 OpenWrt 直接做二级网关(LAN 侧)? Unifi 不支持 VRRP。如果把 OpenWrt 设为 DHCP 下发的默认网关,一旦 OpenWrt 挂了,Unifi 无法自动把网关切回自己,全家断网。
  2. 为什么不能 OpenWrt 做旁路网关配合 PBR? Unifi 的策略路由(Traffic Routes)只能选 WAN 接口作为出口,不能指定 LAN 侧的某个 IP(OpenWrt)作为下一跳。
  3. 为什么必须让 OpenWrt 充当 Primary WAN?
    如果反过来让 PPPoE 作为 Primary WAN,OpenWrt 作为 Backup WAN,则无法利用双 WAN 的 Failover 功能来应对 OpenWrt 下线的情况,通过策略路由则会有以下问题:
    • 策略路由的 Fallback 功能残废:需要设置策略路由让海外流量走 Backup WAN,但问题是策略路由的 Fallback 与双 WAN Fallback 机制不通,后者会用 ping 检测是否真正可用,而前者只会在相应接口 Down 掉时才会被禁用,导致就算 OpenWrt 挂掉或死机,但接口还在,海外可直连的流量依然无法 Fallback
    • DNS 配置麻烦:默认的 DNS 行为会直接走 PPPoE,造成 DNS 无法抗污染。而若指定走 OpenWrt 的话又难以 Failover,需要 SSH 进去 Unifi 来配置 dnsmasq 为 strict-order 模式,然后使用主-备 DNS 服务器,也很麻烦

作者:WuSiYu

学生,计算机/HPC/MLsys/LLM infra方向

发表评论

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