旁路由-主路由自动替代旁路由的自动切换方案

旁路由/网关在维护的时候导致断网或其他一些地方肯定不是够稳定,所以需要一个更加智能无感的自动切换方案。 传统dhcp切换网关的方式相应速度慢,掉线时间长。爱快分流方案虽然可以无感切换但是需要一个x86设备运行不开源有过黑历史的爱快。

于是想到想到了一个新的方案,我姑且称之为 主路由自动切换ip接位网关方案

# 旧的旁路由自动方案

目前主要有两种

  • 传统的旁网关形式,内外设备单独配置一个网关设备。在这个网关设备失效的后,通过自动脚本配合dhcp等方式实现切换,需要下游设备断开重连,或重启主路由切换时间较长。这是效果最差的一种启动切换方案。
  • 主路由用爱快根据ip和域名通过运营商配置绑定wan2的分流方案,也就是 ikuai-bypass,使用体验上要比上一种方式好非常多,不存在短时断网,堪称完美,但是需要x86做主路由并刷闭源的爱快。切换时间最少1分钟,但是切换期间不会导致断网。如果您用 ikuai-bypass 方案,也期待能给我点一个star。

# 思路

# 新方案使用主路由和旁路由 ip轮替的方式,原理:

旁路由用桥接/别名或虚拟网卡的方式配置两个ip 第一个ip我们暂且称之为工作ip,第二个ip姑且叫辅助ip。

主路由不断ping旁路由的第二个ip,如果ping不通,那么主路由把自己的ip修改为旁路有工作ip接替旁路由的工作。旁路路由正常再把自己改回去。这样就实现免重连切换。

# 新方案优点

原理简单维护也简单。切换速度快(3-10秒以内),不需要内网设备断网后重联,主路由不需要是x86设备,不需要闭源的爱快。

各方面体验远高于dhcp切换方案,缺点是不如ikuai-bypass的完全无缝切换,切换期间会有3-10秒断网。

# 切换和配置

我们为了便于理解和管理方式,干脆给两个设备规划4个ip,分别为:

主路由 默认IP(10.1.1.1) 主路由辅助ip(10.1.1.11,用来登录主路由的web管理界面)

旁路由 工作IP(10.1.1.2) 旁路路由辅助ip(10.1.1.22,用来检测是否旁路由在线)

主路由负责dhcp服务,旁路由关闭dhcp。dhcp指定下游设备的网关均为旁路由工作IP(10.1.1.2)。

下文以openwrt为例(文末有Padavan/梅林的兼容实现),内核为5.15.148 版本git-25.050.75038-257d60d 使用 openwrt.ai 的在线编译固件 感谢 supes

主路由为一个4口ramips硬路由 旁路有为vm内的x86路由 已经配置好低调上网插件以及dns分流 广告屏蔽等。

# 双ip的实现

openwrt网络-接口面板,新建一个接口 和lan口一样 桥接 br-lan 然后静态ip配置为另外一个ip即可。参考/etc/config/network 中lan部分如下

主路由 正常工作状态 (主路由是一个四口硬路由) 用桥接方式配置了两个ip

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
config device
        option name 'br-lan'
        option type 'bridge'
        list ports 'lan1'
        list ports 'lan2'
        list ports 'lan3'
        list ports 'lan4'
        option promisc '1'

config interface 'lan'
        option device 'br-lan'
        option proto 'static'
        option ipaddr '10.1.1.1'
        option netmask '255.255.255.0'
        option ip6assign '60'
        option dns '223.5.5.5 114.114.114.114'
        
config interface 'lanManager'
        option proto 'static'
        option device 'br-lan'
        option ipaddr '10.1.1.11'
        option netmask '255.255.255.0'

旁路由正常工作状态 旁路由是一个单口虚拟机的openwrt 用桥接方式配置了两个ip

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
config device
        option name 'br-lan'
        option type 'bridge'
        list ports 'eth0'
        option promisc '1'
        
config interface 'lan'
        option device 'br-lan'
        option proto 'static'
        option ipaddr '10.1.1.2'
        option ipaddr '10.1.1.1'
        option netmask '255.255.255.0'
        option ip6assign '60'
        list dns '223.5.5.5'

config interface 'lanCheck'
        option proto 'static'
        option device 'br-lan'
        option ipaddr '10.1.1.22'
        option netmask '255.255.255.0'

两个路由器的lan口的配置截图 请参考 我的恩山帖子 https://www.right.com.cn/forum/thread-8355919-1-1.html

# openwrt 配置dhcp网关

主路由openwrt 配置dhcp服务分配给下游设备的网关为10.1.1.2 ssh登录到主路由后 运行下面两行命令 。

1
2
uci add_list dhcp.lan.dhcp_option="3,10.1.1.2"
uci commit dhcp

完成后重启dhcp 并重连下游设备,或干脆重启一下路由器。

dhcp_option的含义以及指定的下游设备通过dhcp分组或按照mac给下游设备分别配置不同网关功能,本文不扩展

# 检查状态

此时 下游设备dhcp分配的网关应该是10.1.1.2 在旁路由正常的情况下,下游被分配到10.1.1.2网关的设备应该都可以正常低调上网。

此时和传统旁路方案完全一致。旁路由断开后,下游设备无法上网,需要通过dhcp重新分配网关ip,下游设备断开重连或手动修改下游设备网关 才可以恢复网络。说不上完美,只能说凑合而已。

下面实现在旁路由下线后,主路由自动接替旁路由工作,并在旁路由上线后让位给旁路由。

# 自动切换程序

# openwrt 主路由

这个脚本运行在主路由上。 以openwrt为例。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
mkdir /opt
vi /opt/ReplaceBypass.sh
================================
#!/bin/sh
check_ip_available(){
    ping -c 3 $1 | grep packets | awk '{print $4}'
}
while true
do
    echo "ping 10.1.1.22 ..."
	res=`check_ip_available 10.1.1.22` 
	current_ip=`uci get network.lan.ipaddr`
	echo "current_ip $current_ip"
	if [ $(($res)) -eq 0 ]; then
		echo "bypass is offline"
		if [ "$current_ip" != "10.1.1.2" ]; then
			echo "change to 10.1.1.2"
			sed -i "s/10.1.1.1'/10.1.1.2'/" /etc/config/network
			ifdown lan && ifup lan
		fi
	else
		echo "bypass is online"
		if [ "$current_ip" != "10.1.1.1" ]; then
			echo "change to 10.1.1.1"
			sed -i "s/10.1.1.2'/10.1.1.1'/" /etc/config/network
			ifdown lan && ifup lan
		fi
	fi
    sleep 2 #时间可以修改为1-5秒 
done

这是一个循环shell脚本程序,间隔5秒用ping命令检测一次旁路由的辅助ip然后如果路由在线那么切换自己到10.1.1.1这个ip,否则切换到10.1.1.2替代路由工作。

先手动执行sh /opt/ReplaceBypass.sh,期间反复断开和联通旁路由观察 主路由ip切换情况。期间可以用 10.1.1.11 这个ip登录到主路由web管理界面检查。

测试正常后,我们在主路由创建一个服务来运行这个脚本,并并让openwrt的开机自启这个服务。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
vi /etc/init.d/ReplaceBypass 
===========================================
#!/bin/sh /etc/rc.common
START=99
start(){
        echo "ReplaceBypass service  is staring"
        sh /opt/ReplaceBypass.sh  > /dev/null 2>&1 &
}

stop(){
        PID=$(ps | grep "sh /opt/ReplaceBypass.sh" | grep -v grep | awk '{print $1}')
        kill $PID
        echo "ReplaceBypass service is stoped"
}

编辑完成后 启用这个服务

1
2
3
4
chmod +x /etc/init.d/ReplaceBypass # 必须执行
service ReplaceBypass enable # 开启自启
service ReplaceBypass start # 手动执行
ps |grep ReplaceBypass # 检查进程是否存在

# Padavan主路由

补充一个Padavan作为主路由的检测脚本,写完未测试 理论可行, 供参考。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
cat > /etc/storage/change_ip.sh << \EOF
#!/bin/bash
MainDefaultIp='10.1.1.1'
BypassWorkIp='10.1.1.2' 
BypassCheckIp='10.1.1.22'

check_ip_available(){ 
    ping -c 3 $1 | grep packets | awk '{print $4}'
}
res=`check_ip_available $BypassCheckIp`  #检测旁路由是否存在

current_ip=`nvram get lan_ipaddr`  #主路由当前ip 更多命令 nvram show

change_ip(){
   nvram set lan_ipaddr=$1  #设置ip
   nvram set lan_gateway=$1
   nvram commit  #提交修改
   sleep 3 
   reboot # 需要重启设备 老毛子单独重启lan口貌似无效
}

if [ $(($res)) -eq 0 ]; #即旁路由不存在,主路由应该把自己修改旁路路由的工作ip
then
    if [ "$current_ip" != "$BypassWorkIp" ]; then  #如果当前ip不是工作ip
       echo "change ip to $BypassWorkIp " 
       `change_ip $BypassWorkIp` 
    fi
    exit 1
fi
if [ $(($res)) -ne 0 ]; # 即旁路由存在,主路由应该把自己改为默认ip
then
    if [ "$current_ip" != "$MainDefaultIp" ]; then #如果当前ip不是默认ip
         echo "change ip to $MainDefaultIp " 
       `change_ip $MainDefaultIp`
    fi
    exit 1
fi
EOF

chmod +x   /etc/storage/change_ip.sh #设置脚本运行权限

/sbin/mtd_storage.sh save #保存脚本,防止重启丢失


# 自动定时运行脚本(每一分钟检测一次):
# 在老毛子的 `系统管理 - 服务 ` 调度任务 (Crontab)  加入 `*/1 * * * * /etc/storage/change_ip.sh` 

如果您在使用ikuai-bypass 方案,希望能给点个star

Licensed under CC BY-NC-SA 4.0
comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计