本网站可以通过分类标签帮助你快速筛选出你想看的文章,记住地址:www.Facec.cc

玩机:自建Linux网关 配置限流(基于tc工具)

我有一台Linux多网口主机,搭建了一个网关,本文记录一下实现限流功能。

  • 基于tc工具(Traffic Control,流量控制),
  • 结合HTB队列规则(Hierarchical Token Bucket,分层令牌桶)
  • ifb虚拟设备
    实现网关对不同终端、不同方向流量的精准限流,覆盖下行、上行限流场景及完整运维流程。

一、核心组件工具

1.1 关键工具与模块

  • tc:Linux内核自带的流量控制工具,支持队列规则(qdisc)、流量类别(class)、过滤器(filter)三层配置,可实现带宽限制、优先级调度等功能。

  • HTB队列规则:核心限流规则,支持层级化带宽分配,可设置最小保障带宽(rate)和最大突发带宽(ceil),适配网关多终端共享带宽场景。

  • ifb模块:虚拟网络接口模块,用于解决Linux对“上行流量”直接限流的局限性,通过流量重定向实现上行带宽精准控制。

1.2 网关流量方向定义

网关限流需明确流量方向,避免配置混淆:

  • 下行流量:外网→网关→内网终端(如终端浏览网页、下载文件),限流需配置在网关的外网网卡(如ens36)。

  • 上行流量:内网终端→网关→外网(如终端上传文件、访问外网服务),需通过ifb虚拟设备重定向流量后限流。

1.3 常用基础命令

用于查看、验证限流配置,排查问题:


# 查看所有网卡的队列规则
tc qdisc show|ls
# 查看指定网卡(如ens36)的队列规则
tc qdisc show dev ens36
# 查看指定网卡的过滤器配置(流量匹配规则)
tc filter show dev ens36
# 查看指定网卡的流量类别(带宽分配规则)
tc class show dev ens36

二、网关限流实操配置

本文以网关外网网卡ens36、内网网段10.100.0.0/24为例,实现多场景限流配置,所有命令需以root权限执行。

2.1 场景1:内网终端下行限流(外网→内网)

限制指定内网终端(如10.100.0.99)的下行带宽为10Mbit,保障其他终端网络体验。

  1. 添加根HTB队列规则:在网关外网网卡ens36上创建根队列,作为所有限流类的父节点。
    tc qdisc add dev ens36 root handle 1: htb
    说明:handle 1:为根队列句柄(主类标识),后续子类需基于此关联。

  2. 创建下行限流类:定义带宽限制规则,rate为最小保障带宽(此处与ceil一致,即固定限流10Mbit)。
    tc class add dev ens36 parent 1: classid 1:10 htb rate 10mbit ceil 10mbit
    说明:classid 1:10为子类标识(主类1+次类10),parent 1:表示继承根队列属性。

  3. 配置过滤器(匹配目标终端):将访问内网终端10.100.0.99的下行流量,引导至上述限流类。
    tc filter add dev ens36 protocol ip parent 1:0 prio 1 u32 \ match ip dst 10.100.0.99/32 \ flowid 1:10 说明:match ip dst匹配目标IP(内网终端),flowid 1:10指定流量对应限流类,prio 1为过滤器优先级(数值越小优先级越高)。

2.2 场景2:内网终端上行限流(内网→外网)

Linux无法直接对网卡入口流量(上行)限流,需通过ifb虚拟设备重定向流量,再对虚拟设备配置限流规则。

  1. 加载ifb模块并启用虚拟设备:`# 加载ifb模块(一次性加载,重启后需重新加载)
    modprobe ifb

启用ifb0虚拟设备(可支持多个虚拟设备,如ifb0、ifb1)

ip link set dev ifb0 up`

  1. 重定向外网网卡入口流量至ifb0:将ens36的上行流量(内网→外网)转发到ifb0处理。
    `# 为ens36添加 ingress 队列(用于捕获入口流量)
    tc qdisc add dev ens36 handle ffff: ingress

配置过滤器,将所有入口IP流量重定向至ifb0

tc filter add dev ens36 parent ffff: protocol ip u32 match u32 0 0 action mirred egress redirect dev ifb0说明:handle ffff:是ingress队列的固定句柄,match u32 0 0`表示匹配所有流量。

  1. 为ifb0配置HTB限流规则:限制10.100.0.99访问指定外网IP(183.66.100.19)的上行带宽为20Mbit。
    `# 为ifb0添加根HTB队列
    tc qdisc add dev ifb0 root handle 1: htb

创建上行限流类(20Mbit固定限流)

tc class add dev ifb0 parent 1: classid 1:20 htb rate 20mbit ceil 20mbit

配置过滤器,匹配指定内网IP→外网IP的流量

tc filter add dev ifb0 protocol ip parent 1:0 prio 1 u32
match ip src 10.100.0.99/32
match ip dst 183.66.100.19/32
flowid 1:20`

2.3 场景3:网段批量限流与端口级限流

针对网关场景的批量控制需求,可扩展配置网段限流和端口级限流,适配不同业务场景。

3.1 内网网段整体限流(如10.100.0.0/24)

限制整个内网网段上行带宽不超过100Mbit,避免网段占用全部网关带宽:


# 在ifb0上创建网段限流类(rate 100mbit,ceil 120mbit允许突发)
tc class add dev ifb0 parent 1: classid 1:30 htb rate 100mbit ceil 120mbit
# 匹配整个内网网段流量
tc filter add dev ifb0 protocol ip parent 1:0 prio 2 u32 \
match ip src 10.100.0.0/24 \
flowid 1:30

说明:优先级设为2(低于单终端限流的优先级1),确保单终端限流优先于网段限流生效。

3.2 端口级限流(如HTTP/HTTPS服务)

限制内网终端访问外网80(HTTP)、443(HTTPS)端口的下行带宽为5Mbit,保障核心业务流量:


# 在ens36上创建端口限流类
tc class add dev ens36 parent 1: classid 1:40 htb rate 5mbit ceil 5mbit
# 匹配目标端口为80和443的流量
tc filter add dev ens36 protocol ip parent 1:0 prio 1 u32 \
match ip dport 80 0xffff \
match ip dport 443 0xffff \
flowid 1:40

说明:0xffff为端口掩码,确保精准匹配指定端口。

三、限流配置复原(清理规则)

测试完成或需重置配置时,需清理所有队列规则、类和过滤器,避免残留配置影响网络。

3.1 清理所有网卡队列规则与类


for dev in $(ip link show | grep '^[0-9]' | awk '{print $2}' | sed 's/://'); do
    echo "Cleaning up tc rules for device: $dev"
    tc qdisc del dev "$dev" root 2>/dev/null
done

3.2 清理ingress队列与ifb设备


# 清理所有网卡的ingress队列
for dev in $(ip link show | grep '^[0-9]' | awk '{print $2}' | sed 's/://'); do
    echo "Cleaning up ingress qdisc for device: $dev"
    tc qdisc del dev "$dev" ingress 2>/dev/null
done
# 禁用并卸载ifb模块
ip link set dev ifb0 down 2>/dev/null
rmmod ifb 2>/dev/null

说明:2>/dev/null用于忽略“规则不存在”的报错,使脚本更稳健。

四、配置持久化(避免重启失效)

上述配置为临时生效,重启网络服务或系统后会丢失,需通过脚本实现持久化。

4.1 编写限流启动脚本


# 创建脚本文件 /usr/local/bin/gateway-traffic-limit.sh
vi /usr/local/bin/gateway-traffic-limit.sh

脚本内容(整合上述所需限流规则,按需调整参数):


#!/bin/bash
# 加载ifb模块
modprobe ifb
ip link set dev ifb0 up

# 清理原有规则
for dev in $(ip link show | grep '^[0-9]' | awk '{print $2}' | sed 's/://'); do
    tc qdisc del dev "$dev" root 2>/dev/null
    tc qdisc del dev "$dev" ingress 2>/dev/null
done

# 配置ens36下行限流(10.100.0.99 下行10Mbit)
tc qdisc add dev ens36 root handle 1: htb
tc class add dev ens36 parent 1: classid 1:10 htb rate 10mbit ceil 10mbit
tc filter add dev ens36 protocol ip parent 1:0 prio 1 u32 match ip dst 10.100.0.99/32 flowid 1:10

# 配置上行限流(重定向流量至ifb0,10.100.0.99上行20Mbit)
tc qdisc add dev ens36 handle ffff: ingress
tc filter add dev ens36 parent ffff: protocol ip u32 match u32 0 0 action mirred egress redirect dev ifb0
tc qdisc add dev ifb0 root handle 1: htb
tc class add dev ifb0 parent 1: classid 1:20 htb rate 20mbit ceil 20mbit
tc filter add dev ifb0 protocol ip parent 1:0 prio 1 u32 match ip src 10.100.0.99/32 match ip dst 183.66.100.19/32 flowid 1:20

echo "Gateway traffic limit rules applied successfully!"

4.2 配置开机自启


# 赋予脚本执行权限
chmod +x /usr/local/bin/gateway-traffic-limit.sh

# 方式1:通过rc.local自启(适用于CentOS 7、Ubuntu)
echo "/usr/local/bin/gateway-traffic-limit.sh" >> /etc/rc.local
chmod +x /etc/rc.local

# 方式2:通过systemd自启(适用于CentOS 8、Ubuntu 18+)
cat > /etc/systemd/system/gateway-limit.service << EOF
[Unit]
Description=Gateway Traffic Limit Service
After=network.target

[Service]
Type=oneshot
ExecStart=/usr/local/bin/gateway-traffic-limit.sh
RemainAfterExit=yes

[Install]
WantedBy=multi-user.target
EOF

# 启用并启动服务
systemctl daemon-reload
systemctl enable gateway-limit.service
systemctl start gateway-limit.service

五、关键参数与注意事项

5.1 核心参数说明

  • rate:流量控制类的最小保障带宽,即使网络拥堵,也会为该类保留此带宽。

  • ceil:流量控制类的最大突发带宽,当网络空闲时,该类可占用的最大带宽,超过rate但不超过ceil。

  • parent:指定流量类的父类句柄,形成层级关系,父类带宽需大于等于子类带宽之和。

  • prio:过滤器优先级,数值越小优先级越高,当流量匹配多个过滤器时,优先执行高优先级规则。

# linux  

评论