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 "=========================================="

滑稽的菊花

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

Post comment