告别 ALLinBOOM,用 VRRP 为折腾旁路由保驾护航

4 月 16 日
 metalvest
爱折腾的大伙都知道,ALLinONE 软路由一旦发生崩溃,便会造成全家断网(ALLinBOOM)。

解决这一问题的思路在于,把路由功能与扩展功能进行解耦处理,也就是采用“主路由 + 旁路由”这一架构。在常见的旁路由方案当中,要么需要客户端手动把网关指向旁路由(一旦旁路由故障,每个设备都要手动改回主路由),要么在旁路由上开启强制 DHCP 功能(旁路由宕机之后,DHCP 服务随之失效,新设备将无法获取 IP 地址)。这两种方式在自动化方面均有所欠缺,一旦遇到断网,全家人就要给你上压力了。

更为省心的做法是,引入 VRRP (虚拟路由冗余协议),让主路由与旁路由共同使用一个虚拟网关 IP 地址。在正常状态下,旁路由会作为 MASTER 角色来接管流量;一旦旁路由发生故障,主路由会在数秒内自动接替其工作,整个切换过程对客户端而言完全无感。

下面给出基于 VRRP 协议的具体配置方法。整个方案需要借助两台设备来完成:其中一台作为主路由,负责拨号、NAT 以及 DHCP 服务,其 VRRP 角色为 BACKUP ;另一台作为旁路由,负责处理特殊流量(例如去广告、科学上网等),其 VRRP 角色为 MASTER 。同时,还需要设置一个虚拟网关 IP ( VIP ),以此作为客户端统一的网关地址,并由 VRRP 协议动态地对其进行接管。

以下配置以具体的硬件设备为例(可以将其任意更换为手头其他支持 OpenWrt 系统的设备):
主路由:H3C NX30 Pro ( LAN 口 IP 地址为 10.0.0.1 ,默认网关指向运营商侧)
旁路由:斐讯 N1 ( IP 地址为 10.0.0.3 ,默认网关为 10.0.0.1 ,并关闭 DHCP 服务)
VIP 虚拟网关地址:10.0.0.254/24

配置步骤基础准备:两台设备均已刷入 OpenWrt 系统,并且主路由的 WAN 口能够正常上网。
对旁路由进行静态 IP 地址的设置:IP 地址为 10.0.0.3 ,网关为 10.0.0.1 ,同时关闭其 DHCP 服务。

安装 keepalived 软件包
opkg update && opkg install keepalived
编写配置文件
旁路由( MASTER )的配置文件路径为 /etc/keepalived/keepalived.conf ,其内容如下:
global_defs {
router_id N1_MASTER
}
vrrp_instance VI_1 {   state MASTER   interface br-lan   virtual_router_id 51   priority 150   advert_int 1   virtual_ipaddress { 10.0.0.254/24 }}
主路由( BACKUP )的配置文件路径同样为 /etc/keepalived/keepalived.conf ,其内容如下:
global_defs { router_id NX30Pro_BACKUP }vrrp_instance VI_1 {   state BACKUP   interface br-lan   virtual_router_id 51   priority 100   advert_int 1   virtual_ipaddress { 10.0.0.254/24 }}

解决 OpenWrt 系统中 UCI 配置覆盖的问题
在两台设备上分别创建 /etc/config/keepalived 文件,并写入以下内容:
config globals 'globals'
option alt_config_file '/etc/keepalived/keepalived.conf'
启动 keepalived 服务并设置开机自启动
/etc/init.d/keepalived
enable/etc/init.d/keepalived start

通过 DHCP 向客户端下发虚拟网关地址
在主路由的 LuCI 管理界面中,依次进入:网络 → 接口 → LAN → DHCP 服务器 → 高级设置 → DHCP-选项,然后填入 3,10.0.0.254 。

验证方案效果
正常状态下的验证:在旁路由上执行 ip addr show br-lan 命令,可以看到 10.0.0.254/24 地址存在,而主路由上则没有该 IP 地址。
客户端自动获取网关地址的验证:客户端能够自动获得网关地址 10.0.0.254 。
模拟旁路由故障的验证:执行 keepalived stop 命令停止旁路由的 keepalived 服务,3 秒之内主路由便会接管 VIP 地址。
恢复旁路由的验证:执行 keepalived start 命令重新启动旁路由的 keepalived 服务,VIP 地址会自动切换回旁路由。
重启测试的验证:将两台设备分别重启,重启之后 VIP 地址仍然位于旁路由上,客户端的网关地址也保持正确。

完成上述配置之后,一旦旁路由发生故障,系统会自动切换至主路由,用户几乎感觉不到断网的发生。这样一来,既能够放心地折腾各种插件功能,又不会影响到全家人的正常上网。虽然该配置过程相比手动修改网关的方式要稍微复杂一些,但是配置完成之后便可以实现一劳永逸的效果。
4059 次点击
所在节点    宽带症候群
15 条回复
mooyo
4 月 16 日
排版有点问题。。。
cloudsong
4 月 16 日
写得非常棒。给您锦上添花两点:1. 在 keepalived 中添加 ping 外网地址的功能,防止科学上网插件挂了但是 openwrt 还活着,PREROUTING 链依然存在,但客户端发出的数据包到达旁路由后,防火墙规则会将包扔给指定的端口,此时端口对应的监听进程已经没了,系统内核收到包后发现没有进程认领,通常会直接 DROP 或返回 RST 。2. 如果你所有设备只连接一个交换机就没问题。如果主从之间有交换机,然后下游还有交换机接设备,那么主从之间的交换机一旦坏了,主从都认为自己还活着是主机,就开始竞争给下游发包。这一点可以通过更改网络拓扑解决,大部分人遇不到的
cloudsong
4 月 16 日
另外还要考虑 dns 用 fakeip ,以及避免 vrrp 震荡的问题。这些我都遇见过。比如出海线路很差,那么有可能系统会在两个线路之间来回切换,表现是游戏断线,视频通话断线。因此线路检测还需要加入一个延时机制,比如连续 ping 失败 3-5 次就切换。以及在你的 Keepalived 配置 fall 3 rise 2 这种,避免网关反复横跳
metalvest
4 月 16 日
@cloudsong #2 你说得非常对。基础 VRRP 配置只检测 keepalived 进程是否存活,无法感知业务层面的故障(如科学上网插件进程假死、dnsmasq 异常、内核转发失效等)。这种“半死”状态会导致 VIP 不切换,客户端流量依然指向已失效的旁路由,造成断网。

这部分需要根据各人自己使用的具体业务自定义需要检查的内容,就不单独写在文章里了,可以自行描述自己的需求让 AI 帮写合适的脚本逻辑
djw123
4 月 16 日
其实安装 keepalived-i18n 就可以了,web 里面 gui 设置更方便一点
qwvy2g
4 月 16 日
记得还有一种方式是网关虚拟实体机的 ip ,实体机 vrrp 是最高的。
Kinnice
4 月 16 日
还有一个思路是用路由来做,ospf 这种
cloudsong
4 月 16 日
@Kinnice 我见过 ospf 做双线分流,但是那是多运营商分流。你如果要分流科学,那回流要单独处理,确保都去主路由。ip 分流通过路由宣告做掉,这是 l3 ,但是请教一下,l7 这层分流怎么做呢?还是用 singbox 吗?还是用 mosdns ?最后科学挂了之后,tun 是否会自动消失呀? tun 如果还在的话,岂不是依然绕不开业务层监控?
Kinnice
4 月 17 日
@cloudsong 所有流量去主路由,
1 主路由路由分流的路由到旁路设备
2 主路由设置旁路的设备 srcip 直连

对于下层设备
直连: 设备-主路由-互联网
科学: 设备-主路由-旁路-主路由-互联网

旁路可随便断开,ospf 会直接建立不了路由通路走直连或其他,dns 最好无污染,有污染就得依靠旁路的嗅探功能,
Kinnice
4 月 17 日
@Kinnice 你也可以理解为就是双 wan ,其中一个 wan 是接到旁路设备的 lan ,这个设备的 wan 又接回主路由的 lan ,只不过做了一个路由配置让他不要环下去
Kinnice
4 月 17 日
@cloudsong 旁路你可以选择直接跑一个 mihomo 或者 singbox ,tun 还是 tproxy 就看你机器性能选择了


主路由( openwrt )跑 bird 和 adguardhome (国内走运营商,其他走旁路的科学工具的 dns )

旁路( alpine )跑 bird 和科学工具 7 层分流什么的都没问题

旁路挂了,本来没法访问的还是没法访问,直连无任何影响

我现在在两地跑了 2 个方案 vrrp 和 ospf ,发现稳定性几乎一致,节点没全故障过( amy+cn2gia 自建+cnix 自建),以至于都快忘了它们的存在了
cloudsong
4 月 17 日
@Kinnice 谢谢。受教了。你这个防环路结构很棒。后面 l7 我打算前面 mosdns 先 dns 分流一次,后面 singbox sniff inbound 兜底。tun 这边还是业务层判断联网来做掉。
qu771M5iZv41syn9
4 月 17 日
你的方案里都是假设出现故障是旁路由,而且故障来源仅仅是 IP 下线

如果是代理程序意外退出、套接字过高 CPU100%
...?

实际上你的方法完全可以在主路由用脚本替代。
metalvest
4 月 18 日
@om2mo 假设出现故障是旁路由是因为这样就只折腾旁路由啊
LOVOQ
4 月 21 日
我个人一点浅见,父母长辈这个需要高可靠网络的群体,建议不要进行多余设置,所有操作建议强制在硬路由上进行。去广告什么的让他在本地设备上进行,不要经过软漏油。如果实在需要软路由功能,建议为他们手动设置网关和 dns 服务器。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/1206217

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX