ImmortalWrt-QOS 脚本
———————————-
复制粘贴到xxx.sh 文件内,
上传路由器,
chmod 755 xxx.sh 修改权限,
直接运行。
——————————————
脚本使用 deepseekv4-pro 生成;
测试路由器环境:
RedMi AX6S 刷入 ImmortalWrt 25.12.0-rc2
按照脚本生成的测试命令,反馈给AI,AI说已正常运行,实际体验还可以。
———————————————-
公寓带宽上传约9M、下载约30M。
填写时可少写1~10M,防止占用过高。
————————————————-
测试内网环境:
1电脑、5手机,电脑游戏多开,手机刷bilibili。
电脑单开游戏流畅无掉线(CF、英雄联盟、300英雄)。
电脑多开游戏卡顿小概率掉线(后台双开300英雄,前台战地5或CF,其中一个300英雄延迟会非常高,40%概率掉线,但CF 或 战地 不会掉线)
手机B站视频缓冲3-6秒,不快进或加速播放可流畅观看,快进则缓冲3-10秒。(480p缓冲3-5秒、720缓冲5-8秒、1080缓冲6-9秒,估计大概是这个范围)
总结:带宽太小,估计下载35M-40M,上传10M-13M,5台设备同时用网,不会有缓冲。
若使用出现问题,请使用 deepseekv4-pro,复制粘贴代码 和 报错信息,让AI解决。
——————————————————————–
修改的参数位置:
ctrl+f 搜索,然后修改以下位置的参数(kbit):
—- 网络接口配置 —-
—- 带宽配置(kbit)—-
—- 上传各类保证带宽(kbit)—-
—- 下载各类保证带宽(kbit)—-
—————————————————————————
#!/bin/sh
# ============================================================
# ImmortalWrt 智能 QoS 游戏优化版 v2.5
# 文件名: qos-game-optimized.sh
# 适用平台: ImmortalWrt 25.10 R2 (apk包管理器)
# ============================================================
# ============================================================
# 【脚本大纲】
# ============================================================
#
# 零、执行前检查
# 0.1 检查root权限
# 0.2 检测包管理器类型(apk/opkg)
# 0.3 检查并安装依赖包(apk方式)
# 0.4 检测网络接口(WAN/IPv6/LAN)
# 0.5 验证关键内核模块
#
# 一、环境准备
# 1.1 备份当前规则(iptables + tc)
# 1.2 清理旧QoS规则(包括IPv6接口)
# 1.3 加载内核模块(静默+验证)
# 1.4 配置用户参数(带宽/优先级/端口)
#
# 二、虚拟网卡初始化
# 2.1 创建/复用ifb0(上传整形)
# 2.2 创建/复用ifb1(下载整形)
# 2.3 启用虚拟网卡
#
# 三、HTB队列配置
# 3.1 上传HTB队列树(ifb0)
# - 根队列 1:(总带宽控制)
# - 子类 1:10~50(优先级队列)
# - 叶子qdisc: fq_codel(自动回退pfifo)
# 3.2 下载HTB队列树(ifb1)
# - 根队列 2:(总带宽控制)
# - 子类 2:10~50(优先级队列)
# - 叶子qdisc: fq_codel(自动回退pfifo)
#
# 四、流量重定向配置
# 4.1 下行重定向(支持多接口IPv4/IPv6分离)
# - 检测IPv6接口(pppoe-wan/pppoe-wan6/wan6)
# - IPv4: WAN ingress → ifb1
# - IPv6: 独立接口或共用接口处理
# 4.2 上传重定向(支持多接口IPv4/IPv6分离)
# - IPv4: WAN egress → ifb0
# - IPv6: 独立接口或共用接口处理
#
# 五、防火墙标记规则
# 5.1 游戏流量识别(P10 - 最高优先级)
# - UDP游戏端口范围(5060-60000)
# - TCP游戏管理端口
# - UDP小包特征(1024-65535, len≤512)
# 5.2 DNS/ICMP/小包标记(P15 - 次高优先级)
# - DNS查询(UDP/TCP 53)
# - ICMP/ICMPv6控制报文
# - 非UDP小包(≤256字节)
# 5.3 微信/支付/通讯标记(P20 - 中高优先级)
# - 微信专用端口
# - SNI字符串匹配(weixin/wechat)
# 5.4 普通网页标记(P25 - 中等优先级)
# - HTTP/HTTPS/QUIC
# 5.5 视频/下载标记(P35 - 低优先级)
# - 视频平台SNI匹配
# - 大流量端口
# 5.6 默认流量标记(P30 - 中低优先级)
# 5.7 Conntrack标记保存(IPv4+IPv6)
#
# 六、FW过滤器绑定
# 6.1 ifb0 fw过滤器(上传方向,mark→class映射)
# 6.2 ifb1 fw过滤器(下载方向,mark→class映射)
#
# 七、验证与监控
# 7.1 规则统计输出
# 7.2 IPv6支持状态
# 7.3 游戏连接统计
# 7.4 验证命令和故障排查
#
# ============================================================
# 【依赖包说明 - apk版本】
# ============================================================
#
# 【必需包】(apk包名可能与opkg不同)
# - kmod-ifb : 虚拟网卡ifb模块
# - kmod-sched-connmark : tc connmark action
# - kmod-sched-core : tc调度核心(HTB、fq_codel等)
# - kmod-ipt-connmark : CONNMARK目标
# - iptables-mod-extra : multiport、string、length匹配
# - tc-tiny 或 tc-full : 流量控制工具
# - ip-tiny 或 ip-full : iproute2工具
# - iptables-nft 或 iptables-legacy : 防火墙工具
#
# 【安装命令 - apk】
# apk update
# apk add kmod-ifb kmod-sched-connmark kmod-sched-core \
# kmod-ipt-connmark iptables-mod-extra tc-tiny ip-tiny
#
# 【可选包】
# - kmod-ipt-ipopt : IP选项匹配
# - conntrack-tools : 连接跟踪调试工具
#
# ============================================================
# 【核心概念讲解】
# ============================================================
#
# 1. IFB(Intermediate Functional Block)
# - 虚拟网络设备,用于流量重定向和整形
# - ifb0: 处理上传流量(egress方向重定向)
# - ifb1: 处理下载流量(ingress方向重定向)
#
# 2. HTB(Hierarchical Token Bucket)
# - 层次化令牌桶算法
# - rate: 保证带宽(kbit/s)
# - ceil: 最大可借用带宽
# - prio: 优先级(0-7,0最高)
# - quantum: 每次轮询发送的字节数
#
# 3. fq_codel(Fair Queueing with Controlled Delay)
# - 公平排队 + CoDel AQM算法
# - 在同一类内部公平分配带宽
# - 减少bufferbloat,降低延迟
#
# 4. CONNMARK机制
# - 上传: iptables设置skb->mark → CONNMARK保存到conntrack
# - 下载: tc action connmark恢复conntrack标记 → 对称QoS
#
# 5. 标记系统(fwmark → HTB类映射)
# - 10: 游戏/语音(最高优先级, prio 0)
# - 15: DNS/ICMP/小包(prio 1)
# - 20: 微信/支付(prio 2)
# - 25: 普通网页(prio 3)
# - 30: 默认流量(prio 4)
# - 35: 视频/下载(prio 5)
# - 40-50: 备用保留
#
# ============================================================
# 【常见游戏端口参考】
# ============================================================
#
# Steam: TCP 27014-27050, UDP 27000-27100, 3478
# 英雄联盟: TCP 2099, 5222-5223, UDP 5000-5500
# CS:GO: UDP 27000-27030, 3478
# DOTA2: UDP 27000-27100
# PUBG: UDP 7000-8000, 10000-20000
# 堡垒之夜: UDP 9000-9100, 3478-3479
# Discord: UDP 3478-3481, 50000-60000
#
# ============================================================
# ============================================================
# 第零步:执行前检查
# ============================================================
echo "=========================================="
echo " ImmortalWrt 游戏优化 QoS v2.5"
echo " 适配版本: 25.10 R2 (apk)"
echo "=========================================="
echo ""
# 0.1 检查root权限
if [ "$(id -u)" != "0" ]; then
echo "❌ 错误: 此脚本必须以root身份运行"
exit 1
fi
echo "✓ Root权限检查通过"
# 0.2 检测包管理器类型
echo "→ 检测包管理器..."
PKG_MGR=""
if command -v apk >/dev/null 2>&1; then
PKG_MGR="apk"
echo " ✓ 检测到apk包管理器 (25.10 R2+)"
elif command -v opkg >/dev/null 2>&1; then
PKG_MGR="opkg"
echo " ✓ 检测到opkg包管理器 (旧版本)"
else
echo " ❌ 未找到包管理器,请手动安装依赖"
exit 1
fi
# 0.3 检查并安装依赖包(已适配25.10 R2包名)
echo "→ 检查依赖包..."
# 定义依赖包列表(按包管理器分组)
if [ "$PKG_MGR" = "apk" ]; then
# 25.10 R2的正确包名
REQUIRED_PKGS="kmod-ifb kmod-sched-core kmod-sched-connmark kmod-ipt-extra tc-tiny ip-tiny iptables-zz-legacy"
elif [ "$PKG_MGR" = "opkg" ]; then
# 旧版本的包名(兼容)
REQUIRED_PKGS="kmod-ifb kmod-sched-connmark kmod-sched-core kmod-ipt-connmark iptables-mod-extra tc ip"
fi
MISSING_PKGS=""
# 检查缺失的包
for pkg in $REQUIRED_PKGS; do
if [ "$PKG_MGR" = "apk" ]; then
if ! apk info -e "$pkg" >/dev/null 2>&1; then
MISSING_PKGS="$MISSING_PKGS $pkg"
fi
elif [ "$PKG_MGR" = "opkg" ]; then
if ! opkg list-installed 2>/dev/null | grep -q "^$pkg "; then
MISSING_PKGS="$MISSING_PKGS $pkg"
fi
fi
done
if [ -n "$MISSING_PKGS" ]; then
echo " ⚠ 以下依赖包未安装:$MISSING_PKGS"
echo " → 尝试自动安装..."
if [ "$PKG_MGR" = "apk" ]; then
apk update 2>/dev/null
for pkg in $MISSING_PKGS; do
echo " 安装 $pkg..."
apk add "$pkg" 2>/dev/null
if [ $? -eq 0 ]; then
echo " ✓ $pkg 安装成功"
else
echo " ❌ $pkg 安装失败,请手动执行: apk add $pkg"
fi
done
elif [ "$PKG_MGR" = "opkg" ]; then
opkg update 2>/dev/null
for pkg in $MISSING_PKGS; do
echo " 安装 $pkg..."
opkg install "$pkg" 2>/dev/null
if [ $? -eq 0 ]; then
echo " ✓ $pkg 安装成功"
else
echo " ❌ $pkg 安装失败,请手动执行: opkg install $pkg"
fi
done
fi
else
echo " ✓ 所有依赖包已安装"
fi
echo ""
# ============================================================
# 第一步:环境准备
# ============================================================
echo "==> 第一步:环境准备"
# 1.1 备份当前规则
echo " → 备份当前iptables规则..."
BACKUP_FILE="/tmp/qos_backup_$(date +%Y%m%d_%H%M%S)"
iptables-save > "${BACKUP_FILE}_iptables.txt" 2>/dev/null
ip6tables-save > "${BACKUP_FILE}_ip6tables.txt" 2>/dev/null
echo " 备份已保存到: ${BACKUP_FILE}_*"
# 1.2 清理旧规则
echo " → 清理旧防火墙规则..."
iptables -t mangle -F FORWARD 2>/dev/null
iptables -t mangle -X 2>/dev/null
ip6tables -t mangle -F FORWARD 2>/dev/null
ip6tables -t mangle -X 2>/dev/null
echo " → 清理旧tc规则..."
# 清理IFB接口
tc qdisc del dev ifb0 root 2>/dev/null
tc qdisc del dev ifb1 root 2>/dev/null
# 清理WAN接口
WAN_INTERFACES="pppoe-wan pppoe-wan6 wan6 eth0 eth1 wan"
for iface in $WAN_INTERFACES; do
if ip link show "$iface" >/dev/null 2>&1; then
tc qdisc del dev "$iface" ingress 2>/dev/null
tc qdisc del dev "$iface" root 2>/dev/null
fi
done
# 1.3 加载内核模块
echo " → 加载内核模块..."
# 静默加载,不显示非关键警告
modprobe ifb numifbs=2 2>/dev/null || true
modprobe xt_MARK 2>/dev/null || true
modprobe xt_connmark 2>/dev/null || true
modprobe xt_multiport 2>/dev/null || true
modprobe xt_string 2>/dev/null || true
modprobe xt_length 2>/dev/null || true
modprobe xt_comment 2>/dev/null || true
modprobe act_connmark 2>/dev/null || true
modprobe act_mirred 2>/dev/null || true
modprobe sch_htb 2>/dev/null || true
modprobe sch_fq_codel 2>/dev/null || true
modprobe cls_fw 2>/dev/null || true
modprobe cls_u32 2>/dev/null || true
# 验证关键模块
echo " → 验证关键模块..."
CRITICAL_MODS="ifb sch_htb cls_fw act_mirred"
for mod in $CRITICAL_MODS; do
if lsmod | grep -q "^$mod "; then
echo " ✓ $mod"
else
echo " ⚠ $mod 未加载,QoS可能无法正常工作"
fi
done
# 1.4 配置用户参数
echo " → 配置网络参数..."
# ---- 网络接口配置 ----
WAN="pppoe-wan" # 主WAN接口(IPv4)
LAN_IF="br-lan" # 内网接口
LAN_SUBNET="192.168.254.0/24" # 内网IPv4网段
# ---- 检测IPv6接口 ----
echo " → 检测IPv6接口..."
WAN_IPV6=""
IPV6_SUPPORT=0
# 检查主WAN口是否有IPv6
if ip -6 addr show dev "$WAN" 2>/dev/null | grep -q "inet6.*global"; then
WAN_IPV6="$WAN"
IPV6_SUPPORT=1
echo " ✓ 检测到IPv6在主WAN口: $WAN"
fi
# 检查pppoe-wan6接口
if [ $IPV6_SUPPORT -eq 0 ] && ip link show pppoe-wan6 2>/dev/null | grep -q "UP"; then
WAN_IPV6="pppoe-wan6"
IPV6_SUPPORT=1
echo " ✓ 检测到IPv6专用接口: pppoe-wan6"
fi
# 检查wan6接口
if [ $IPV6_SUPPORT -eq 0 ] && ip link show wan6 2>/dev/null | grep -q "UP"; then
WAN_IPV6="wan6"
IPV6_SUPPORT=1
echo " ✓ 检测到IPv6接口: wan6"
fi
# 自动检测其他IPv6接口
if [ $IPV6_SUPPORT -eq 0 ]; then
for iface in $(ip -6 addr show 2>/dev/null | grep "inet6.*global" | awk '{print $NF}' | sort -u); do
if [ "$iface" != "$LAN_IF" ] && [ "$iface" != "lo" ] && [ -n "$iface" ]; then
WAN_IPV6="$iface"
IPV6_SUPPORT=1
echo " ✓ 自动检测到IPv6接口: $WAN_IPV6"
break
fi
done
fi
if [ $IPV6_SUPPORT -eq 0 ]; then
echo " ⚠ 未检测到IPv6全局地址,IPv6 QoS将禁用"
fi
# ---- 带宽配置(kbit)----
UP_BW="8000" # 上行总带宽(约8Mbps)
DOWN_BW="27000" # 下行总带宽(约27Mbps)
BURST="160k" # 突发流量大小
# ---- 上传各类保证带宽(kbit)----
UP_P10="2500" # 游戏(最高优先级)
UP_P15="800" # DNS/小包
UP_P20="600" # 微信/支付
UP_P25="800" # 网页
UP_P30="1500" # 默认
UP_P35="500" # 视频/下载
UP_SPARE="300" # 备用类
# ---- 下载各类保证带宽(kbit)----
DL_P10="5500" # 游戏
DL_P15="3000" # DNS/小包
DL_P20="2000" # 微信/支付
DL_P25="4000" # 网页
DL_P30="6000" # 默认
DL_P35="3000" # 视频/下载
DL_SPARE="1000" # 备用类
echo ""
# ============================================================
# 第二步:虚拟网卡初始化
# ============================================================
echo "==> 第二步:初始化IFB虚拟网卡"
# 2.1 创建ifb0
if ip link show ifb0 >/dev/null 2>&1; then
echo " ✓ ifb0已存在"
else
ip link add ifb0 type ifb 2>/dev/null
if [ $? -eq 0 ]; then
echo " ✓ ifb0创建成功"
else
echo " ❌ ifb0创建失败,请检查kmod-ifb是否安装"
exit 1
fi
fi
# 2.2 创建ifb1
if ip link show ifb1 >/dev/null 2>&1; then
echo " ✓ ifb1已存在"
else
ip link add ifb1 type ifb 2>/dev/null
if [ $? -eq 0 ]; then
echo " ✓ ifb1创建成功"
else
echo " ❌ ifb1创建失败"
exit 1
fi
fi
# 2.3 启用虚拟网卡
ip link set ifb0 up
ip link set ifb1 up
echo " ✓ ifb0/ifb1已启用"
echo ""
# ============================================================
# 第三步:HTB队列配置
# ============================================================
echo "==> 第三步:配置HTB队列"
# ---------- 3.1 上传HTB队列 (ifb0) ----------
echo " → 配置上传队列 (ifb0)..."
tc qdisc del dev ifb0 root 2>/dev/null
tc qdisc add dev ifb0 root handle 1: htb default 30 r2q 1
# 根类
tc class add dev ifb0 parent 1: classid 1:1 htb \
rate ${UP_BW}kbit ceil ${UP_BW}kbit quantum 1500 burst $BURST
echo " ✓ 上传根类创建完成 (${UP_BW}kbit)"
# 子类
for cls in 10 15 20 25 30 35 40 45 50; do
eval rate=\${UP_P${cls}:-$UP_SPARE}
prio=$(( (cls-10)/5 ))
[ $prio -gt 7 ] && prio=7
tc class add dev ifb0 parent 1:1 classid 1:${cls} htb \
rate ${rate}kbit ceil ${UP_BW}kbit prio $prio quantum 1500 burst $BURST
# 优先使用fq_codel,失败则使用pfifo
tc qdisc add dev ifb0 parent 1:${cls} fq_codel limit 1000 2>/dev/null || \
tc qdisc add dev ifb0 parent 1:${cls} pfifo limit 1000
done
echo " ✓ 上传子类创建完成"
echo " P10(游戏):${UP_P10}kbit P15:${UP_P15}kbit P20:${UP_P20}kbit"
echo " P25(网页):${UP_P25}kbit P30:${UP_P30}kbit P35(视频):${UP_P35}kbit"
# ---------- 3.2 下载HTB队列 (ifb1) ----------
echo " → 配置下载队列 (ifb1)..."
tc qdisc del dev ifb1 root 2>/dev/null
tc qdisc add dev ifb1 root handle 2: htb default 30 r2q 1
# 根类
tc class add dev ifb1 parent 2: classid 2:1 htb \
rate ${DOWN_BW}kbit ceil ${DOWN_BW}kbit quantum 1500 burst $BURST
echo " ✓ 下载根类创建完成 (${DOWN_BW}kbit)"
# 子类
for cls in 10 15 20 25 30 35 40 45 50; do
eval rate=\${DL_P${cls}:-$DL_SPARE}
prio=$(( (cls-10)/5 ))
[ $prio -gt 7 ] && prio=7
tc class add dev ifb1 parent 2:1 classid 2:${cls} htb \
rate ${rate}kbit ceil ${DOWN_BW}kbit prio $prio quantum 1500 burst $BURST
tc qdisc add dev ifb1 parent 2:${cls} fq_codel limit 1000 2>/dev/null || \
tc qdisc add dev ifb1 parent 2:${cls} pfifo limit 1000
done
echo " ✓ 下载子类创建完成"
echo " P10(游戏):${DL_P10}kbit P15:${DL_P15}kbit P20:${DL_P20}kbit"
echo " P25(网页):${DL_P25}kbit P30:${DL_P30}kbit P35(视频):${DL_P35}kbit"
echo ""
# ============================================================
# 第四步:流量重定向配置
# ============================================================
echo "==> 第四步:配置流量重定向"
# ---------- 4.1 下行重定向(WAN ingress → ifb1)----------
echo " → 配置下行重定向..."
# IPv4下行重定向
tc qdisc del dev "$WAN" ingress 2>/dev/null
tc qdisc add dev "$WAN" handle ffff: ingress
tc filter add dev "$WAN" parent ffff: protocol ip prio 1 u32 \
match u32 0 0 \
action connmark \
action mirred egress redirect dev ifb1
echo " ✓ IPv4下行重定向已配置"
# IPv6下行重定向
if [ $IPV6_SUPPORT -eq 1 ]; then
if [ "$WAN_IPV6" = "$WAN" ]; then
# IPv6和IPv4在同一接口
tc filter add dev "$WAN" parent ffff: protocol ipv6 prio 2 u32 \
match u32 0 0 \
action connmark \
action mirred egress redirect dev ifb1 2>/dev/null
if [ $? -eq 0 ]; then
echo " ✓ IPv6下行重定向已配置(共用接口)"
else
echo " ⚠ IPv6下行重定向失败,尝试备用方法..."
# 备用方法:在root qdisc上重定向
tc qdisc add dev "$WAN" root handle 5: htb default 1 r2q 1 2>/dev/null
tc class add dev "$WAN" parent 5: classid 5:1 htb rate 100mbit 2>/dev/null
tc filter add dev "$WAN" parent 5: protocol ipv6 prio 1 u32 \
match u32 0 0 \
action connmark \
action mirred egress redirect dev ifb1 2>/dev/null
[ $? -eq 0 ] && echo " ✓ IPv6下行重定向已配置(备用方法)" || echo " ❌ IPv6下行重定向失败"
fi
else
# IPv6在独立接口上
tc qdisc del dev "$WAN_IPV6" ingress 2>/dev/null
tc qdisc add dev "$WAN_IPV6" handle ffff: ingress 2>/dev/null
if [ $? -eq 0 ]; then
tc filter add dev "$WAN_IPV6" parent ffff: protocol ipv6 prio 1 u32 \
match u32 0 0 \
action connmark \
action mirred egress redirect dev ifb1 2>/dev/null
if [ $? -eq 0 ]; then
echo " ✓ IPv6下行重定向已配置(接口: $WAN_IPV6)"
else
echo " ⚠ IPv6 filter添加失败,尝试root qdisc方法..."
tc qdisc add dev "$WAN_IPV6" root handle 6: htb default 1 r2q 1 2>/dev/null
tc class add dev "$WAN_IPV6" parent 6: classid 6:1 htb rate 100mbit 2>/dev/null
tc filter add dev "$WAN_IPV6" parent 6: protocol ipv6 prio 1 u32 \
match u32 0 0 \
action connmark \
action mirred egress redirect dev ifb1 2>/dev/null
[ $? -eq 0 ] && echo " ✓ IPv6下行重定向已配置(备用方法)" || echo " ❌ IPv6下行重定向失败"
fi
else
echo " ⚠ IPv6接口不支持ingress,使用root qdisc方法..."
tc qdisc add dev "$WAN_IPV6" root handle 6: htb default 1 r2q 1 2>/dev/null
tc class add dev "$WAN_IPV6" parent 6: classid 6:1 htb rate 100mbit 2>/dev/null
tc filter add dev "$WAN_IPV6" parent 6: protocol ipv6 prio 1 u32 \
match u32 0 0 \
action connmark \
action mirred egress redirect dev ifb1 2>/dev/null
[ $? -eq 0 ] && echo " ✓ IPv6下行重定向已配置(备用方法)" || echo " ❌ IPv6下行重定向失败"
fi
fi
fi
# ---------- 4.2 上传重定向(WAN egress → ifb0)----------
echo " → 配置上传重定向..."
# IPv4上传重定向
tc qdisc del dev "$WAN" root 2>/dev/null
tc qdisc add dev "$WAN" root handle 3: htb default 1 r2q 1
tc class add dev "$WAN" parent 3: classid 3:1 htb rate 100mbit
tc filter add dev "$WAN" parent 3: protocol ip prio 1 u32 \
match u32 0 0 \
action mirred egress redirect dev ifb0
echo " ✓ IPv4上传重定向已配置"
# IPv6上传重定向
if [ $IPV6_SUPPORT -eq 1 ]; then
if [ "$WAN_IPV6" = "$WAN" ]; then
# IPv6和IPv4在同一接口
tc filter add dev "$WAN" parent 3: protocol ipv6 prio 2 u32 \
match u32 0 0 \
action mirred egress redirect dev ifb0 2>/dev/null
if [ $? -eq 0 ]; then
echo " ✓ IPv6上传重定向已配置(共用接口)"
else
echo " ⚠ IPv6上传重定向失败,接口可能不支持IPv6 filter"
fi
else
# IPv6在独立接口上
tc qdisc del dev "$WAN_IPV6" root 2>/dev/null
tc qdisc add dev "$WAN_IPV6" root handle 7: htb default 1 r2q 1 2>/dev/null
tc class add dev "$WAN_IPV6" parent 7: classid 7:1 htb rate 100mbit 2>/dev/null
tc filter add dev "$WAN_IPV6" parent 7: protocol ipv6 prio 1 u32 \
match u32 0 0 \
action mirred egress redirect dev ifb0 2>/dev/null
if [ $? -eq 0 ]; then
echo " ✓ IPv6上传重定向已配置(接口: $WAN_IPV6)"
else
echo " ⚠ IPv6上传重定向失败,接口$WAN_IPV6可能不支持"
fi
fi
fi
echo ""
# ============================================================
# 第五步:防火墙标记规则
# ============================================================
echo "==> 第五步:配置防火墙标记规则"
# 标记规则函数
mark_rules() {
local T=$1 # iptables/ip6tables
local SRC=$2 # 源匹配
local DST=$3 # 目标匹配
echo " → 配置${T}标记规则..."
# ===== P10 游戏(最高优先级)=====
echo " → 游戏标记规则..."
# UDP游戏端口
$T -t mangle -A FORWARD $SRC $DST -m mark --mark 0 -p udp \
-m multiport --dports 5060,3478,3479,3480,3481,50000:60000,27000:27200,8801:8810,10000:20000,30000:40000 \
-m comment --comment "Game-UDP" -j MARK --set-mark 10
# TCP游戏管理端口
$T -t mangle -A FORWARD $SRC $DST -m mark --mark 0 -p tcp \
-m multiport --dports 27014:27050,3478,3479,3480,3481,5222,5223,5228,8080 \
-m comment --comment "Game-TCP" -j MARK --set-mark 10
# UDP小包特征(游戏典型特征)
$T -t mangle -A FORWARD $SRC $DST -m mark --mark 0 -p udp \
--dport 1024:65535 -m length --length 0:512 \
-m comment --comment "Game-UDP-SmallPacket" -j MARK --set-mark 10
# ===== P15 DNS/ICMP/小包(次高优先级)=====
echo " → DNS/小包标记规则..."
# DNS查询
$T -t mangle -A FORWARD $SRC $DST -m mark --mark 0 -p udp --dport 53 \
-m comment --comment "DNS-UDP" -j MARK --set-mark 15
$T -t mangle -A FORWARD $SRC $DST -m mark --mark 0 -p tcp --dport 53 \
-m comment --comment "DNS-TCP" -j MARK --set-mark 15
# ICMP控制报文
$T -t mangle -A FORWARD $SRC $DST -m mark --mark 0 -p icmp \
-m comment --comment "ICMP" -j MARK --set-mark 15
$T -t mangle -A FORWARD $SRC $DST -m mark --mark 0 -p ipv6-icmp \
-m comment --comment "ICMPv6" -j MARK --set-mark 15 2>/dev/null || true
# 非UDP小包
$T -t mangle -A FORWARD $SRC $DST -m mark --mark 0 \
-m length --length 0:256 ! -p udp \
-m comment --comment "SmallPacket-NonUDP" -j MARK --set-mark 15
# ===== P20 微信/支付(中高优先级)=====
echo " → 微信/支付标记规则..."
# SNI匹配微信(如果支持字符串匹配)
if lsmod 2>/dev/null | grep -q xt_string; then
$T -t mangle -A FORWARD $SRC $DST -m mark --mark 0 -p tcp --dport 443 \
-m string --string "weixin" --algo bm --from 40 --to 80 \
-m comment --comment "WeChat-SNI" -j MARK --set-mark 20 2>/dev/null || true
$T -t mangle -A FORWARD $SRC $DST -m mark --mark 0 -p tcp --dport 443 \
-m string --string "wechat" --algo bm --from 40 --to 80 \
-m comment --comment "WeChat-SNI2" -j MARK --set-mark 20 2>/dev/null || true
fi
# 微信专用端口
$T -t mangle -A FORWARD $SRC $DST -m mark --mark 0 -p tcp \
-m multiport --dports 5223,8080,14000,8000,8001,5228 \
-m comment --comment "WeChat-Ports" -j MARK --set-mark 20
# ===== P25 网页(中等优先级)=====
echo " → 网页标记规则..."
$T -t mangle -A FORWARD $SRC $DST -m mark --mark 0 -p tcp --dport 80 \
-m comment --comment "Web-HTTP" -j MARK --set-mark 25
$T -t mangle -A FORWARD $SRC $DST -m mark --mark 0 -p tcp --dport 443 \
-m comment --comment "Web-HTTPS" -j MARK --set-mark 25
$T -t mangle -A FORWARD $SRC $DST -m mark --mark 0 -p udp --dport 443 \
-m comment --comment "Web-QUIC" -j MARK --set-mark 25
# ===== P35 视频/下载(低优先级)=====
echo " → 视频/下载标记规则..."
# SNI匹配视频平台
if lsmod 2>/dev/null | grep -q xt_string; then
for domain in \
"douyin.com" "kuaishou.com" "bilibili.com" \
"huya.com" "douyu.com" "youtube.com" "netflix.com" \
"iqiyi.com" "youku.com" "qq.com" "twitch.tv"; do
$T -t mangle -A FORWARD $SRC $DST -m mark --mark 0 \
-p tcp --dport 443 \
-m string --string "$domain" --algo bm --from 40 --to 120 \
-m comment --comment "Video-$domain" -j MARK --set-mark 35 2>/dev/null || true
done
fi
# 视频/下载端口
$T -t mangle -A FORWARD $SRC $DST -m mark --mark 0 -p tcp \
-m multiport --dports 1935,8080,8000:8002 \
-m comment --comment "Video-Ports" -j MARK --set-mark 35
# ===== P30 默认(中低优先级)=====
echo " → 默认标记规则..."
$T -t mangle -A FORWARD $SRC $DST -m mark --mark 0 \
-m comment --comment "Default" -j MARK --set-mark 30
echo " ✓ ${T}标记规则配置完成"
}
# 应用规则
echo " → 应用IPv4标记规则..."
mark_rules iptables "-s $LAN_SUBNET" "! -d $LAN_SUBNET"
echo " → 应用IPv6标记规则..."
mark_rules ip6tables "-i $LAN_IF" "! -o $LAN_IF"
# 保存标记到Conntrack
echo " → 保存标记到Conntrack..."
iptables -t mangle -A FORWARD -m mark ! --mark 0 \
-m comment --comment "Save-Conntrack" -j CONNMARK --save-mark
echo " ✓ IPv4 Conntrack标记保存已配置"
ip6tables -t mangle -A FORWARD -m mark ! --mark 0 \
-m comment --comment "Save-Conntrack-v6" -j CONNMARK --save-mark
echo " ✓ IPv6 Conntrack标记保存已配置"
echo ""
# ============================================================
# 第六步:FW过滤器绑定
# ============================================================
echo "==> 第六步:绑定FW过滤器"
for dev in ifb0 ifb1; do
if [ "$dev" = "ifb0" ]; then
parent="1:"
direction="上传"
else
parent="2:"
direction="下载"
fi
echo " → 配置${direction}过滤器 (${dev})..."
for cls in 10 15 20 25 30 35 40 45 50; do
tc filter replace dev $dev protocol all parent $parent prio 1 \
handle $cls fw classid ${parent}${cls} 2>/dev/null
done
echo " ✓ ${direction}过滤器绑定完成"
done
echo ""
# ============================================================
# 第七步:验证与总结
# ============================================================
echo "=========================================="
echo " ✅ QoS部署完成!"
echo "=========================================="
echo ""
echo "【配置摘要】"
echo " 包管理器: $PKG_MGR"
echo " 主WAN接口: $WAN"
echo " IPv6接口: $([ $IPV6_SUPPORT -eq 1 ] && echo "$WAN_IPV6" || echo "禁用")"
echo " 内网接口: $LAN_IF ($LAN_SUBNET)"
echo " 上行带宽: ${UP_BW}kbit (~$((UP_BW/1000))Mbps)"
echo " 下行带宽: ${DOWN_BW}kbit (~$((DOWN_BW/1000))Mbps)"
echo ""
echo "【优先级分配】"
echo " P10 游戏 : ${UP_P10}kbit↑ / ${DL_P10}kbit↓ (最高)"
echo " P15 DNS : ${UP_P15}kbit↑ / ${DL_P15}kbit↓"
echo " P20 微信 : ${UP_P20}kbit↑ / ${DL_P20}kbit↓"
echo " P25 网页 : ${UP_P25}kbit↑ / ${DL_P25}kbit↓"
echo " P30 默认 : ${UP_P30}kbit↑ / ${DL_P30}kbit↓"
echo " P35 视频 : ${UP_P35}kbit↑ / ${DL_P35}kbit↓ (最低)"
echo ""
# 规则统计
echo "【规则统计】"
echo " IPv4规则: $(iptables -t mangle -L FORWARD -n 2>/dev/null | grep -c 'MARK\|CONNMARK') 条"
echo " IPv6规则: $(ip6tables -t mangle -L FORWARD -n 2>/dev/null | grep -c 'MARK\|CONNMARK') 条"
echo " TC过滤器: $(tc filter show dev ifb0 2>/dev/null | grep -c 'fw') 个(上传) + $(tc filter show dev ifb1 2>/dev/null | grep -c 'fw') 个(下载)"
echo ""
# IPv6状态
if [ $IPV6_SUPPORT -eq 1 ]; then
echo "【IPv6支持】"
echo " 状态: 已启用"
echo " 接口: $WAN_IPV6"
# 检查IPv6规则是否生效
if [ "$WAN_IPV6" = "$WAN" ]; then
v6_down=$(tc filter show dev "$WAN" parent ffff: 2>/dev/null | grep -c "protocol ipv6")
v6_up=$(tc filter show dev "$WAN" parent 3: 2>/dev/null | grep -c "protocol ipv6")
else
v6_down=$(tc filter show dev "$WAN_IPV6" parent ffff: 2>/dev/null | grep -c "protocol ipv6")
v6_up=$(tc filter show dev "$WAN_IPV6" parent 7: 2>/dev/null | grep -c "protocol ipv6")
fi
echo " 下行规则: ${v6_down}条"
echo " 上传规则: ${v6_up}条"
echo ""
fi
echo "【验证命令】"
echo " 上传队列统计: tc -s class show dev ifb0"
echo " 下载队列统计: tc -s class show dev ifb1"
echo " 防火墙规则: iptables -t mangle -L FORWARD -n -v"
echo " Conntrack标记: cat /proc/net/nf_conntrack | grep mark"
echo " 实时监控: watch -n1 'tc -s class show dev ifb0 | grep -E \"class htb|Sent\"'"
echo ""
echo "【故障排查】"
echo " 1. 游戏掉线: 增加P10带宽或添加游戏端口"
echo " 2. 网页卡顿: 检查P25带宽是否充足"
echo " 3. IPv6不生效: 确认IPv6接口检测正确"
echo " 4. 完全清除: 重启路由器或手动清理tc/iptables规则"
echo ""
# 游戏连接统计
echo "【当前游戏连接】"
echo " 已标记为游戏的连接数:"
echo " IPv4: $(cat /proc/net/nf_conntrack 2>/dev/null | grep 'mark=10' | wc -l)"
echo " IPv6: $(cat /proc/net/nf_conntrack 2>/dev/null | grep 'mark=10' | wc -l)"
echo ""
echo "=========================================="
