引言 利用mwan3自带的可用性检测
,可以实现以下功能:
多网口负载均衡,并可根据网速分配调用概率。例:wanA:30mbps,wanB:30mbps,wanC:100mbps 则分配比例应为,3:3:10,以满足最大速率
自动软断开掉登录,不稳定的网口。
对软断开的网口执行登录指令
持续ping已断开的网口,检测到恢复时重新接入负载均衡。 由此,登录流程全自动,一次配置,长期免维护。理论上只要你可用于登录的账号够多,通过macvlan虚拟网口,可以一直把网速叠到链路上限(1000mbps),且稳定运行!下面让我来分享我的方法吧。注意,下面的脚本均适是为了openwrt、immotalwrt等系统设计的,对于windows,请对应修改登录脚本 学校在3月更新了检测方法,添加了对ua字段的检测 脚本仅用于计算机网络学习交流,请遵守校园网络使用规定
更新:2025/07/21 改用了新版本的总控脚本和登陆脚本 添加了图片,流程更好了 引导使用Ui创建Macvlan而非使用脚本
设备需求
支持多网口的可刷机设备(推荐软路由或支持第三方固件的路由器)
可安装mwan3且支持macvlan的系统环境 `兼容系统:OpenWrt、ImmortalWrt、iKuai等``
一台拥有网口的电脑,用于配置路由器。
RJ45网线一根。
配置原理 本方案通过mwan3的接口状态监控能力与自定义脚本联动,实现智能流量调度和故障自愈。核心原理如下:
graph TD
A[创建物理/虚拟网口] --> B[mwan3接口状态监控]
B --> C{接口在线?}
C -->|在线| D[按权重分配流量]
C -->|离线| E[触发总控脚本]
E --> F[执行对应登录脚本]
F --> G{认证成功?}
G -->|是| H[重置接口检测]
G -->|否| I[指数退避重试]
H --> J[恢复流量分配]
I --> E
J --> B
工作原理分解:
接口虚拟化 :通过macvlan创建虚拟网口,每个虚拟口拥有独立MAC地址,可绕过校园网单设备并发限制
状态监控 :mwan3持续ping测8.8.8.8
等稳定地址,根据响应判断接口在线状态
故障转移 :当检测到接口离线时:
立即从负载均衡池中移除该接口
触发总控脚本执行对应登录认证
智能重连 :采用指数退避算法控制重试频率(4s→8s→16s…→512s)
负载均衡 :基于接口带宽动态调整权重比例,计算公式:
1 权重值 = 接口实测带宽 / 基准带宽(取最小带宽为基准)
流量调度 :通过调整跃点数实现优先级控制,同跃点接口按权重比例分配流量
配置过程 安装mwan3 通过Web界面安装: 进入系统 -> 软件包
执行更新列表
,搜索安装luci-app-mwan3
或通过SSH执行:
1 opkg update && opkg install luci-app-mwan3
虚拟网口创建
使用web页面创建虚拟网口
在网络-> 接口 -> 设备 ->添加设备中创建虚拟网口
选择基础设备为你的WAN接口 对应设备(例如,我这里是eth0,创建了虚拟接口eth00,eth01,eth0x)。 设备名随意,但最好创建一个自己能记得住,分得清的名称。 不建议启用ipv6,mac地址随意/默认均可。 目前校园网支持同时登陆三个设备,所以你可以创建两个虚拟网口,以最大化单个账户。
登录认证脚本
登录脚本直接参与登录过程,直接执行登录脚本即可实现单次登录。后面会使用一个总控脚本来调控多个登录脚本。
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 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 #!/bin/sh MWAN3_NAME="wan" WAN_INTERFACE="eth0" WLAN_USER_ACCOUNT="在这里输入你的账户" WLAN_USER_PASSWORD="在这里输入你的密码" WLAN_USER_MAC=$(cat /sys/class/net/$WAN_INTERFACE /address) WLAN_USER_IP=$(ifconfig $WAN_INTERFACE | grep 'inet ' | awk '{print $2}' | sed 's/addr://' )log () { logger -t "drcom_auth[$WAN_INTERFACE ]" "$1 " echo "$1 " }check_status () { local status_url="http://10.254.7.4/drcom/chkstatus?callback=dr1002&jsVersion=4.X&v=5505&lang=zh" local response=$(mwan3 use $MWAN3_NAME curl $status_url ) local result=$(echo "$response " | grep -o '"result":[0-9]' | cut -d':' -f2) if [ "$result " = "1" ]; then log "当前已认证,无需重复登录" return 0 elif [ "$result " = "0" ]; then log "当前未认证,继续登录流程..." return 1 else log "状态检查失败,响应: $response " return 2 fi }do_login () { local URL_PC="http://10.254.7.4:801/eportal/portal/login?callback=dr1004&login_method=1&user_account=%2C0%2C$WLAN_USER_ACCOUNT &user_password=$WLAN_USER_PASSWORD &wlan_user_ip=$WLAN_USER_IP &wlan_user_ipv6=&wlan_user_mac=$WLAN_USER_MAC &wlan_ac_ip=&wlan_ac_name=&ua=$PC_UA &term_type=1&jsVersion=4.2&terminal_type=1&lang=zh-cn&v=9875&lang=zh" local URL_MOBILE="http://10.254.7.4:801/eportal/portal/login?callback=dr1005&login_method=1&user_account=%2C1%2C$WLAN_USER_ACCOUNT &user_password=$WLAN_USER_PASSWORD &wlan_user_ip=$WLAN_USER_IP &wlan_user_ipv6=&wlan_user_mac=$WLAN_USER_MAC &wlan_ac_ip=&wlan_ac_name=&ua=$MOBILE_UA &term_type=2&jsVersion=4.2&terminal_type=2&lang=zh-cn&v=7090&lang=zh" log "尝试登录,使用IP: $WLAN_USER_IP , MAC: $WLAN_USER_MAC " local response=$(mwan3 use $MWAN3_NAME curl -s "$URL_MOBILE " ) local json_response=$(echo "$response " | grep -o '{.*}' ) if [ -n "$json_response " ]; then if echo "$json_response " | grep -q '"result":1' ; then log "登录成功!响应: $json_response IP: $WLAN_USER_IP " return 0 else log "登录失败!响应: $json_response " return 1 fi else log "无法解析响应: $response " return 1 fi }main () { check_status case $? in 0) exit 2 ;; 1) if do_login; then exit 0 else exit 1 fi ;; *) exit 3 ;; esac } main
将以上文本保存为:eth0_login.sh 然后根据自身需求修改: 网口名称,校园网账号,密码。以及登录使用的网口 这里的两个不同的接口是怎么回事呢?见图
一个是wrt软件接口名称,一个是硬件名称,有区分的必要。使用接口名称来调用mwan3的 mwan3 use
命令,更精确。 使用网口名称来获取 ip 和 mac
地址
1 2 3 MWAN3_NAME="wan" WAN_INTERFACE="wan"
由于校园网支持同时登录一个安卓设备和两个电脑设备,所以你可以登录自己的账号三次 ,网速x3 如果想要占用pc设备位,修改上述登录脚本的这个部分:
1 2 3 4 5 6 do_login() ... log "尝试登录,使用IP: $WLAN_USER_IP , MAC: $WLAN_USER_MAC " local response=$(mwan3 use $MWAN3_NAME curl -s "$URL_MOBILE " )<- 修改这一行的"$URL_MOBILE " 为"$URL_PC " ...
例如,根据上面创建的MACVLAN网口(假设你和我一样命名为eth01和eth02),那么你将拥有: 一个物理网口,两个虚拟网口。三个登录脚本:eth0_login.sh
,eth01_login.sh
,eth02_login.sh
其中,任意两个使用pc_url,另外一个使用mobile_url
上传脚本
将*_login.sh
上传至路由器推荐路径:/root/
使用MobaXterm等工具赋予可执行权限:
测试登录脚本 在shell中执行: 登录脚本
预期输出:wan 登录成功!
获取到的IP地址xx.xxx.xx.xx
或者当前已认证,无需重复登录
如果输出与预期不符,请结合ai,文档检查错误。
总控脚本
该部分脚本利用mwan3接口获取接口可用性,对状态为非“online”的接口,执行其登录脚本。
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 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 #!/bin/bash INTERFACE_CONFIG=" wan /root/login_shell/eth00_login.sh " INITIAL_RETRY_DELAY=4 MAX_RETRY_DELAY=4096 ALREADY_LOGGED_DELAY=16 log () { local level=$1 local message=$2 case "$level " in "debug" ) return ;; "info" |"notice" |"warning" |"error" ) logger -t "drcom_auth[$$]" -p "user.$level " "[$level ] $message " ;; *) logger -t "drcom_auth[$$]" -p "user.info" "[unknown] $message " ;; esac }login_interface () { local interface_name=$1 local login_script=$2 local delay_var=$3 eval "current_delay=\${$delay_var }" [ -f "$login_script " ] || { log "error" "$interface_name 错误:登录脚本 '$login_script ' 未找到" return 3 } sh "$login_script " >/tmp/login_output_$interface_name 2>&1 local login_result=$? local login_output=$(cat /tmp/login_output_$interface_name ) rm -f /tmp/login_output_$interface_name case $login_result in 0) new_delay=$INITIAL_RETRY_DELAY eval "$delay_var =$new_delay " log "notice" "$interface_name 登录成功 - 重置延迟为 $new_delay 秒" log "debug" "登录输出: $login_output " return 0 ;; 1) new_delay=$(( current_delay * 2 )) [ $new_delay -gt $MAX_RETRY_DELAY ] && new_delay=$MAX_RETRY_DELAY eval "$delay_var =$new_delay " log "warning" "$interface_name 登录失败 - 下次延迟为 $new_delay 秒" log "debug" "失败输出: $login_output " return 1 ;; 2) eval "$delay_var =$ALREADY_LOGGED_DELAY " log "info" "$interface_name 已登录状态 - 设置固定延迟 $ALREADY_LOGGED_DELAY 秒" return 2 ;; *) log "error" "$interface_name 未知返回码 $login_result " log "debug" "完整输出: $login_output " return 3 ;; esac }main () { local interfaces=() local scripts=() local delays=() while IFS= read -r line; do line=$(echo "$line " | awk '{$1=$1; print}' ) [ -z "$line " ] && continue interface=$(echo "$line " | awk '{print $1}' ) path=$(echo "$line " | awk '{print $2}' ) interfaces+=("$interface " ) scripts+=("$path " ) eval "delay_$interface =$INITIAL_RETRY_DELAY " delays+=("delay_$interface " ) done <<EOF $INTERFACE_CONFIG EOF log "info" "启动多WAN口自动登录守护进程 (PID: $$)" log "debug" "加载接口配置: ${interfaces[@]} " while true ; do local max_delay=1 local interface_status=$(mwan3 interfaces 2>/dev/null) local need_action=false for ((i=0 ; i<${#interfaces[@]} ; i++)); do local iface="${interfaces[i]} " local script="${scripts[i]} " local delay_var="${delays[i]} " if echo "$interface_status " | grep -qw "interface $iface is offline" ; then need_action=true log "debug" "$iface 检测到离线状态" login_interface "$iface " "$script " "$delay_var " retval=$? eval "current_delay=\${$delay_var }" [ $current_delay -gt $max_delay ] && max_delay=$current_delay case $retval in 0) log "info" "$iface 处理完成: 登录成功" ;; 1) log "warning" "$iface 处理完成: 登录失败" ;; 2) log "info" "$iface 处理完成: 已登录但掉线" ;; 3) log "error" "$iface 处理完成: 脚本错误" ;; esac else eval "$delay_var =$INITIAL_RETRY_DELAY " log "debug" "$iface 在线状态正常" fi done if $need_action ; then log "debug" "本轮检测完成,最大延迟 $max_delay 秒" sleep $max_delay else log "debug" "所有接口正常,短暂休眠 5 秒" sleep 5 fi done }trap 'log "notice" "收到终止信号,退出程序"; exit 0' INT TERM main
图形化配置 创建接口
进入网络 -> 接口 -> 添加新接口
命名规则:wanA、wanB…
协议选择DHCP客户端
设备 选择你创建的虚拟设备eth01等 点击创建接口。
接口参数
高级设置中设置唯一网关跃点
防火墙区域指定为wan
确保勾选忽略此接口
(DHCP服务)
mwan3配置
进入网络 -> 负载均衡 -> 接口
删除默认接口,新建对应虚拟接口
每个接口配置:
启用状态:√
追踪地址:223.5.5.5,223.6.6.6,114.114.114
跟踪可靠性:建议2
检测间隔:建议5秒
检测超时:建议2秒 其余设置看图:
编辑接口成员(用于分配负载)
解释:跃点数代表接口优先级,权重则代表该接口在同跃点数中占的比重。
成员配置示例:
wan_m1_w3(跃点1,权重3)
wanA_m1_w2(跃点1,权重2)
注意,若使用不同的跃点数,wan_m1_w2,wanA_m2_w3,那么wan将 占用100%的流量 ,wanA 占比为0% 完成修改后,请点击保持并应用。保存自己的更改。 请根据需求添加成员 例如:两个同速率的接口,请使用 相同的跃点和相同的权重。wan_m1_w2,wanA_m1_w2。
修改策略
选择 策略 页面
修改策略 balanced 删除原先自带的策略。把自己上面添加的成员写上去。
例:wan_m1_w2,wanA_m1_w2
确认规则 确认default_rule_v4
使用新建的均衡策略
运行
这里推荐使用图形化的shell脚本管理器nettask来运行管理脚本。nettask下载
下载完成luci-app-nettask.ipk后,上传到任意位置,使用opkg install安装即可 例如 opkg install /root/luci-app-nettask.ipk
安装完成后刷新luci网页。在系统->自定义脚本
下的 立即执行
中粘贴上方的 自己修改好的 总控脚本
如果不清楚应该怎么修改,请结合gpt等ai工具,它会帮助你。
点击保存后,立即执行。 在状态->系统日志 中应当能看到对于的登录日志。
成功 在这步之后,应当就能正常负载均衡上网了!
状态验证
在状态 -> 负载均衡
中确认各接口在线状态
典型正常状态显示:
1 接口 wan 状态 在线 运行时间 12 h :34 m:56 s
如果不是这样,请点击详细信息,检查interface status。
如果接口状态全部为error,请检查网关跃点和mwan3配置。
如果重启路由器后,接口状态为error,请尝试随便修改一点mwan3的什么。(例如修改规则的顺序)然后点击保存并应用,自动重启mwan3 后,状态恢复正常。
我也不知道为什么会有这种情况,能用就行(
结语 本方案通过智能流量调度和自动故障恢复机制,可有效提升网络可靠性和吞吐量。实际测试中,在配置3个虚拟接口的情况下,(两个30Mbps,一个100Mbps)实现了长期稳定的200Mbps寝室网络接入。并可分享给全寝室人用。