关于iptables和tc的限速理解

关于iptables

iptables是包过滤软件,包过滤的顺序如下:

鸟哥的iptables图

每一个包都会匹配rule策略,而每一个rule策略会有一个action,触发了其中一个rule就不会触发另外一个rule,但如果要触发的rule放在最后面,那么可以想象,包过滤的效率就会大大降低,所以设计策略的时候要尽量将常用的策略放在最前面,策略的顺序可以通过不断的调整 -A 和-I策略,甚至还有return的动作,设计iptables的人真的很厉害。

这是iptables内部的table表和chain链,可以理解为iptables是一个大网,table就是小网,里面的chain就是他的网线,当数据包经过这个小网的时候必然会触碰这些网线,这样“看不顺眼”的数据包就会被拦住。鸟哥的图画的真好。这里需要理解的是数据包的流行会分2个地方,就是进入本机或者不进入本机,进入本机的包就会走input的chain链,不进入本机的包就会去FORWARD,什么是进入或者不进入呢?

举个例子就是这是一台路由器服务器,服务器上面假设了web服务器,然后这个路由器负责的内部网络还有一台数据库服务器,不过这台服务器是独立于路由器的另外一台机器,不过上网也是要经过路由器,那么一个外网用户访问这个web服务器和访问数据库服务器的行为就是进入本机和不进入本机的行为,因为web服务器是跟路由器在同一台机器上的,所以要进入本机,因为数据库服务器是另外一台机器上的,所以不进入本机。解释得好渣,还是看鸟哥吧。鸟哥乃神人。回归主题,看下图的结构,可以看出如果我们要在iptables上操刀的话可以在任何表上操刀,例如可以在PREROUTING,FORWARD,POSTROUTING表上做限速是完全没有问题的,前提是要注意不能冲突,每个表都有各自的作用。所以一般来说,要写iptables策略的时候都要跟着这个图来笔画一下,这样才能知道有没有写错。

filter (過濾器):主要跟進入 Linux 本機的封包有關,這個是預設的 table 喔!
INPUT:主要與想要進入我們 Linux 本機的封包有關;
OUTPUT:主要與我們 Linux 本機所要送出的封包有關;
FORWARD:這個咚咚與 Linux 本機比較沒有關係, 他可以『轉遞封包』到後端的電腦中,與下列 nat table 相關性較高。

nat (位址轉換):是 Network Address Translation 的縮寫, 這個表格主要在進行來源與目的之 IP 或 port 的轉換,與 Linux 本機較無關,主要與 Linux 主機後的區域網路內電腦較有相關。
PREROUTING:在進行路由判斷之前所要進行的規則(DNAT/REDIRECT)
POSTROUTING:在進行路由判斷之後所要進行的規則(SNAT/MASQUERADE)
OUTPUT:與發送出去的封包有關

mangle (破壞者):這個表格主要是與特殊的封包的路由旗標有關, 早期僅有 PREROUTING 及 OUTPUT 鏈,不過從 kernel 2.4.18 之後加入了 INPUT 及 FORWARD 鏈。 由於這個表格與特殊旗標相關性較高,所以像咱們這種單純的環境當中,較少使用 mangle 這個表格。
Table (表名) Explanation (注释)
nat nat表的主要用处是网络地址转换,即Network Address Translation,缩写为NAT。做过NAT操作的数据包的地址就被改变了,当然这种改变是根据我们的规则进行 的。属于一个流的包只会经过这个表一次。如果第一个包被允许做NAT或Masqueraded,那么余下的包都会自 动地被做相同的操作。也就是说,余下的包不会再通过这个表,一个一个的被NAT,而是自动地完成。这就 是我们为什么不应该在这个表中做任何过滤的主要原因,对这一点,后面会有更加详细的讨论。PREROUTING 链的作用是在包刚刚到达防火墙时改变它的目的地址,如果需要的话。OUTPUT链改变本地产生的包的目的地 址。POSTROUTING链在包就要离开防火墙之前改变其源地址。
mangle 这个表主要用来mangle数据包。我们可以改变不同的包及包 头的内容,比如 TTL,TOS或MARK。 注意MARK并没有真正地改动数据包,它只是在内核空间为包设了一个标记。防火墙 内的其他的规则或程序(如tc)可以使用这种标记对包进行过滤或高级路由。这个表有五个内建的链: PREROUTING,POSTROUTING, OUTPUT,INPUT和 FORWARD。PREROUTING在包进入防火墙之后、路由判断之前改变 包,POSTROUTING是在所有路由判断之后。 OUTPUT在确定包的目的之前更改数据包。INPUT在包被路由到本地 之后,但在用户空间的程序看到它之前改变包。FORWARD在最初的路由判 断之后、最后一次更改包的目的之前mangle包。注意,mangle表不能做任何NAT,它只是改变数据包的 TTL,TOS或MARK,而不是其源目地 址。NAT是在nat表中操作的。
filter filter表是专门过滤包 的,内建三个链,可以毫无问题地对包进行DROP、LOG、ACCEPT和REJECT等操作。FORWARD 链过滤所有不是本地产生的并且目的地不是本地(所谓本地就是防火墙了)的包,而 INPUT恰恰针对那些目的地是本地的包。OUTPUT 是用来过滤所有本地生成的包的
鸟哥的iptables图
  • iptables是主要工作在第三,四层的,即主要处理ip、tcp,偶尔能够在第七层工作是因为打了patch。

  • 什么是数据包:其实就是只ip数据包和tcp数据包

包(Packet)是TCP/IP协议通信传输中的数据单位,一般也称“数据包”。有人说,局域网中传输的不是“帧”(Frame)吗?没错,但是TCP/IP协议是工作在OSI模型第三层(网络层)、第四层(传输层)上的,而帧是工作在第二层(数据链路层)。上一层的内容由下一层的内容来传输,所以在局域网中,“包”是包含在“帧”里的。

举例来说tcp包的包头含有以下这些信息(等等):

信息|解释|iptables关键字
------------- | -------------
源ip地址|发送包的IP地址。|src
目的IP地址|接收包的IP地址。|dst
源端口|源系统上的连接的端口。|sport
目的端口|目的系统上的连接的端口。|dport

osi7层图

关于tc

TC--Traffic Control

TC是linux中的流量控制模块,利用队列规定建立起数据包队列,并定义了队列中数据包的发送方式,从而实现对流量的控制。关键字:队列系统,包接收和传输。

Traffic control is the name given to the sets of queuing systems and mechanisms by which packets are received and transmitted on a router. This includes deciding which (and whether) packets to accept at what rate on the input of an interface and determining which packets to transmit in what order at what rate on the output of an interface.

这里是官方翻译:http://my.oschina.net/guol/blog/82453?p=1

原版:http://www.tldp.org/HOWTO/Traffic-Control-HOWTO/

tc工作位置图:

tc工作位置图

在我使用的过程中,对于他的理解是有一些加深了:

  1. tc就是看门的,like as a dog,所以这就可以解释了为什么要iptables+tc了,tc能够和iptables合作,因为可以从图上看到各自工作的位置是不一样的,各施其职。

  2. tc对于包一视同仁,专门负责包的排队分发,官方里面提到一个很经典的说法就是他是一个接收和传输的队列系统,tc翻译为交通管制是很巧妙的,有鉴于此,我认为他的限速效果最好,无论你是p2p包还是什么加密包,只要是包就要受到约束,这样就可以避免了那些日新月异的封装加密之类的包被逃掉了。

  3. tc主要是以mark的形式来匹配,所以使用的时候mark标记需要注意不要冲突,mark标记是iptables里面提到的一个东西:

    6.5.5. MARK target

    用来设置mark值,这个值只能在本地的mangle表里使用,不能用在其他任何地方,就更不用说路由器或 另一台机子了。因为mark比较特殊,它不是包本身的一部分,而是在包穿越计算机的过程中由内核分配的和 它相关联的一个字段。它可以和本地的高级路由功能联用,以使不同的包能使用不同的队列要求,等等。如 果你想在传输过程中也有这种功能,还是用TOS target吧。有关高级路由的更多信息,可以查看Linux Advanced Routing and Traffic Control HOW-TO。

    mark只能存在于内核之中,不受三界法则影响,所以mark值我觉得是配置tc的特别需要注意的地方,尤其是如果你使用了wifidog之类的要玩mark的时候。

  4. tc的类是树架构,有主干和叶这样很分明的区分的,这种层次是很容易理解的,不过文档的解释是相当的难理解,难理解的是怎么做,命令写法简直坑爹。

  5. 涉及很多相当高深的队列算法,流控制模式其实略懂就行了,诸葛先生不也就略懂么。所以不是那种极端情况其实无须特别考虑这个。

  6. 对于tc来说,上传和下载行为是这样区分的,上传,就是用户端发送数据包给服务器,假设路由器是双网卡,所以负责发送数据包给服务器的是外网网卡,所以限制上传速度在外网网卡处, 下载,就是服务器发送数据包给用户,因为路由器是双网卡的关系,所以负责发送数据包给用户的是内网网卡,所以限制下载速度是在内网网卡,因为tc是一个能够负责接收数据包的工具,所以限制上传速度其实就是限制外网网卡接收用户发送的数据包的速度,而限制下载速度其实就是限制内网网卡接收到要发送给用户的数据包的速度。


测试流程介绍

  1. 首先需要建立tc策略
  2. 然后由iptables 来进行调用,主要通过set mark,根据不同的mark标记来进行不同的tc策略调用

备注:

  1. 测试环境是eth0负责外网,p3p1是负责内网
  2. 考虑到特殊需求,tc限制的是所有的包,所以需要iptables将发到内网服务器的包分开处理,以便实现访问外网能够限制网速,访问内网没有限制

上传:

清除 eth0 所有队列规则
tc qdisc del dev eth0 root 2>/dev/null

定义最顶层(根)队列规则,并指定 default 类别编号,为网络接口eth1 绑定一个队列,类型为htb,并指定了一个handle句柄1:0用于标识它下面的子类,没有标识的会被分配到默认子类123(默认值只是设置而已,可以不用)
tc qdisc add dev eth0 root handle 1:0 htb default 123

用于为队列建一个主干类,带宽为100Mbit,最大速率为100Mbit,(这里是bit,所以实际速度需要除以8)优先级为0,htb的主干类不能互相借用带宽,但是一个父类的所有子类之间可以借用带宽,这里parent 1:0是刚才建立的handle1:0 ,classid是他的子类,分类号为1:1,冒号前面是父类号
后面是子类号
tc class add dev eth0 parent 1:0 classid 1:1 htb rate 100Mbit ceil 100Mbit prio 0

为主干类建立第一个叶分类,带宽为10Mbit,最大速为10Mbit,优先级为1,所有叶分类的全部子类优先级低于主干类,
以防止重要数据堵塞,主要还是避免逻辑混乱,10Mbit必须要有96kbit的burst速度
tc class add dev eth0 parent 1:1 classid 1:11 htb rate 10Mbit ceil 10Mbit prio 1 burst 96kbit

设置调度,sfq随机公平算法,这里的parent是指隶属于之前的子分类,你需要对哪一个子分类的条目做队列分配控制就需要在这里写对应的子分类id
在每个类下面再附加上另一个队列规定,随机公平队列(SFQ),不被某个连接不停占用带宽,以保证带宽的平均公平使用:
        #SFQ(Stochastic Fairness Queueing,随机公平队列),SFQ的关键词是“会话”(或称作“流”) ,
        #主要针对一个TCP会话或者UDP流。流量被分成相当多数量的FIFO队列中,每个队列对应一个会话。
        #数据按照简单轮转的方式发送, 每个会话都按顺序得到发送机会。这种方式非常公平,保证了每一
        #个会话都不会没其它会话所淹没。SFQ之所以被称为“随机”,是因为它并不是真的为每一个会话创建
        #一个队列,而是使用一个散列算法,把所有的会话映射到有限的几个队列中去。
        #参数perturb是多少秒后重新配置一次散列算法。默认为10
tc qdisc add dev eth0 parent 1:11 handle 111:0 sfq perturb 10

设置过滤器filter,对应之前配置的哪一个父类和子类,然后设置控制编号handle,这里是跟iptables的mark相对应的,并且多个不同的filter注意prio不要相同。
tc filter add dev eth0 parent 1:0 protocol ip prio 1 handle 1001 fw classid 1:11

设置iptables规则,在mangle表的postroutingchain上配置,源地址是172.16.1.138并且目标地址不是192.168.0.10,从网卡eth0发出的包进行mark,mark号是1001
iptables -t mangle -A POSTROUTING -s 172.16.1.138/32 ! -d 192.168.0.10 -o eth0 -j MARK --set-xmark 1001
设置return是为了加快包检查,return的顺序是:子链——>父链——>缺省的策略,检查到源地址是172.16.1.138并且目标地址不是192.168.0.10的包就会跳到postrouting层,然后会继续检查其他这层的chain,这样不用每个包都要检查一次这条chain的内容了,加快了一倍的速度,
iptables -t mangle -A POSTROUTING -o eth0 -s 172.16.1.138 ! -d 192.168.0.10 -j RETURN

下载:

tc qdisc del dev p3p1 root 2>/dev/null

tc qdisc add dev p3p1 root handle 1:0 htb default 123

tc class add dev p3p1 parent 1:0 classid 1:1 htb rate 100Mbit ceil 100Mbit prio 0

tc class add dev p3p1 parent 1:1 classid 1:11 htb rate 10Mbit ceil 10Mbit prio 1

tc qdisc add dev p3p1 parent 1:11 handle 111:0 sfq perturb 10

tc filter add dev p3p1 parent 1:0 protocol ip prio 1 handle 1000 fw classid 1:11

这里用I的是insert一条配置,这样排序会放在前面,因为iptables是按顺序匹配的,并且为了跟wifidog的策略避免冲突
iptables -t mangle -I POSTROUTING -o p3p1 -d 172.16.1.138 ! -s 192.168.0.10 -j MARK --set-mark 1000
iptables -t mangle -I POSTROUTING -o p3p1 -d 172.16.1.138 ! -s 192.168.0.10 -j RETURN

EOF完


引用:

  1. http://man.chinaunix.net/network/iptables-tutorial-cn-1.1.19.html
  2. http://linux.vbird.org/linux_server/0250simple_firewall.php
  3. http://www.tldp.org/HOWTO/Traffic-Control-HOWTO/
  4. http://my.oschina.net/guol/blog/82453?p=1
  5. http://www.lartc.org/howto/
  6. http://chuansongme.com/n/403831
  7. http://blog.sina.com.cn/s/blog_4b9633a6010007l7.html
  8. http://blog.sina.com.cn/s/blog_60244a2e0100d4t8.html
  9. http://wenku.baidu.com/view/cd450e82e53a580216fcfe59.html

原文出处:http://www.godblessyuan.com/2015/01/18/iptables_tc_bandwidth_limiting/

你可能感兴趣的:(关于iptables和tc的限速理解)