在之前文章《如何用 iStoreOS (OpenWrt) 实现多线上网 + 多线 IPTV》中,给粉丝朋友在 iStoreOS 中配置“电信上网 + 移动上网”以及“电信 IPTV + 广电 IPTV”的四口拆分与负载均衡。
当时配置主线路为电信线路,播放移动内网节目失败,后来粉丝有提到用静态路由配置,初步实现分流,让移动 IPTV 的单播源顺利走移动宽带拨号(PPPoE)出去了。
但这引出了一个非常致命的问题——断网重连后,电视就又看不了移动内网单播了!
🚨 为什么静态路由会“失效”?
在使用双线(电信为主,移动为辅)的场景下,为了让移动 IPTV(例如 CHINAMOBILE 接口)的内网流量强制走移动线路,通常会在 iStoreOS 的 网络 -> 路由 -> 静态 IPv4 路由 中手动指定 IP 段。
如图所示,我们需要把 39.0.0.0/8、120.0.0.0/8 等移动的 IP 段绑定到 CHINAMOBILE 接口,并指定网关 :
静态路由配置说明
初期配置好后,单播播放如丝般顺滑。但运营商的 PPPoE 拨号是动态 IP 和动态网关 的!
一旦路由器重启,拨号网关就变了(比如从 100.67.201.1 变成了 100.67.112.1)。但是,静态路由表里的网关依然是上一次填写的旧网关 。
此时,静态路由因为网关不可达而彻底失效,所有的移动 IPTV 单播流量就会“漏”到默认的电信主干线上,由于跨网鉴权失败,电视播放失败。
🛠️ 解决方案:用 Shell 脚本实现网关自动跟随
既然手动填写的静态网关无法应对动态变化的 PPPoE 网关,我们就写一个脚本,让路由器自己去对比实际网关和路由表网关 ,发现不一致就自动修改并重载网络 。
1. 编写自动监测脚本
我们在路由器的 /opt/scripts/ 目录下创建一个名为 sync_route.sh 的脚本(使用终端 SSH 登录操作):
#!/bin/sh
IFACE="CHINAMOBILE"
LOG="/mnt/sata1-4/cm.log"
MAX_LINES=100
# 获取当前时间
NOW=$(date '+%Y-%m-%d %H:%M:%S')
# 获取实际网关
REAL_GW=$(ubus call network.interface.${IFACE} status 2>/dev/null | \
grep -A3 '"target": "0.0.0.0"' | grep '"nexthop"' | \
grep -oE '[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+')
if [ -z "$REAL_GW" ]; then
echo"$NOW [!] ${IFACE} 当前未获取到有效网关,跳过。" >> "$LOG"
else
echo"$NOW => ${IFACE} 当前实际网关: ${REAL_GW}" >> "$LOG"
CHANGED=0
INDEX=0
whiletrue; do
ROUTE_IFACE=$(uci -q get network.@route[${INDEX}].interface 2>/dev/null)
[ -z "$ROUTE_IFACE" ] && break
if [ "$ROUTE_IFACE" = "$IFACE" ]; then
CONFIG_GW=$(uci -q get network.@route[${INDEX}].gateway)
if [ "$CONFIG_GW" != "$REAL_GW" ]; then
echo"$NOW [!] 发现不一致:静态路由 [@route[${INDEX}]] 原网关为 ${CONFIG_GW},已更新为 ${REAL_GW}。" >> "$LOG"
uci set network.@route[${INDEX}].gateway="$REAL_GW"
CHANGED=1
else
echo"$NOW [√] 静态路由 [@route[${INDEX}]] 网关已经是最新 (${CONFIG_GW}),无需修改。" >> "$LOG"
fi
fi
INDEX=$((INDEX + 1))
done
if [ "$CHANGED" = "1" ]; then
uci commit network
/etc/init.d/network reload
echo"$NOW => 配置已保存并重载生效。" >> "$LOG"
fi
fi
# 限制日志行数:保留最后100行覆盖回原文件
if [ -f "$LOG" ]; then
tail -n "$MAX_LINES""$LOG" > "${LOG}.tmp"
mv "${LOG}.tmp""$LOG"
fi
2. 赋予执行权限
脚本保存后,一定要赋予它执行权限,并解决可能存在的 Windows 换行符问题:
sed -i 's/\r$//' /opt/scripts/sync_route.sh
chmod +x /opt/scripts/sync_route.sh
3. 加入定时任务 (Cron),每 5 分钟自动巡检
在终端运行 crontab -e,添加以下内容:
*/5 * * * * /opt/scripts/sync_route.sh
然后重启 Cron 服务生效:/etc/init.d/cron restart。
🎯 效果实测:无感知的自动切换
完成上述配置后,让我们来看看实际效果!
- 日常状态下 ,脚本每 5 分钟巡检一次,发现实际网关和路由表网关一致,安安静静不打扰网络,并在日志中打上
[√]。
检测网口网关和路由网关是否一致
- 触发断线重连 ,我们模拟移动宽带掉线。接口重新拨号后,获取到了全新的网关:
100.67.112.1(原来是100.67.192.1)。
重新拨号网关变了
- 脚本介入 ,在下一个 5 分钟周期到来时,脚本敏锐地捕捉到了网关的变化!自动将静态路由表中的旧网关全部替换为新的
100.67.112.1,并执行了一次无感知的network reload。
自动更新路由网关和网口一致
刷新 iStoreOS 的静态路由页面,你会发现网关已经悄无声息地变成了最新的!
自动更新的路由表
电视画面仅卡顿了很短的时间(取决于重拨时间),就自动恢复了流畅播放,再也不用每次登录路由器后台手动改网关了!
💡 总结
通过 iStoreOS 自带的 ubus 和 uci 命令体系,配合简单的 Shell 脚本,我们完美补齐了传统“静态路由”无法应对动态 PPPoE 的短板。
多线多拨 + IPTV 融合确实是个折腾但充满乐趣的过程。如果你家里也是复杂的多宽带环境,不妨试试这个方案!
当然还可以用php脚本对特定url强制走特定网口,并实现内网转全网通使用,且看后面文章分享。
你还有哪些 OpenWrt 的奇淫巧技?欢迎在评论区留言交流!如果这篇文章解决了你的问题,别忘了点赞、在看、转发给同样爱折腾的朋友哦! 👇
📚 往期精彩文章推荐
🌟 与你互动
嗨~这里是【医工学习日志】的温暖小窝!
📩 随时戳一戳 :后台留言任何问题,树树会带着光速回复闪现!
💡 奇思妙想征集令 :
👉 遇到有趣资源?戳我分享!
👉 想看的硬核测评?甩题过来!
🔥 你的脑洞,可能成为下期爆款文章哦~
如需有偿部署服务或商务,请加V注明来意,不闲聊:

📝 栏目信息
策划编辑 ✨ 树树 ✨
技术支撑 @恩山无线论坛 & Github & 瀚思彼岸
📜 版权声明
内容说明:
-
原创文章转载请私信授权;
-
部分素材源自网络,版权归属原作者;
-
如觉侵权,请凭权属证明联系删除