tc是用来提供流量控制的强大工具,自己在进行DDoS攻击模拟、网络负载测试中一直使用!
简单概要
#简介
netem是linux内核版本提供的一个网络模拟功能模块
tc 是 Linux 系统中的一个工具,全名为traffic control(流量控制)。tc 可以用来控制 netem 的工作模式
如果想使用 netem ,需要至少两个条件,一个是内核中的 netem 功能被包含,另一个是要有 tc 。
#原理
TC用于Linux内核的流量控制,主要是通过在输出端口处建立一个队列来实现流量控制。
Linux 流量控制方法,控发不控收 , 所以只能对产生瓶颈网卡处的发包速率进行控制 , 而网络瓶颈分析亦为 Linux 网络流控的第一步,Linux流量控制主要是在输出接口排列时进行处理和实现的。
#Linux 流量控制过程分二种:
队列控制:即 QOS, 瓶颈处的发送队列的规则控制,常见的有 SFQ PRIO
流量控制:即带宽控制 , 队列的排队整形, 一般为 TBF HTB
#Linux 流量控制算法分二种:
无类算法:用于树叶级无分支的队列,例如:SFQ
队列控制的无类算法 SFQ(随机公平队列)
流量控制的无类算法 TBF(令牌桶过滤器)
先进先出先入先出 pfifo_fast/(bfifo_fast)
分类算法:用于多分支的队列,例如:PRIO CBQ HTB
队列控制的分类算法 PRIO(优先级调度程序)
流量整形的分类算法 CBQ(基于类的排队)
流量整形的分类算法 HTB(分层令牌桶)
#pfifo_fast:
FIFO算法构成所有Linux网络接口(pfifo_fast)上默认qdisc的基础。它不对数据包进行整形或重新排列。它只是在接收并排队后尽快传输数据包。这也是在所有新创建的类中使用的qdisc,直到另一个qdisc或一个类替换FIFO。
但是,真实的FIFO qdisc必须具有大小限制(缓冲区大小),以防止它无法在接收包时尽快使数据包出队的情况下溢出。Linux实现了两个基本的FIFO qdisc,一个基于字节,一个基于数据包。无论使用哪种FIFO,队列的大小都由参数limit定义 。对于pfifo,该单元被理解为分组,而对于bfifo,该单元被理解为字节。
#TBF:
它只是对接口上传输的流量进行整形。为了限制数据包从特定接口出队的速度,TBF qdisc是理想的解决方案。它只是将传输的流量减慢到指定的速率。仅在有足够的令牌可用时才发送数据包。否则,数据包将被延迟。以这种方式延迟数据包会将人为延迟引入数据包的往返时间
#HTB:
HTB将令牌和存储桶的概念与基于类的系统和过滤器一起使用,以实现对流量的复杂而细粒度的控制。通过复杂的 借用模型,HTB可以执行各种复杂的流量控制技术。立即使用HTB的最简单方法之一就是整形。
通过了解令牌和存储桶或掌握TBF的功能,HTB应该仅仅是一个逻辑步骤。该排队规则允许用户定义所使用的令牌和存储桶的特性,并允许用户以任意方式嵌套这些存储桶。与分类方案结合使用时 ,可以非常精细的方式控制流量。
以下是使用tc工具在命令行上显示HTB语法的示例输出。
简单使用:以下功能一般是基于无类队列,可完成如下功能如下(故障模拟)
1:模拟延迟传输(以使用netem(Token Bucket Filter)为例)
#该命令将 eth0 网卡的传输设置为延迟100毫秒发送
tc qdisc add dev eth0 root netem delay 100ms
tc qdisc del dev eth0 root netem delay 100ms
#该命令将 ens33 网卡的传输设置为延迟 100ms ± 10ms (90 ~ 110 ms 之间的任意值)发送,真实情况延迟值不会这么精确,会存在波动,用该命令来模拟出带有波动性的延迟值
tc qdisc add dev ens33 root netem delay 100ms 10ms
#该命令将 ens33 网卡的传输设置为100ms,同时,大约有30%的包会延迟±10ms 发送。进一步加强波动的随机性
tc qdisc add dev ens33 root netem delay 100ms 10ms 30%
2:模拟网络丢包(以netem为例)
#该命令将 ens33 网卡的传输设置为随机丢掉 1% 的数据包。
tc qdisc add dev ens33 root netem loss 5%
#设置丢包的成功率,该命令将 ens33 网卡的传输设置为随机丢掉 1% 的数据包,成功率为 30% 。
tc qdisc add dev ens33 root netem loss 1% 30%
3. 模拟包重复
#该命令将 ens33 网卡的传输设置为随机产生 1% 的重复数据包 。
tc qdisc add dev ens33 root netem duplicate 1%
4. 模拟包损坏
#该命令将 ens33 网卡的传输设置为随机产生 0.2% 的损坏的数据包 。 (内核版本需在2.6.16以上)
tc qdisc add dev ens33 root netem corrupt 0.2%
5. 模拟包乱序
#该命令将 ens33 网卡的传输设置为:有 25% 的数据包(50%相关)会被立即发送,其他的延迟 10 秒。
tc qdisc change dev ens33 root netem delay 10ms reorder 25% 50%
#该命令会在一定程度上打乱发包的次序
tc qdisc add dev ens33 root netem delay 100ms 10ms
http://www.tldp.org/HOWTO/html_single/Traffic-Control-HOWTO/
https://www.ibm.com/developerworks/cn/linux/1412_xiehy_tc/
http://codeshold.me/2017/01/tc_detail_inro.html
https://wenku.baidu.com/view/f02078db50e2524de5187e45.html
https://lartc.org/howto/lartc.cookbook.ultimate-tc.html#AEN2233
TC命令规则,及语法
#Linux流量控制主要分为建立队列,建立分类和建立过滤器三个方面。
1:争对物理接口设备,建立队列(QDisc)
2:建立分类(Class)
3:建立过滤器(FIlter)
4:最后与过滤器相配合,建立特定的路由表
#命令规则:
1:所有的QDisc,类和过滤器都有ID。
2:ID可以手工设置,也可以有内核自动分配。
3:ID由一个主序列号和一个从序列号组成,两个数字之间用一个冒号分开。
#流量控制处理对象
QDISC:(排队规则,队列) 一个QDisc会被分配一个主序列号,称为句柄(handle),然后把从序列号作为类的命名空间。句柄采用像“10:” 一样的表达方式。习惯上,需要为有子类的QDisc显式地分配一个句柄。
CLASS:(类别) 在同一个QDisc里面的类共享这个QDisc的主序列号,但是每个类都有自己的从序列号,叫做类识别符(classid)。类识别符只与父QDisc有关,和父类无关。类的命名习惯和QDisc的相同,编号小的优先。
FILTER:(过滤器) 过滤器的ID有三部分,只有在对过滤器进行散列组织才会用到。详情请参考tc-filters手册页。
#TC命令:
add: 在一个节点里加入一个队列、类、过滤器。添加时,需要传递一个祖先作为参数,传递参数时既可以使用ID也可以直接传递设备的根。如果要建立一个队列规定或者过滤器,可以使用句柄(句柄)来命名;如果要建立一个类,可以使用类识别符(classid)来命名。
del: 删除有某个句柄(句柄)指定的QDisc,根QDisc(root)也可以删除。被删除QDisc上的所有子类以及附属于各个类的过滤器都会被自动删除。
change:以替代的方式修改某些附加。另外句柄(句柄)和祖先不能修改其他,更改命令的语法和添加命令相同。
replace:对一个现有的常规进行近于原子操作的删除/添加。如果中断不存在,这个命令就会建立例程。
link: 仅适用于DQisc,替代一个现有的例程。
#语法简览
tc qdisc [ add | change | replace | link ] dev DEV [ parent qdisc-id | root ] [ handle qdisc-id ] qdisc [ qdisc specific parameters ]
tc class [ add | change | replace ] dev DEV parent qdisc-id [ classid class-id ] qdisc [ qdisc specific parameters ]
tc filter [ add | change | replace ] dev DEV [ parent qdisc-id | root ] protocol protocol prio priority filtertype [ filtertype specific parameters ] flowid flow-id
tc [-s | -d ] qdisc show [ dev DEV ]
tc [-s | -d ] class show dev DEV tc filter show dev DEV
#示例
#tc qdisc add dev ens33 root tbf rate 100mbit latency 50ms burst 1000
#tc qdisc change dev ens33 root tbf rate 200mbit latency 50ms burst 1000
#tc qdisc change dev ens33 root tbf rate 300mbit latency 50ms burst 1000
#tc qdisc del dev ens33 root tbf rate 300mbit latency 50ms burst 1000
流量控制包括以下4种方式
1:SHAPING(限制)
#当流量被限制,它的传输速率就被控制在某个值以下。限制值可以大大小于有效带宽,这样可以平滑突发数据流量,使网络更为稳定。shaping(限制)只适用于向外的流量。
2:SCHEDULING(调度)
#通过调度数据包的传输,可以在带宽范围内,按照优先级分配带宽。SCHEDULING(调度)也只适于向外的流量。
3:POLICING(策略)
#SHAPING用于处理向外的流量,而POLICIING(策略)用于处理接收到的数据。
4:DROPPING(丢弃)
#如果流量超过某个设定的带宽,就丢弃数据包,不管是向内还是向外。
实列一:WEB 服务器的流量控制为 5Mbps,SMTP 流量控制在 3Mbps 上 . 而且二者一共不得超过 6Mbps, 互相之间允许借用带宽
实现方法一:使用CBQ进行实现
#这里用CBQ来实现,将一个cbq绑定到网络物理设备eth0上,其编号为1:0;网络物理设备eth0的实际长度为100 Mbit,包的平均大小为1000字节;包间隔发送单元的大小为8个字节,最小传输包大小为64个字节。
tc qdisc add dev eth0 root handle 1:0 cbq bandwidth 100Mbit avpkt 1000 cell 8 mpu 64
#这部分按惯例设置了根为 1:0, 并且绑定了类 1:1. 也就是说整个带宽不能超过 6Mbps. 优先级为8,最大传输单元加MAC头的大小为1514字节,包的平均大小为1000字节,包间隔发送单元的大小为8字节
tc class add dev eth0 parent 1:0 classid 1:1 cbq bandwidth 100Mbit rate 6Mbit weight 0.6Mbit prio 8 allot 1514 cell 8 maxburst 20 avpkt 1000 bounded
#建立2 个类 . 注意我们如何根据带宽来调整 weight 参数的 . 两个类都没有配置成"bounded", 但它们都连接到了类 1:1 上 , 而 1:1 设置了"bounded". 所以两个类的总带宽不会超过 6Mbps.
#别忘了同一个 CBQ 下面的子类的主号码都必须与 CBQ 自己的号码相一致 !
tc class add dev eth0 parent 1:1 classid 1:3 cbq bandwidth 100Mbit rate 5Mbit weight 0.5Mbit prio 5 allot 1514 cell 8 maxburst 20 avpkt 1000
tc class add dev eth0 parent 1:1 classid 1:4 cbq bandwidth 100Mbit rate 3Mbit weight 0.3Mbit prio 5 allot 1514 cell 8 maxburst 20 avpkt 1000
#缺省情况下 , 两个类都有一个 FIFO 队列规定 . 但是我们把它换成 SFQ 队列 , 以保证每个数据流都公平对待 .
tc qdisc add dev eth0 parent 1:3 handle 30: sfq
tc qdisc add dev eth0 parent 1:4 handle 40: sfq
#建立过滤器,根据端口来表示WEB流量,以及SMTP流量
tc filter add dev eth0 parent 1:0 protocol ip prio 1 u32 match ip sport 80 0xffff flowid 1:3
tc filter add dev eth0 parent 1:0 protocol ip prio 1 u32 match ip sport 25 0xffff flowid 1:4
#测试完成后,若是要清除你的配置
tc qdisc del dev eth0 root handle 1:0 cbq bandwidth 100Mbit avpkt 1000 cell 8 mpu 64
实现方法二:使用HTB进行实现
#这里用HTB来实现
tc qdisc add dev eth0 root handle 1: htb default 30
tc class add dev eth0 parent 1: classid 1:1 htb rate 6mbit burst 15k
tc class add dev eth0 parent 1:1 classid 1:10 htb rate 5mbit ceil 6mbit burst 15k
tc class add dev eth0 parent 1:1 classid 1:20 htb rate 3mbit ceil 6mbit burst 15k
#rate: 是一个类保证得到的带宽值.如果有不只一个类,请保证所有子类总和是小于或等于父类.
#ceil: ceil是一个类最大能得到的带宽值
tc qdisc add dev eth0 parent 1:10 handle 10: sfq perturb 10
tc qdisc add dev eth0 parent 1:20 handle 20: sfq perturb 10
#perturb:是多少秒后重新配置一次散列算法,默认为10秒
#sfq,他可以防止一个段内的一个ip占用整个带宽
#添加过滤器 , 直接把流量导向相应的类 :
U32="tc filter add dev eth0 protocol ip parent 1:0 prio 1 u32"
$U32 match ip sport 80 0xffff flowid 1:10
$U32 match ip dport 25 0xffff flowid 1:20
实现方法三:使用HTB进行实现(推荐使用)
tc qdisc add dev eth0 root handle 1: htb default 21
tc class add dev eth0 parent 1: classid 1:2 htb rate 6mbit ceil 6mbit
tc class add dev eth0 parent 1: classid 1:21 htb rate 5mbit ceil 6mbit
tc class add dev eth0 parent 1:2 classid 1:22 htb rate 3mbit ceil 6mbit
tc filter add dev eth0 protocol ip parent 1: prio 1 u32 match ip sport 80 0xffff flowid 1:21
tc filter add dev eth0 protocol ip parent 1:2 prio 1 u32 match ip dport 25 0xffff flowid 1:22
#这里为根队列1创建一个根类别,即1:2,其中1:2对应6Mbit的数据流。然后,在1:2中,创建两个子类别1:21和1:22,分别对应WWW和E-mail数据流。由于类别1:21和1:22是类别1:2的子类别,因此他们可以共享分配的86Mbit带宽。同时,又确保当需要时,自己的带宽。
Linux 流量控制之 U32 过滤规则
#在10: 节点添加一个过滤规则,优先权1: 凡是去往22口(精确匹配)的IP数据包,发送到频道10:1..
tc filter add dev eth0 protocol ip parent 10: prio 1 u32 match ip dport 22 0xffff flowid 10:1
#在10: 节点添加一个过滤规则,优先权1: 凡是来自80口(精确匹配)的IP数据包,发送到频道 10:1..
tc filter add dev eth0 protocol ip parent 10: prio 1 u32 match ip sport 80 0xffff flowid 10:1
#在eth0 上的 10: 节点添加一个过滤规则,它的优先权是2: 凡是上二句未匹配的IP数据包,发送到频道10:2..
tc filter add dev eth0 protocol ip parent 10: prio 2 flowid 10:2
#去往4.3.2.1的包发送到频道10:1其它参数同上例
tc filter add dev eth0 parent 10:0 protocol ip prio 1 u32 match ip dst 4.3.2.1/32 flowid 10:1
#来自1.2.3.4的包发到频道10:1
tc filter add dev eth0 parent 10:0 protocol ip prio 1 u32 match ip src 1.2.3.4/32 flowid 10:1
#凡上二句未匹配的包送往10:2
tc filter add dev eth0 protocol ip parent 10: prio 2 flowid 10:2
#可连续使用match,匹配来自1.2.3.4的80口的数据包
tc filter add dev eth0 parent 10:0 protocol ip prio 1 u32 match ip src 4.3.2.1/32 match ip sport 80 0xffff flowid 10:1
#根据源/目的地址
'match ip src 1.2.3.0/24'
'match ip dst 4.3.2.0/24'
#单个IP地址
'match ip 1.2.3.4/32'
#根据源/目的端口 , 所有IP协议
'match ip sport 80 0xffff' 0xffff 表所有数据包
'match ip dport 80 0xffff'
#根据 IP 协议 (tcp, udp, icmp, gre, ipsec) /etc/protocols 文件里有协议号
'match ip protocol 1 0xff'
#根据 fwmark
iptables -A PREROUTING -t mangle -i eth0 -j MARK --set-mark 6
tc filter add dev eth1 protocol ip parent 1:0 prio 1 handle 6 fw flowid 1:1
注 :handle 根据过滤器的不同 , 含义也不同
#按 TOS 字段
tc filter add dev ppp0 parent 1:0 protocol ip prio 10 u32 match ip tos 0x10 0xff
#flowid 1:4 选择交互和最小延迟的数据流 匹配大量传输 , 使用"0x08 0xff".
tc filter add dev eth0 protocol ip parent 1:0 pref 10 u32 match u32 00100000 00ff0000
查看现有变量,分类,过滤器和路由的状况
#显示队列的状况
tc qdisc ls dev eth0 #简单显示
tc -s qdisc ls dev eth0 #详细显示(等同于 tc -s qd sh dev eth0)
#显示分类的状况
tc class ls dev eth0 #简单显示
tc -s class ls dev eth0 #详细显示(等同于 tc -s cl ls dev eth0)
#显示过滤器的状况
tc filter ls dev eth0 #简单显示
tc -s filter ls dev eth0 #详细显示(等同于 tc -s fi ls dev eth0)
#流量控制模拟
tc qd add dev eth1 root handle 1: tbf rate 256kbit burst 10000 latency 50ms
速率 256kbit 突发传输 10k 最大延迟 50ms
tc qd del dev eth1 root 删除
学习实列一
#清理现有的下行和上行qdiscs,隐藏错误
tc qdisc del dev eth0 root 2> /dev/null > /dev/null
tc qdisc del dev eth0 ingress 2> /dev/null > /dev/null
#安装根HTB(root htb),将默认流量指向1:20:
tc qdisc add dev eth0 root handle 1: htb default 20
#塑造为$上行速度的一切 - 这可以防止巨大的队列中的,破坏延迟的DSL调制解调器:
tc class add dev eth0 parent 1: classid 1:1 htb rate 220kbit burst 6k
#高优先级1:10:
tc class add dev eth0 parent 1:1 classid 1:10 htb rate 220kbit burst 6k prio 1
#较低的优先级1:20,批量和默认类别1:20-获得的流量略少,
tc class add dev eth0 parent 1:1 classid 1:20 htb rate [9*220/10]kbit burst 6k prio 2
#都获得随机公平性:
tc qdisc add dev eth0 parent 1:10 handle 10: sfq perturb 10
tc qdisc add dev eth0 parent 1:20 handle 20: sfq perturb 10
#TOS最小延迟(ssh,NOT scp)在1:10中:
tc filter add dev eth0 parent 1:0 protocol ip prio 10 u32 match ip tos 0x10 0xff flowid 1:10
#ICMP(IP协议1)在交互式类1:10中,所以我们可以进行测量并打动我们的朋友:
tc filter add dev eth0 parent 1:0 protocol ip prio 10 u32 \
match ip protocol 1 0xff flowid 1:10
#为了加快上传过程中的下载速度,请在其中放入ACK数据包
tc filter add dev eth0 parent 1: protocol ip prio 10 u32 \
match ip protocol 6 0xff \
match u8 0x05 0x0f at 0 \
match u16 0x0000 0xffc0 at 2 \
match u8 0x10 0xff at 33 \
flowid 1:10
#将下载速度降低到略低于实际速度以防止,在我们的ISP排队调一下看看你能调多高。ISP往往会有*大*队列来确保大的下载速度
tc qdisc add dev eth0 handle ffff: ingress
# filter *everything* to it (0.0.0.0/0), drop everything that's
# coming in too fast:
tc filter add dev eth0 parent ffff: protocol ip prio 50 u32 match ip src \
0.0.0.0/0 police rate 800kbit burst 10k drop flowid :1
如果最后两行出现错误,请将您的tc工具更新为较新的版本!
学习实列二
tc qdisc del dev $DEV root 2> /dev/null > /dev/null
tc qdisc del dev $DEV ingress 2> /dev/null > /dev/null
tc qdisc add dev $DEV root handle 1: cbq avpkt 1000 bandwidth 10mbit
tc class add dev $DEV parent 1: classid 1:1 cbq rate ${UPLINK}kbit allot 1500 prio 5 bounded isolated
tc class add dev $DEV parent 1:1 classid 1:10 cbq rate ${UPLINK}kbit allot 1600 prio 1 avpkt 1000
tc class add dev $DEV parent 1:1 classid 1:20 cbq rate $[9*$UPLINK/10]kbit allot 1600 prio 2 avpkt 1000
tc qdisc add dev $DEV parent 1:10 handle 10: sfq perturb 10
tc qdisc add dev $DEV parent 1:20 handle 20: sfq perturb 10
tc filter add dev $DEV parent 1:0 protocol ip prio 10 u32 match ip tos 0x10 0xff flowid 1:10
tc filter add dev $DEV parent 1:0 protocol ip prio 11 u32 match ip protocol 1 0xff flowid 1:10
tc filter add dev $DEV parent 1: protocol ip prio 12 u32 match ip protocol 6 0xff \
match u8 0x05 0x0f at 0 \
match u16 0x0000 0xffc0 at 2 \
match u8 0x10 0xff at 33 \
flowid 1:10
tc filter add dev $DEV parent 1: protocol ip prio 13 u32 match ip dst 0.0.0.0/0 flowid 1:20
tc qdisc add dev $DEV handle ffff: ingress
tc filter add dev $DEV parent ffff: protocol ip prio 50 u32 match ip src \
0.0.0.0/0 police rate ${DOWNLINK}kbit burst 10k drop flowid :1
如果文章对你有帮助,欢迎点击上方按钮打赏作者
暂无评论