本帖最后由 滑稽的菊花 于 2026-5-22 16:32 编辑
———————————-
复制粘贴到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: 购物_codel(自动回退pfifo)
- # 3.2 下载HTB队列树(ifb1)
- # - 根队列 2:(总带宽控制)
- # - 子类 2:10~50(优先级队列)
- # - 叶子qdisc: 购物_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、购物_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. 购物_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_购物_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
-
- # 优先使用购物_codel,失败则使用pfifo
- tc qdisc add dev ifb0 parent 1:${cls} 购物_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} 购物_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 "=========================================="
复制代码
|