1. 为什么需要精准IP限速你的网络卡顿有救了家里网络一到晚上就卡成PPT孩子看动画片你开视频会议就疯狂掉线NAS备份文件直接把全屋网速吃干抹净如果你也遇到过这些头疼事那今天聊的OpenWrt精准IP限速可能就是你的解药。很多人以为换个更贵的路由器就能解决所有问题其实不然。再高的总带宽如果被某个“大户”无节制占用其他设备照样得“饿肚子”。这就好比一条很宽的高速公路如果有一辆巨型卡车长期占着两条车道慢行后面的小车也只能干着急。精准IP限速就是给这条路上的每辆车每个IP设备分配明确的车道和速度限制确保紧急车辆比如你的视频会议永远有优先路权而大货车比如下载机则被限制在它自己的车道里不能出来捣乱。OpenWrt作为一款开源的路由器操作系统它的强大之处就在于提供了近乎底层的网络控制能力。我们常说的“限速”在OpenWrt里主要是通过两套核心工具实现的**TCTraffic Control流量控制**和iptables防火墙规则。TC负责搭建限速的“车道和交通规则”而iptables则像交警负责识别哪辆车哪个IP的数据包应该进入哪条车道。通过脚本将它们结合起来我们就能实现指哪打哪的精准控制。这种方案特别适合家庭和小型办公环境。你可以轻松做到给客人的手机限个速防止他们看高清视频拖垮网络保障智能电视的4K流媒体优先级看剧不卡顿严格限制备份服务器的上传带宽避免它“偷跑”影响别人。相比于路由器自带的、往往比较粗糙的“QoS”或“带宽管理”功能自己动手写的脚本规则更透明、更灵活效果也立竿见影。2. 动手之前理解核心工具TC与iptables在直接抄脚本之前花几分钟搞懂背后的原理能让你在调试和修改时事半功倍遇到问题也不慌。别担心我们用最直白的方式来解释。TC流量控制是干什么的你可以把TC想象成一个多层级的自来水管道系统。最粗的那根总管道接入你家这就是你的物理网卡比如WAN口。TC的工作就是在这根总管道后面安装一系列的水阀和分管道。qdisc队列规则这是安装在网卡上的“总阀门”。htbHierarchical Token Bucket分层令牌桶是我们最常用的阀门类型因为它能很好地实现带宽分层和借用。class类这是在总阀门下面创建的不同规格的“分管道”。比如你可以创建一个“保障带宽”管道一个“限制带宽”管道一个“默认”管道。filter过滤器这是连接在分管道入口的“识别器”。它根据规则比如IP地址把水流数据包引导到对应的分管道里去。 TC的配置逻辑就是在网卡上挂一个qdisc在qdisc下创建不同的class然后用filter把流量分类到各个class中。每个class都可以独立设置带宽速率。iptables的mangle表又扮演什么角色iptables我们通常用来做防火墙但它有个mangle表专门用来修改数据包的一些“元数据”。在限速场景里我们主要用它来给数据包“贴标签”打Mark。数据包从内网设备发往互联网时会经过PREROUTING链路由前。我们在这里匹配源IP-s给它贴上一个我们自定义的数字标签。数据包从互联网返回内网设备时会经过POSTROUTING链路由后。我们在这里匹配目标IP-d同样贴上标签。 贴标签的目的是为了后面的TC过滤器能识别。TC的filter规则可以设定凡是贴着标签2的数据包就请进入class 2这个管道。这样通过IP地址打标再通过标签引导流量就实现了基于IP的精准限速。一个简单的比喻iptables是小区门口的保安他根据住户门牌号IP地址给每辆进出的车贴上不同颜色的通行证Mark。TC是地下车库的管理系统它规定贴红色通行证的车只能停A区限速1M贴绿色通行证的车可以停B区保障10M。保安贴标车库系统按标引导分工明确。3. 实战第一步拆解与定制你的限速脚本下面这个脚本是基于原始文章优化后的增强版我增加了更多的注释和错误处理逻辑。你可以把它保存到OpenWrt路由器的/root/limit.sh然后根据你的网络情况修改前面那段配置参数就行。#!/bin/sh # 【第一部分用户配置区按需修改】 # 定义内外网接口名称使用 ip addr 或 ifconfig 命令查看 # 通常br-lan是内网桥接接口pppoe-wan或eth0.2是外网接口 IDEVbr-lan ODEVpppoe-wan # 定义你的物理总带宽。务必填写真实值这是所有限制的基准 # 单位可以是 kbit, mbit, gbit。例如100兆宽带下行约 100mbit上行可能 30mbit。 UP30mbit # 总上行带宽 DOWN100mbit # 总下行带宽 # 定义对单个IP的限速参数 # rate: 保障带宽。就算网络拥堵这个IP至少能拥有这么多带宽。 # ceil: 最大带宽。当网络空闲时这个IP最高可以借用到的带宽。 # 注意所有受限IP的ceil总和最好不要超过总带宽否则可能失效。 UPLOAD1mbit # 单IP保障上行 MUPLOAD3mbit # 单IP最大上行可借用 DOWNLOAD4mbit # 单IP保障下行 MDOWNLOAD10mbit # 单IP最大下行可借用 # 定义你的内网网段和要限制的IP范围 INET192.168.1. IPS100 # 起始IP例如 192.168.1.100 IPE110 # 结束IP例如 192.168.1.110 # 【配置结束以下部分无需改动】 # 清除网卡上可能已有的TC规则避免冲突 echo 正在清除旧队列规则... tc qdisc del dev $ODEV root 2/dev/null tc qdisc del dev $IDEV root 2/dev/null # 在内外网接口上创建最顶层的HTB队列规则默认类别编号设为256 # handle 10: 给这个qdisc一个句柄编号相当于给它起个名 # default 256: 未分类的流量默认进入256这个类别 tc qdisc add dev $ODEV root handle 10: htb default 256 tc qdisc add dev $IDEV root handle 10: htb default 256 # 创建根类10:1其带宽限制为你的总带宽 # parent 10: 说明这个类挂在handle为10的qdisc下 # classid 10:1 是这个类的编号 tc class add dev $ODEV parent 10: classid 10:1 htb rate $UP ceil $UP tc class add dev $IDEV parent 10: classid 10:1 htb rate $DOWN ceil $DOWN # 为默认未分类的流量创建一个“无限速”的类实际上限制为总带宽 tc class add dev $ODEV parent 10:1 classid 10:256 htb rate 1kbit ceil $UP prio 0 tc qdisc add dev $ODEV parent 10:256 handle 256: pfifo tc class add dev $IDEV parent 10:1 classid 10:256 htb rate 1kbit ceil $DOWN prio 0 tc qdisc add dev $IDEV parent 10:256 handle 256: pfifo # 开始循环为指定IP范围的每个IP创建独立的限速类和规则 echo 正在为IP段 $INET$IPS 到 $INET$IPE 配置限速规则... i$IPS while [ $i -le $IPE ] do # 为当前IP创建上行限速类 (10:2$i) 和队列 tc class add dev $ODEV parent 10:1 classid 10:2$i htb rate $UPLOAD ceil $MUPLOAD prio 1 tc qdisc add dev $ODEV parent 10:2$i handle 100$i: pfifo # 创建过滤器将标记为 2$i 的流量导向刚创建的类 10:2$i tc filter add dev $ODEV parent 10: protocol ip prio 100 handle 2$i fw classid 10:2$i # 为当前IP创建下行限速类 (10:2$i) 和队列 tc class add dev $IDEV parent 10:1 classid 10:2$i htb rate $DOWNLOAD ceil $MDOWNLOAD prio 1 tc qdisc add dev $IDEV parent 10:2$i handle 100$i: pfifo tc filter add dev $IDEV parent 10: protocol ip prio 100 handle 2$i fw classid 10:2$i # 使用iptables给来自此IP的数据包打上标记 2$i (用于限制上行) iptables -t mangle -A PREROUTING -s $INET$i -j MARK --set-mark 2$i iptables -t mangle -A PREROUTING -s $INET$i -j RETURN # 使用iptables给发往此IP的数据包打上标记 2$i (用于限制下行) iptables -t mangle -A POSTROUTING -d $INET$i -j MARK --set-mark 2$i iptables -t mangle -A POSTROUTING -d $INET$i -j RETURN echo - IP: $INET$i 限速已设置 (上行保障/最大: $UPLOAD/$MUPLOAD, 下行保障/最大: $DOWNLOAD/$MDOWNLOAD) iexpr $i 1 done echo 所有限速规则配置完成关键参数解读与配置心得rate和ceil这是HTB的精髓。rate是保证带宽ceil是峰值带宽。我一般把rate设为需要保障的最低值ceil设为允许它偶尔爆发的上限。比如给视频会议设备设置rate 3mbit ceil 5mbit保证它永远流畅空闲时也能更快加载页面。prio优先级数字越小优先级越高。在脚本里我们把默认类别设为prio 0最高限速IP设为prio 1。这意味着当网络拥塞时系统会优先满足未限速IP可能是你的主力设备的带宽限速IP的流量会被延迟处理。你可以根据设备重要性调整。IP范围设置我强烈建议在路由器的DHCP服务器里为需要限速的设备如访客、IoT设备配置静态IP地址分配并把这些IP划到一个连续的段里。这样用起这个脚本就非常方便只需改IPS和IPE两个数字。4. 部署、调试与验证让脚本真正跑起来脚本写好了怎么用呢这里我把每一步都掰开揉碎包括可能遇到的坑。第一步脚本上传与权限设置用WinSCP、scp或者OpenWrt Luci界面里的“文件传输”功能把上面那个脚本文件比如limit.sh上传到路由器的/root目录下。非常重要通过SSH登录路由器或者直接在Luci的“系统-TTYD终端”里输入命令给脚本加上执行权限chmod x /root/limit.sh没有这一步脚本是无法运行的。第二步首次运行与开机自启手动运行一次测试效果/root/limit.sh观察输出如果没有报错就说明规则已经加载了。设置开机自动运行。编辑OpenWrt的启动脚本vi /etc/rc.local在exit 0这一行之前添加sleep 30 # 等待网络接口完全就绪 /root/limit.sh这里sleep 30很关键因为TC规则必须在网络接口特别是PPPoE拨号的WAN口完全启动后才能生效否则可能会失败。第三步如何验证规则生效了光运行没报错不行得验证。这里有几个实用的命令查看TC的类结构tc -s class show dev pppoe-wan把pppoe-wan换成你的外网接口。你会看到类似10:1、10:2100这样的类以及它们的流量统计。如果10:2100里有数据包计数在增加说明IP为.100的设备流量正在被限速类处理。查看过滤器tc -s filter show dev br-lan。看看过滤器是否成功绑定到了对应的类上。查看iptables标记iptables -t mangle -nvL。在PREROUTING和POSTROUTING链里你应该能看到针对你配置的IP的MARK规则并且packets和bytes计数在增长。最直观的测速找一台被限速的IP设备比如手机用Speedtest或从局域网NAS下载大文件同时观察它的速度。它应该被限制在你设定的ceil值附近而其他未限速的设备则能跑满带宽。我踩过的坑接口名不对最大的坑OpenWrt不同版本、不同硬件接口名可能不一样。br-lan、eth0、pppoe-wan、wan、wan6都有可能。务必用ip addr命令确认你的内外网接口真实名称。总带宽设错把UP/DOWN设得比实际宽带高限速会不准确。最好用运营商的签约速率或者用Speedtest测个速留点余量比如95%。重启后失效大概率是rc.local执行太早网络没准备好。增加sleep时间或者更高级的做法是写一个hotplug脚本在网络接口ifup事件触发后再执行。5. 进阶玩法从固定限速到动态智能QoS基础的IP限速能解决“谁不能多用”的问题但更智能的需求是“谁在什么时候可以多用”。这就是智能QoS服务质量的范畴。OpenWrt上有很多成熟的智能QoS方案比如SQMSmart Queue Management、nft-qos以及大名鼎鼎的CAKECommon Applications Kept Enhanced。脚本限速 vs. 智能QoS脚本限速是静态的、基于IP的硬性规定。它不管这个IP是在打游戏还是在下BT一律按设定值限制。优点是精准、直接、资源消耗极低。智能QoS如SQM/CAKE是动态的、基于流量类型的智能调度。它通过识别数据包的类型游戏、视频、网页、下载并配合先进的队列算法如CAKE、FQ_CODEL在网络拥堵时优先保证延迟敏感的流量游戏、语音延迟或丢弃可以等待的流量下载、更新。它的目标是降低整体网络延迟和缓冲而不是限制某个IP。如何选择我个人的经验是有明确“坏邻居”时用脚本。比如你知道家里那台NAS一备份就全屋卡死或者需要严格隔离访客网络那么用脚本给它一个固定的、较低的带宽上限是最简单有效的。追求整体网络流畅度用智能QoS。如果你感觉网络时不时卡顿、游戏延迟高但说不清是哪个设备的问题那么开启SQM/CAKE会有奇效。它能显著改善多人共用网络时的体验。可以组合使用这不是二选一。你完全可以在开启SQM进行全局智能调度的基础上再用脚本对某个特定IP进行额外的、更严格的带宽封顶。例如全局用CAKE保证低延迟同时对BT下载机的IP再用脚本限制其最大带宽不超过50M防止它占满队列。在Luci界面配置SQM QoS对于新手我推荐从Luci界面配置SQM开始它已经集成在大多数OpenWrt版本中。进入“网络” - “SQM QoS”。“基本设置”中启用SQM选择你的WAN口接口如pppoe-wan。“下载速度”和“上传速度”填写你实际带宽的90%-95%这是关键必须填准。“队列规则”强烈推荐选择cake调度算法选piece_of_cake。这是目前最简单高效的组合。“额外SQM参数”可以留空。保存并应用。配置好后你可以明显感觉到在网络繁忙时网页响应更快游戏延迟更稳定。它的原理是在接口出口处建立一个智能队列主动管理数据包的发送顺序而不是像传统限速那样简单粗暴地丢包。6. 故障排查与性能优化指南规则不生效限速不准网络变慢了别急我们一步步来排错。问题一运行脚本后所有设备都变慢了。可能原因默认类别default 256的ceil值设置过低或者prio优先级设置有问题导致所有未标记的流量也被严重限制。解决检查脚本中创建10:256类的两行。ceil值应该等于总带宽$UP/DOWNprio应该设为0最高。确保你的主力设备IP不在IPS到IPE的限速范围内。问题二限速IP的设备速度远超设定的ceil值。可能原因1总带宽UP/DOWN设置远大于实际带宽。TC的限速是基于它认为的“总带宽”进行比例分配的。如果告诉它总带宽是1000mbit你限速10mbit实际比例只有1%当实际带宽是100mbit时它就能用到10mbit看起来就像没限住。解决校准总带宽参数。用有线连接测速取稳定值。可能原因2数据包没有被打上标记。可能是iptables规则没生效或者标记值2$i和TC过滤器里的handle值对不上。解决运行iptables -t mangle -nvL查看对应IP的MARK规则是否有数据包计数。运行tc -s filter show dev br-lan查看过滤器的classid是否指向了正确的限速类如10:2100。问题三网络延迟反而增加了。可能原因使用了pfifo这种简单的队列。在流量突发时pfifo可能导致缓冲膨胀Bufferbloat增加延迟。优化将脚本中的pfifo队列替换为更先进的fq_codel。修改这两行# 将 tc qdisc add dev $ODEV parent 10:2$i handle 100$i: pfifo # 替换为 tc qdisc add dev $ODEV parent 10:2$i handle 100$i: fq_codel limit 1000 flows 1024 quantum 300 target 5ms interval 100ms memory_limit 32Mb ecnfq_codel能显著减少队列延迟特别适合交互式应用。这是从“硬限速”向“智能管理”迈进的一小步。问题四路由器CPU占用变高。TC和iptables规则本身消耗资源很小。但如果限速的IP非常多比如上百个或者使用了非常复杂的过滤器可能会增加一些CPU负担。对于家用级路由器如MT7621、IPQ8065等管理几十个IP的限速完全无压力。如果感觉卡顿可以考虑减少限速IP数量或者换用硬件性能更强的设备。最后记得定期检查规则是否还在。因为iptables的规则在路由器重启后会消失我们的脚本在rc.local里重加了但TC规则可能因为接口重启而丢失。建立一个简单的监控比如在计划任务Cron里每小时检查一次关键TC类是否存在不存在则重新运行脚本是一个让网络长治久安的好习惯。