模拟网络丢包延迟和TC的使用
iptables方案
这个方案纯基于iptables,不需要内核模块,对容器更加友好一些。
iptables -A OUTPUT -d xx.xx.xx.xx -m statistic --mode random --probability 0.1 -j DROP
但是这个方案有个副作用。ping的时候,能看到错误“不允许的操作”。
tc方案
tc方案相对比较复杂。我们先不说这些复杂的事情,先说结果。
tc qd add dev wlan0 root netem delay 100ms
tc qd change dev wlan0 root netem loss 50%
一个是延迟一个是丢包,一个是设定一个是修改。netem还允许你做乱序和重复。方法就不细写了。删除是这么干。
tc qd del dev wlan0 root netem
你再用tc qd show
看看是不是规则已经没了?
tc简述
tc是linux下面用来控制网络发包(注意是发包)的一套系统。基本的设计目标是确定优先级,限流,也有测试性的丢包之类的策略。可以配合iptables和route协同工作。
基本原理
包从进入tc开始,分为多个qd(qdisc)。每个qd可以包含多个子qd,qd彼此连接形成一颗树。每个qd上可以附加filter,选择进入哪个child。如果都没命中,那就看本身规则。
我们先从最简单的例子开始。将root qd改为prio。
sudo tc qdisc add dev eth0 root handle 1: prio
使用tc qd show
查看变化。完成后使用sudo tc qdisc del dev eth root
删除变化,还原为默认的pfifo_fast。
使用filter来分类
要分类,最低是两类。一类父,一类子。具体进入哪个sub-class可以用filter来设定。filter可以用sudo tc filter show dev eth0
来查看。注意,这里必须附加dev。
sudo tc qdisc del dev eth0 root
sudo tc qdisc add dev eth0 root handle 1: prio
sudo tc qdisc add dev eth0 parent 1:1 handle 10: netem delay 1s loss 2%
sudo tc filter del dev eth0
sudo tc filter add dev eth0 protocol ip parent 1: prio 1 u32 match ip dst 192.168.33.1 flowid 1:1
完成后,192.168.33.1被延迟,192.168.33.2无效果。
注意prio的默认bands是3,因此直接插入parent 1:4会报错。
sudo tc qdisc del dev eth0 root
sudo tc qdisc add dev eth0 root handle 1: prio
sudo tc qdisc add dev eth0 parent 1:3 handle 30: netem delay 1s loss 2%
sudo tc qdisc add dev eth0 parent 1:4 handle 40: sfq
将bands改为5问题消失。
sudo tc qdisc del dev eth0 root
sudo tc qdisc add dev eth0 root handle 1: prio bands 5
sudo tc qdisc add dev eth0 parent 1:3 handle 30: netem delay 1s loss 2%
sudo tc qdisc add dev eth0 parent 1:4 handle 40: sfq
将flowid更换为classid将会导致不起作用。
sudo tc qdisc del dev eth0 root
sudo tc qdisc add dev eth0 root handle 1: prio
sudo tc qdisc add dev eth0 parent 1:1 handle 10: netem delay 1s loss 2%
sudo tc filter del dev eth0
sudo tc filter add dev eth0 protocol ip parent 1: prio 1 u32 match ip dst 192.168.33.1 flowid 20:
此时ping 192.168.33.1,结果没有延迟。
多个sub-class的例子
更复杂的例子。在prio下面分了多个sub-class。命中IP的进入延迟,未命中IP的按照prio的规则走。在prio里,使用priomap将prio映射到不同的sub-class。测试下来,ICMP报文的默认规则将是1:2。
sudo tc qdisc del dev eth0 root
sudo tc qdisc add dev eth0 root handle 1: prio
sudo tc qdisc add dev eth0 parent 1:1 handle 10: netem delay 1s loss 2%
sudo tc qdisc add dev eth0 parent 1:2 handle 20: netem delay 2s loss 2%
sudo tc qdisc add dev eth0 parent 1:3 handle 30: netem delay 3s loss 2%
sudo tc filter del dev eth0
sudo tc filter add dev eth0 protocol ip parent 1: prio 1 u32 match ip dst 192.168.33.1 flowid 1:1
sudo tc filter add dev eth0 protocol ip parent 1: prio 1 u32 match ip dst 192.168.33.2 flowid 1:2
sudo tc filter add dev eth0 protocol ip parent 1: prio 1 u32 match ip dst 192.168.33.3 flowid 1:3
测试ping 192.168.33.4,结果是延迟2s。
tc+filter方案
运用’多个sub-class的例子’的同类方法可以用于将特定IP延迟丢包,其他走默认的pfifo_fast。
sudo tc qdisc del dev eth0 root
sudo tc qdisc add dev eth0 root handle 1: prio
sudo tc qdisc add dev eth0 parent 1:1 handle 10: netem delay 1s loss 2%
sudo tc qdisc add dev eth0 parent 1:2 handle 20: pfifo_fast
sudo tc filter del dev eth0
sudo tc filter add dev eth0 protocol ip parent 1: prio 1 u32 match ip dst 192.168.33.1 flowid 1:1
sudo tc filter add dev eth0 protocol ip parent 1: prio 1 u32 match ip dst 192.168.33.2 flowid 1:1
tc+iptables方案
我们也可以不用内置的u32 filter来做流量分离,而是先用iptables做mark,然后根据mark来做流量分离。
sudo tc qdisc del dev eth0 root
sudo tc qdisc add dev eth0 root handle 1: prio
sudo tc qdisc add dev eth0 parent 1:1 handle 10: netem delay 1s
sudo tc qdisc add dev eth0 parent 1:3 handle 30: netem delay 2s
sudo tc filter del dev eth0
sudo tc filter add dev eth0 parent 1:0 prio 1 protocol ip handle 5 fw flowid 1:1
sudo tc filter add dev eth0 parent 1:0 prio 0 protocol ip handle 6 fw flowid 1:3
sudo iptables -F OUTPUT -t mangle
sudo iptables -A OUTPUT -t mangle -p icmp -d 192.168.33.1 -j MARK --set-mark 5
sudo iptables -A OUTPUT -t mangle -p icmp -d 192.168.33.2 -j MARK --set-mark 6
这个方案和filter方案没有什么本质性区别,但是使用iptables完成,个人觉得更加灵活一些。
清除和持久化
刚刚把脚本全部跑了的同学,别忘了执行一下语句清理环境。不然残留各种垃圾配置的话,上网的时候会很慢哦。
sudo iptables -F OUTPUT -t mangle
sudo tc filter del dev eth0
sudo tc qdisc del dev eth0 root
如果希望效果持久,可以将语句添加到rc.local里。但是实话说,我还没见过谁希望自己的系统一开机就变慢呢。QoS倒是有可能。