關於 iptables 和 tc 的限速理解

關於 iptables

iptables 是包過濾軟件,包過濾的順序以下:php

鳥哥的iptables圖

每個包都會匹配 rule 策略,而每個 rule 策略會有一個 action,觸發了其中一個 rule 就不會觸發另一個 rule,但若是要觸發的 rule 放在最後面,那麼能夠想象,包過濾的效率就會大大下降,因此設計策略的時候要儘可能將經常使用的策略放在最前面,策略的順序能夠經過不斷的調整 -A 和 -I 策略,甚至還有 return 的動做,設計 iptables 的人真的很厲害。html

這是 iptables 內部的 table 表和 chain 鏈,能夠理解爲 iptables 是一個大網,table 就是小網,裏面的 chain 就是他的網線,當數據包通過這個小網的時候必然會觸碰這些網線,這樣「看不順眼」的數據包就會被攔住。鳥哥的圖畫的真好。這裏須要理解的是數據包的流行會分 2 個地方,就是進入本機或者不進入本機,進入本機的包就會走 input 的 chain 鏈,不進入本機的包就會去 FORWARD,什麼是進入或者不進入呢?linux

舉個例子就是這是一臺路由器服務器,服務器上面假設了 web 服務器,而後這個路由器負責的內部網絡還有一臺數據庫服務器,不過這臺服務器是獨立於路由器的另一臺機器,不過上網也是要通過路由器,那麼一個外網用戶訪問這個 web 服務器和訪問數據庫服務器的行爲就是進入本機和不進入本機的行爲,由於 web 服務器是跟路由器在同一臺機器上的,因此要進入本機,由於數據庫服務器是另一臺機器上的,因此不進入本機。解釋得好渣,仍是看鳥哥吧。鳥哥乃神人。迴歸主題,看下圖的結構,能夠看出若是咱們要在 iptables 上操刀的話能夠在任何表上操刀,例如能夠在 PREROUTING,FORWARD,POSTROUTING 表上作限速是徹底沒有問題的,前提是要注意不能衝突,每一個表都有各自的做用。因此通常來講,要寫 iptables 策略的時候都要跟着這個圖來筆畫一下,這樣才能知道有沒有寫錯。web

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,INPUTFORWARD。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.less

這裏是官方翻譯: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

用於爲隊列建一個主幹類,帶寬爲 100 Mbit,最大速率爲 100 Mbit,(這裏是 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,最大速爲 10 Mbit,優先級爲1,全部葉分類的所有子類優先級低於主幹類,以防止重要數據堵塞,主要仍是避免邏輯混亂,10 Mbit 必需要有 96 kbit 的 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/

相關文章
相關標籤/搜索