目录
首先纠正某一篇博客,TC并不是只管发包不管收包,之前我也很纳闷 知道最后看到了14年前一位大佬的帖子。是ingress!
这里有个非常重要的点就是ingress,如果父类不是他的话是完不成限制源IP的,这个关键词表明你正在添加一个入口队列规则。与传统的egress(数据包离开网络接口时)规则不同,ingress规则是在数据包进入网络接口之前应用的。这意味着它可以过滤或修改入站流量,即便这些流量不是发送到本地主机的。这对于实现防火墙规则、流量监控或者服务质量(QoS)策略非常有用,尤其是在你希望在网络层对数据包进行操作时。但是,网上的教学很少有关于ingress的讲解以及使用,楼主当时也很疑惑为什么限制不住源IP而只能限制住目标IP。
TC (Traffic Control) 是Linux内核中提供的一个用于控制和管理网络流量的强大工具,它允许用户实现QoS(Quality of Service)策略,包括带宽限制、优先级控制、延迟保证等。TC基于内核的队列 discipline (qdisc) 和流量类别(class) 体系结构,允许对进入或离开网络接口的数据流进行复杂的整形和过滤。
输入格式和基本使用流程:
一般来说,TC命令的基本格式如下:
Bash
1tc [ OPTIONS ] OBJECT ACTION [ FILTER ]
OPTIONS
: 可选参数,比如-s
显示统计数据,-d
删除对象等。OBJECT
: 操作对象,可以是qdisc
(队列规则)、class
(流量类别)或filter
(过滤器)。ACTION
: 针对对象的操作,如add
(添加)、change
(更改)、replace
(替换)、delete
(删除)等。FILTER
: 对象的具体参数,如接口名称(dev eth0
)、父级分类ID(parent ...
)、qdisc类型(htb
、pfifo_fast
等)、速率限制(rate ...
)等。
限制 IP 示例:
1. 设置根qdisc (队列规则)
首先,我们需要在接口上设置一个队列规则作为流量控制的起点。假设我们要在ens192接口上使用HTB(Hierarchical Token Bucket)算法:
Bash
tc qdisc add dev ens192 root handle 1: htb default 20
这条命令将在ens192接口上添加一个根级别的HTB队列,分配给它的handle是1:,default 20
意味着所有未经分类的流量将被送到handle为20的类,这里的default相当于switch里面的default,就是说网口默认收到的数据毁到handle为20的子类去处理,大家看到这可能会疑惑为什么会有默认,这是因为下方的过滤器,过滤器是为了更加细腻的去处理网口数据。
生活举例:
例如我现在收到了三颗糖,一个甜的,一个咸的,一个辣的,如果我下面没人要我默认都给了甲,但是如果下面设好了过滤器,也就是规则,比如说乙想要辣的,我就会把辣的给乙,不再给甲了。
2. 创建子类进行带宽限制
接下来,创建一个子类并分配一定速率的带宽:
Bash
tc class add dev ens192 parent 1:0 classid 1:20 htb rate 500kbps ceil 1mbps
这条命令创建了一个新的类,其父级是上面创建的根类(handle为1:),新类的handle为1:20,这里同时也对应了上方基类的default的20,使用HTB算法,基础速率(rate)为500kbps,最高上限(ceil)为1mbps。
3. 创建过滤器以识别特定流量
最后,创建一个过滤器,以便将特定流量路由到上面创建的带宽受限的子类:
Bash
tc qdisc add dev "$intf" handle ffff: ingress tc filter add dev "$intf" protocol ip parent 1:0 prio 0 u32 match ip dst 172.16.0.135 flowid 1:20 # "$intf" 代表网口 类似于ens33这种
这条命令创建了一个IP协议的过滤器,将目标地址为ip子网的流量引导至类ID为1:20的流量类别,因此这些流量将受到500kbps的带宽限制。
限制 端口 示例:
下面的两步操作都跟限制ip相同,主要是第三步过滤器的不同。
1. 设置根qdisc (队列规则)
首先,我们需要在接口上设置一个队列规则作为流量控制的起点。假设我们要在ens192接口上使用HTB(Hierarchical Token Bucket)算法:
Bash
tc qdisc add dev ens192 root handle 1: htb default 20
这条命令将在ens192接口上添加一个根级别的HTB队列,分配给它的handle是1:,default 20
意味着所有未经分类的流量将被送到handle为20的类,这里的default相当于switch里面的default,就是说网口默认收到的数据毁到handle为20的子类去处理,大家看到这可能会疑惑为什么会有默认,这是因为下方的过滤器,过滤器是为了更加细腻的去处理网口数据。
2. 创建子类进行带宽限制
接下来,创建一个子类并分配一定速率的带宽:
Bash
tc class add dev ens192 parent 1:0 classid 1:20 htb rate 500kbps ceil 1mbps
这条命令创建了一个新的类,其父级是上面创建的根类(handle为1:),新类的handle为1:20,这里同时也对应了上方基类的default的20,使用HTB算法,基础速率(rate)为500kbps,最高上限(ceil)为1mbps。
3. 创建端口过滤器
Bash
tc filter add dev ens192 parent 1:0 protocol ip handle 20 fw flowid 1:20 tc filter add dev ens192 parent 1:0 protocol ip u32 match ip sport 2049 0xffff flowid 1:20
这里第一步是将ipv4类型的接口都归于20的子类去处理,这一步也是为了添加容错,主要是第二步,u32是一种过滤器类型,但它提供了具体的匹配条件——match ip sport 2049 0xffff
,这意味着只有源端口号(sport)等于2049的流量(这里范围是精确匹配,0xffff是因为u32匹配方式需要指定掩码长度)才会被这个过滤器捕获,并将其流量导向类ID为1:20
的类去处理这个数据。