QOS的整个流程是:根据各种条件,如IP地址,数据包大小,上行,下行,这个信息在iptables里面都可以捕获到。然在iptables根据这些规则设置对应的mark,设置完mark,tc规则规则里面根据不同的mark执行不同的内容,如队列分配,限制带宽,流量分配算法。


0 数据流向


  • -i 指定数据包进入 PREROUTING、INPUT、FORWARD链时经由的接口。
  • -o 指定数据包出去 FORWARD、OUTPUT、POSTROUTING链时经由的接口。

当我们开启防火墙功能后,报文需要经过的路径是有区别的,如下图所示:

2-iptables mangle 规则_初始化

报文的流向:


  • 到本机某进程的报文:PREROUTING–>INPUT
  • 由本机转发的报文:PREROUTING–>FORWARD–>POSTROUTING
  • 由本机某进程发出的报文:OUTPUT–>POSTROUTING

对于QOS我们要做的是对转发的包进行规则处理,而内部的包不应该进行干预,另外我们的功能需求有总规则跟设备规则,设备规则要在总规则之前设置,这样才能符合总规则的要求。

根据上面的需求,所以将设备规则放在FORWARD里面,总规则放在POSTROUTING里面。

iptables的底层就是netfilter,根据不同的链在2、3、4层进行分布着,如prerouting在判断是否为本机地址前面,所以应该是在第2层,在上面的iptables数据流程都走完后,会走到底层的TC规则再走一次TC规则的数据流

一个链ACCEPT后,跳出这个链,可是接下去的链还是会经过,接着匹配

1.链初始化(标准链关联QOS链)

脚本启动后会调用ipt_first_setup,将mangle表里面关于QOS的信息全部清楚一边(-F -X),然后重新创建新的规则链(-N),将新的规则链接到对应的标准链上(-g)。

mangle表的5个链PREROUTING、INPUT、FORWARD、OUTPUT、POSTROUTING

ipt_first_setup() {
ipt -t mangle -F QOS_MARK_${IFACE}
ipt -t mangle -X QOS_MARK_${IFACE}
ipt -t mangle -N QOS_MARK_${IFACE}

ipt -t mangle -F QOS_MARK_FORWARD_${IFACE}
ipt -t mangle -X QOS_MARK_FORWARD_${IFACE}
ipt -t mangle -N QOS_MARK_FORWARD_${IFACE}

ipt -t mangle -F QOS_OUTPUT_${IFACE}
ipt -t mangle -X QOS_OUTPUT_${IFACE}
ipt -t mangle -N QOS_OUTPUT_${IFACE}

ipt -t mangle -F QOS_INPUT_${IFACE}
ipt -t mangle -X QOS_INPUT_${IFACE}
ipt -t mangle -N QOS_INPUT_${IFACE}

ipt -t mangle -F QOS_RULES_${IFACE}
ipt -t mangle -X QOS_RULES_${IFACE}
ipt -t mangle -N QOS_RULES_${IFACE}

ipt -t mangle -F QOS_RULES_FORWARD_${IFACE}
ipt -t mangle -X QOS_RULES_FORWARD_${IFACE}
ipt -t mangle -N QOS_RULES_FORWARD_${IFACE}

ipt -t mangle -A POSTROUTING -o ${IFACE} -g QOS_MARK_${IFACE}
ipt -t mangle -A FORWARD -o ${IFACE} -g QOS_MARK_FORWARD_${IFACE}
ipt -t mangle -A OUTPUT -o ${IFACE} -g QOS_OUTPUT_${IFACE}
ipt -t mangle -A INPUT -i ${IFACE} -g QOS_INPUT_${IFACE}

ipt -t mangle -A QOS_OUTPUT_${IFACE} -j MARK --set-mark ${HFSC_NO_QOS_MARK}${IPT_MASK_STRING}
ipt -t mangle -A QOS_INPUT_${IFACE} -j MARK --set-mark ${HFSC_NO_QOS_MARK}${IPT_MASK_STRING}

# FORWARD use to match mac-source
ipt -t mangle -A QOS_MARK_FORWARD_${IFACE} -j CONNMARK \
--restore-mark --nfmask ${IPT_MASK} --ctmask ${IPT_MASK}
ipt -t mangle -A QOS_MARK_FORWARD_${IFACE} -m mark --mark 0x0${IPT_MASK_STRING} \
-j QOS_RULES_FORWARD_${IFACE}

ipt -t mangle -A QOS_MARK_${IFACE} -j CONNMARK \
--restore-mark --nfmask ${IPT_MASK} --ctmask ${IPT_MASK}
ipt -t mangle -A QOS_MARK_${IFACE} -m mark --mark 0x0${IPT_MASK_STRING} \
-j QOS_RULES_${IFACE}
...

2.QOS链信息

使用​​iptables -t mangle -nvL​​可以查看mangle表下面的规则:

默认的5条链如下,会关联到对应的target下面:

root@zihome:~# iptables -t mangle -nvL
Chain PREROUTING (policy ACCEPT 43144 packets, 12M bytes)
pkts bytes target prot opt in out source destination
43166 12M fwmark all -- * * 0.0.0.0/0 0.0.0.0/0

Chain INPUT (policy ACCEPT 31953 packets, 11M bytes)
pkts bytes target prot opt in out source destination
20362 9418K QOS_INPUT_eth1 all -- eth1 * 0.0.0.0/0 0.0.0.0/0 [goto]

Chain FORWARD (policy ACCEPT 12502 packets, 1631K bytes)
pkts bytes target prot opt in out source destination
12505 1632K mssfix all -- * * 0.0.0.0/0 0.0.0.0/0
7990 568K QOS_MARK_FORWARD_eth1 all -- * eth1 0.0.0.0/0 0.0.0.0/0 [goto]

Chain OUTPUT (policy ACCEPT 33467 packets, 5201K bytes)
pkts bytes target prot opt in out source destination
21999 2684K QOS_OUTPUT_eth1 all -- * eth1 0.0.0.0/0 0.0.0.0/0 [goto]

Chain POSTROUTING (policy ACCEPT 50234 packets, 7754K bytes)
pkts bytes target prot opt in out source destination
31325 3361K QOS_MARK_eth1 all -- * eth1 0.0.0.0/0 0.0.0.0/0 [goto]


2.1 PREROUTING链关联的target:
Chain PREROUTING (policy ACCEPT 43144 packets, 12M bytes)
pkts bytes target prot opt in out source destination
43166 12M fwmark all -- * * 0.0.0.0/0 0.0.0.0/0

Chain fwmark (1 references)
pkts bytes target prot opt in out source destination


对于PREROUTING的数据都不做处理,该怎样就怎样。

2.2 INPUT链关联的target:
Chain INPUT (policy ACCEPT 31953 packets, 11M bytes)
pkts bytes target prot opt in out source destination
20362 9418K QOS_INPUT_eth1 all -- eth1 * 0.0.0.0/0 0.0.0.0/0 [goto]

Chain QOS_INPUT_eth1 (1 references)
pkts bytes target prot opt in out source destination
20362 9418K MARK all -- * * 0.0.0.0/0 0.0.0.0/0 MARK xset 0xff/0xfffff

对于从eth1进来给内部进程的数据,全部goto到​​QOS_INPUT_eth1​​规则,改规则将进来的包都设置成0xff/0xfffff标记。

在tc规则里面,0xff走no qos队列,不做QOS处理。

2.3 OUTPUT链关联的target:
Chain OUTPUT (policy ACCEPT 33467 packets, 5201K bytes)
pkts bytes target prot opt in out source destination
21999 2684K QOS_OUTPUT_eth1 all -- * eth1 0.0.0.0/0 0.0.0.0/0 [goto]

Chain QOS_OUTPUT_eth1 (1 references)
pkts bytes target prot opt in out source destination
21999 2684K MARK all -- * * 0.0.0.0/0 0.0.0.0/0 MARK xset 0xff/0xfffff

对于从内部进程发生到eth1的数据,全部goto到​​QOS_OUTPUT_eth1​​规则,改规则将进来的包都设置成0xff/0xfffff标记。

在tc规则里面,0xff走no qos队列,不做QOS处理。

2.4 FORWARD链关联的target:

FORWARD链属于转发规则,在POSTROUTING之前,所以用来限制设备终端的QOS,设置完了,再走POSTROUTING进行全局的校验。

Chain FORWARD (policy ACCEPT 12502 packets, 1631K bytes)
pkts bytes target prot opt in out source destination
12505 1632K mssfix all -- * * 0.0.0.0/0 0.0.0.0/0
7990 568K QOS_MARK_FORWARD_eth1 all -- * eth1 0.0.0.0/0 0.0.0.0/0 [goto]


如通过LAN口的PC要访问外网的IP,那就是要通过eht1端口转发的数据,所以要走​​QOS_MARK_FORWARD_eth1​​规则。

Chain mssfix (1 references)
pkts bytes target prot opt in out source destination
1896 98680 TCPMSS tcp -- * eth1 0.0.0.0/0 0.0.0.0/0 tcp flags:0x06/0x02 /* wan (mtu_fix) */ TCPMSS clamp to PMTU

Chain QOS_MARK_FORWARD_eth1 (1 references)
pkts bytes target prot opt in out source destination
5123 670K ACCEPT udp -- * * 0.0.0.0/0 0.0.0.0/0 state NEW
2886 152K ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 state NEW
0 0 MARK tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp flags:0x07/0x07 MARK xset 0xff/0xfffff
0 0 ACCEPT all -- * * 0.0.0.0/0 0.0.0.0/0 mark match 0xff/0xfffff
18275 1140K CONNMARK all -- * * 0.0.0.0/0 0.0.0.0/0 CONNMARK restore mask 0xfffff
2972 238K QOS_RULES_FORWARD_eth1 all -- * * 0.0.0.0/0 0.0.0.0/0 mark match 0x0/0xfffff


Chain QOS_RULES_FORWARD_eth1 (1 references)
pkts bytes target prot opt in out source destination
3080 324K MARK all -- * * 0.0.0.0/0 0.0.0.0/0 MAC 14:75:90:F7:97:7D MARK xset 0x101/0xfffff
3177 329K CONNMARK all -- * * 0.0.0.0/0 0.0.0.0/0 CONNMARK save mask 0xfffff

进入​​QOS_MARK_FORWARD_eth1​​规则后,可以看到前面有几个ACCEPT的target,如果target为ACCEPT则说明符合这个要求后,就跳出去,停止对下面规则的执行。

2-iptables mangle 规则_初始化_02

所以这边代表,如果为NEW的状态,即新建立的链接则不需要再匹配qos规则了,会保存在skb数据表里面,然后tc规则去匹配skb数据规则进行对应mark的执行。

下面的对于匹配到SYN的同步信息,则设置了MARK为0xff/0xfffff,下一跳规则就马上匹配到这个规则的时候就ACCEPT,进入到TC队列的时候,进入no qos队列。

再下面就为CONNMARK,其实有点不一样,这个是要经过重定向的,connmark最后save的时候会转换成上面mark的形式,及转成skb数据,再由tc规则去匹配。

所以CONNMARK要有初始化restore,要有保存save,最后redirect成skb。

先将mark restore,然后去匹配​​QOS_RULES_FORWARD_eth1​​​里面的规则,如匹配到mac地址为​​14:75:90:F7:97:7D​​的数据,则set mark为 0x101/0xfffff,然后再save mask,最后在tc里面就可以匹配到该mark去执行对应的限速规则。

2.5 POSTROUTING链关联的target:

POSTROUTING链属于总规则,所以用来限制zqos_rule的条目

Chain POSTROUTING (policy ACCEPT 50234 packets, 7754K bytes)
pkts bytes target prot opt in out source destination
31325 3361K QOS_MARK_eth1 all -- * eth1 0.0.0.0/0 0.0.0.0/0 [goto]


如通过LAN口的PC要访问外网的IP,那就是要通过eht1端口转发后,经过FORWARD,最终还是要走​​POSTROUTING​​​规则,所以都是经过​​QOS_MARK_eth1​​规则。

Chain QOS_MARK_eth1 (1 references)
pkts bytes target prot opt in out source destination
12540 1253K ACCEPT udp -- * * 0.0.0.0/0 0.0.0.0/0 state NEW
5732 323K ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 state NEW
0 0 MARK tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp flags:0x07/0x07 MARK xset 0xff/0xfffff
32810 4403K ACCEPT all -- * * 0.0.0.0/0 0.0.0.0/0 mark match 0xff/0xfffff
18275 1140K CONNMARK all -- * * 0.0.0.0/0 0.0.0.0/0 CONNMARK restore mask 0xfffff
2972 238K QOS_RULES_eth1 all -- * * 0.0.0.0/0 0.0.0.0/0 mark match 0x0/0xfffff


Chain QOS_RULES_eth1 (1 references)
pkts bytes target prot opt in out source destination
0 0 MARK udp -- * * 0.0.0.0/0 0.0.0.0/0 multiport dports 53,67,68 MARK xset 0xff/0xfffff
2690 108K MARK tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp flags:!0x17/0x02 multiport sports 0:65535 multiport dports 0:65535 length 0:100 MARK xset 0x22/0xfffff
11 597 MARK udp -- * * 0.0.0.0/0 0.0.0.0/0 multiport sports 0:65535 multiport dports 0:65535 length 0:100 MARK xset 0x22/0xfffff
2909 233K MARK tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp flags:!0x17/0x02 multiport sports 0:65535 multiport dports 25,80,443 MARK xset 0x33/0xfffff
12 1975 MARK all -- * * 0.0.0.0/0 0.0.0.0/0 mark match 0x0/0xfffff MARK xset 0x44/0xfffff
2972 238K CONNMARK all -- * * 0.0.0.0/0 0.0.0.0/0 CONNMARK save mask 0xfffff


进入​​QOS_MARK_eth1​​​规则后,先将mark restore,然后去匹配​​QOS_RULES_eth1​​​里面的规则,如匹配到mac地址为​​14:75:90:F7:97:7D​​的数据,则set mark为 0x101/0xfffff,然后再save mask,最后在tc里面就可以匹配到该mark去执行对应的限速规则。