QOS的整個流程是:根據各種條件,如IP地址,數據包大小,上行,下行,這個信息在iptables裏面都可以捕獲到。然在iptables根據這些規則設置對應的mark,設置完mark,tc規則規則裏面根據不同的mark執行不同的內容,如隊列分配,限制帶寬,流量分配算法。
0 數據流向
- -i 指定數據包進入 PREROUTING、INPUT、FORWARD鏈時經由的接口。
- -o 指定數據包出去 FORWARD、OUTPUT、POSTROUTING鏈時經由的接口。
當我們開啓防火牆功能後,報文需要經過的路徑是有區別的,如下圖所示:
報文的流向:
- 到本機某進程的報文: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則說明符合這個要求後,就跳出去,停止對下面規則的執行。
所以這邊代表,如果爲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去執行對應的限速規則。