如何用旁路网关接管内网 IPv6 代理:RA 双路由优先级实战

AI 生成的摘要

加载中...

(此服务由 xLog 驱动)

如何用旁路网关接管内网 IPv6 代理:RA 双路由优先级实战

前言

最近笔者搬到新地方工作,租的房子自带中国移动的光纤入户。图方便,就直接把之前购买的华为 CPE 当作主路由使用。然而使用 5G Wi-Fi 时总是莫名其妙断流,起初我以为是 R2S 设备过热,花了不少时间优化散热方案。直到有天晚上漏接了整晚消息,第二天排查才发现——问题根本在 CPE 本身!

虽然配有千兆网口,但实测 PC 与 R2S 点对点传输时只能跑到 600 Mbps,而且还有 120 次丢包重传,实在难以接受。在 miaoer 的推荐下,我在京东入手了中兴巡天 AX3000。测试发现内网点对点速率是 940 Mbps,在什么都不变的情况下,零丢包重传。它的后台管理很简洁,基本没什么可调的地方,不过值得欣慰的是,它支持为单个设备定制 DHCP 设置,包括独立下发 IPv4 地址和网关。就凭这点,旁路网关方案就能跑起来。

众所周知,旁路网关是对现有网络拓扑改动最小的代理方案。对于 IPv4 来说,只需手动为终端设置网关,或在主路由绑定 MAC 地址下发定制 DHCP 即可。但如今 IPv6 越来越普及,每个设备都能轻松获得全球唯一的 IPv6 地址,穿透打洞也更简单。那么,旁路网关能否也“喝口 IPv6 的汤”呢?

准备条件

设备列表

设备名称固件/型号角色备注
R2SCatWrt.v24.11.rkarm64旁路网关用于提供 IPv4/IPv6 代理
中兴巡天 AX3000官方固件(简洁后台)主路由支持定制 DHCP 下发
中国移动光猫默认运营商设备入户网关工作在路由模式,不支持桥接

网络拓扑图

实践

原理

在 IPv4 网络中,我们依赖 DHCP 下发 IP、网关和 DNS 信息,想定制给特定设备分配的网络参数,只需在主路由配置即可。

而 IPv6 的机制则不同,它将地址和路由信息的下发分成了两个部分:

  • DHCPv6:负责分配 IPv6 地址和 DNS;

  • RA(Router Advertisement):负责通告路由,同时也可带上 DNS。

因此,我们可以将 DHCPv6 的工作交给主路由,而将 RA 的广播任务交由旁路网关来完成。这样一来,终端设备就会默认使用旁路网关作为 IPv6 出口路由。特别是在手机等非 root 设备上,无法手动设置 IPv6 网关的情况下,这种方式就显得尤为重要。

若由主路由负责 RA 广播,则终端自然会使用主路由作为默认 IPv6 网关,流量也就不会走旁路了。因此,必须让旁路网关承担 主 RA 的角色,才能实现 IPv6 默认走代理。

操作

主路由设置

确保光猫和 AX3000 已开启 IPv6 支持,并启用 LAN 端的 DHCPv6:

关闭主路由的 RA 广播功能(即“路由通告”):

其余 IPv6 功能保持默认或开启状态即可。

旁路网关设置(R2S)

LAN 接口配置示例如下:

IPv6 路由前缀可以从主路由上拿

关闭 CatWrt 中的 DHCP 功能:

IPv6 设置示例:

其中:

  • 服务器模式:表示设备主动广播 RA,宣告自身为 IPv6 网关;
  • 中继模式:则是仅转发给上游;
  • NPD 代理无需开启;
  • DNS 填写旁路网关的 Link-Local 地址即可(如 fe80::xxxx)。

成果

PC IPv6 信息如下:

ip add 输出

BASH
❯ ip add
3: wlan0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether xx brd ff:ff:ff:ff:ff:ff permaddr xx
    inet 192.168.100.2/24 brd 192.168.100.255 scope global noprefixroute wlan0
       valid_lft forever preferred_lft forever
    inet6 2409:8a20:423:e684:2/128 scope global dynamic noprefixroute 
       valid_lft 186269sec preferred_lft 99869sec
    inet6 2409:8a20:423:e684::xxxx/64 scope global noprefixroute 
       valid_lft forever preferred_lft forever
    inet6 fe80::839c:251c:581b:42a5/64 scope link noprefixroute 
       valid_lft forever preferred_lft forever
Copy

ip -6 route 输出

BASH
❯ ip -6 route
::1 dev lo proto kernel metric 30 pref medium
2409:8a20:423:e684:2 dev wlan0 proto kernel metric 600 pref medium
2409:8a20:423:e684::/64 dev wlan0 proto ra metric 600 pref medium
fe80::/64 dev wlan0 proto kernel metric 1024 pref medium
default via fe80::e8fe:1bff:fe6e:614c dev wlan0 proto ra metric 600 pref medium
Copy

访问效果

BASH
❯ curl -v https://www.google.com           
* Host www.google.com:443 was resolved.
* IPv6: 2404:6800:4005:81e::2004
* IPv4: 142.250.198.68
*   Trying [2404:6800:4005:81e::2004]:443...
* ALPN: curl offers h2,http/1.1
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
*  CAfile: /etc/ssl/certs/ca-certificates.crt
*  CApath: none
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.3 (IN), TLS change cipher, Change cipher spec (1):
* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
* TLSv1.3 (IN), TLS handshake, Certificate (11):
* TLSv1.3 (IN), TLS handshake, CERT verify (15):
* TLSv1.3 (IN), TLS handshake, Finished (20):
* TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.3 (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384 / X25519MLKEM768 / id-ecPublicKey
* ALPN: server accepted h2
* Server certificate:
*  subject: CN=www.google.com
*  start date: Jun 17 20:03:51 2025 GMT
*  expire date: Sep  9 20:03:50 2025 GMT
*  subjectAltName: host "www.google.com" matched cert's "www.google.com"
*  issuer: C=US; O=Google Trust Services; CN=WE2
*  SSL certificate verify ok.
*   Certificate level 0: Public key type EC/prime256v1 (256/128 Bits/secBits), signed using ecdsa-with-SHA256
*   Certificate level 1: Public key type EC/prime256v1 (256/128 Bits/secBits), signed using ecdsa-with-SHA384
*   Certificate level 2: Public key type EC/secp384r1 (384/192 Bits/secBits), signed using ecdsa-with-SHA384
* Connected to www.google.com (2404:6800:4005:81e::2004) port 443
* using HTTP/2
* [HTTP/2] [1] OPENED stream for https://www.google.com/
* [HTTP/2] [1] [:method: GET]
* [HTTP/2] [1] [:scheme: https]
* [HTTP/2] [1] [:authority: www.google.com]
* [HTTP/2] [1] [:path: /]
* [HTTP/2] [1] [user-agent: curl/8.14.1]
* [HTTP/2] [1] [accept: */*]
> GET / HTTP/2
> Host: www.google.com
> User-Agent: curl/8.14.1
> Accept: */*
> 
* Request completely sent off
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
< HTTP/2 200
Copy

小结

其实在这里,仍然存在一个问题值得深思:如果让旁路网关承担 RA(Router Advertisement)的职责,那么一旦它宕机,整个内网的 IPv6 网络将不可用。这显然违背了旁路网关“最小侵入原则”的设计初衷。

那么该如何解决这个问题呢?

答案是:为内网配置多个 RA 源,设定优先级即可。

在 IPv6 网络中,允许多个设备同时发送 RA,只要优先级设计合理,客户端会自动选择最优路由。我们可以通过以下方式实现主备切换:

  • 旁路网关 作为 主 RA 广播者,优先级设置为高(或默认);
  • 主路由器 也启用 RA,但将其优先级设置为低(low)作为备用。

配置方法示例:

打开主路由的“路由通告”功能,并将优先级设置为 低(low):

此时,内网将拥有两个 RA 广播源:

  • 旁路网关:广播默认路由,优先级高;
  • 主路由器:也广播默认路由,优先级低。

可以通过如下命令查看实际的 IPv6 路由表:

BASH
❯ ip -6 route
::1 dev lo proto kernel metric 30 pref medium
2409:8a20:423:e684:2 dev wlan0 proto kernel metric 600 pref medium
2409:8a20:423:e684::/64 dev wlan0 proto ra metric 600 pref medium
fe80::/64 dev wlan0 proto kernel metric 1024 pref medium
default via fe80::e8fe:1bff:fe6e:614c dev wlan0 proto ra metric 600 pref medium
default via fe80::5 dev wlan0 proto ra metric 601 pref low
Copy

可以看到:

  • fe80::e8fe:1bff:fe6e:614c 是旁路网关下发的默认路由,优先级为 medium,metric 更低,因此默认使用;
  • fe80::5 是主路由器的默认路由,优先级为 low,metric 稍高,作为备选。

一旦旁路网关失联,内核的邻居不可达检测(NUD) 会将其标记为“不可达”,此时系统会自动切换到主路由器广播的低优先级默认路由,从而保证内网设备的 IPv6 网络依旧可以正常使用。

故障演练,让旁路网关宕机

路由信息如下

BASH
❯ ip -6 route
::1 dev lo proto kernel metric 30 pref medium
2409:8a20:423:e684:2 dev wlan0 proto kernel metric 600 pref medium
2409:8a20:423:e684::/64 dev wlan0 proto ra metric 600 pref medium
fe80::/64 dev wlan0 proto kernel metric 1024 pref medium
unreachable default via fe80::e8fe:1bff:fe6e:614c dev wlan0 proto ra metric 600 pref medium
default via fe80::5 dev wlan0 proto ra metric 601 pref low
Copy
此文章已经由它的创作者签名并安全地存储在区块链上。