? ? ? ?
目錄
簡單概述:
qdisc(隊列):
? 舉例:
??Bash????????
整形隊列算法:
FIFO (First-In-First-Out)
PFIFO (Priority FIFO)
SFQ (Stochastic Fair Queuing)
RED (Random Early Detection)
HTB (Hierarchical Token Bucket)
TBF (Token Bucket Filter)
NETEM (Network Emulator)
CBQ (Class-based Queueing)
整形隊列流量方向管理:
Class(類) 和 Filter(過濾器):
創建?class
使用?class?和?filter
問題:
帶寬或者流速單位:
問題解決方法:
限制IP為1.1.1.3上傳速度實例:
? 創建虛擬網卡并啟用,暫定虛擬網卡名為ifb0
? 創建Ingress隊列并進行導流
? ?對ifb0進行限速即可
限制IP為1.1.1.3下載速度實例:
u32匹配:
u32匹配器的特點
?限速總結:? ?
目前需要做一款關于Linux下對于某IP限制的一個工具(QOS),在網上尋找了許多關于TC的教程,大多數都是一些比較基礎的教學,且多數都是對網口的一些限制,然后自己研究了一段時間,最后有一些小小的了解,故在此分享給大家。
首先我們可以先假設把TCP包的架構設成這樣,方便我們后續去了解限速的規則。這里一定要記好了。
[source-ip] | [source-port] | [other-data] | [destination-ip] | [destination-port]
簡單概述:
TC,即 Traffic Control,是 Linux 內核提供的一種用于網絡流量管理和質量服務(Quality of Service, QoS)的工具。它允許網絡管理員對網絡接口上的數據包進行精細的控制,包括但不限于:
-
SHAPING(限制)
- 當流量被限制時,其傳輸速率被控制在預設的閾值之下。這種限制可以顯著減少突發流量,有助于維持網絡的穩定性和預測性。SHAPING 主要應用于向外的流量控制。
-
SCHEDULING(調度)
- 調度涉及在可用帶寬范圍內,按優先級分配帶寬資源。這確保了關鍵應用和服務可以得到優先處理,從而提高了網絡的整體效率。SCHEDULING 同樣適用于向外的流量。
-
POLICING(策略)
- POLICING 通常用于控制入站流量,當檢測到流量超出預設規則時,可以采取行動,如丟棄超額的數據包,以維持網絡政策的一致性。
-
DROPPING(丟棄)
- 當流量超出設定的帶寬限制時,DROPPING 策略將直接丟棄過量的數據包。這一策略適用于入站和出站流量。
tc
命令的基本結構如下:
Bash
1tc [ OPTIONS ] COMMAND [ @id ] dev DEV [ parent qdisc-id ] [ index INDEX ]
其中 COMMAND
可以是 qdisc
, filter
, class
, action
等不同的子命令,用于執行不同的流量控制任務。
-
qdisc(排隊規則)
- qdisc 定義了數據包在接口上排隊和調度的策略。它決定了數據包如何被存儲和發送,是流量控制的核心機制。qdisc 可分為 CLASSLESS QDISC 和 CLASSFUL QDISC。
-
CLASSLESS QDISC
- 包括簡單的 FIFO(First-In-First-Out)隊列,如 pfifo 和 bfifo,以及更復雜的策略如 pfifo_fast、red、sfq 和 tbf。
- pfifo/bfifo:簡單的 FIFO 隊列,前者基于數據包計數,后者基于字節數。
- pfifo_fast:在高級路由器配置中作為默認 qdisc,具有三個優先級隊列。
- red:隨機早期檢測,用于預防擁塞。
- sfq:基于概率的公平隊列,適用于多流場景。
- tbf:令牌桶過濾器,用于限速和整形。
- 包括簡單的 FIFO(First-In-First-Out)隊列,如 pfifo 和 bfifo,以及更復雜的策略如 pfifo_fast、red、sfq 和 tbf。
-
CLASSFUL QDISC
- 提供更細粒度的控制,允許創建基于類別的隊列,如 HTB 和 CBQ,用于復雜的服務質量策略。
-
class(類別)
- 類別用于組織和劃分流量,允許為不同類型的流量分配特定的帶寬和優先級。
-
filter(過濾器)
- 過濾器用于識別和分類數據包,基于 IP 地址、端口、協議等屬性,將數據包導向特定的 qdisc 或 class。
qdisc(隊列):
- 帶寬分配:限制或保證數據流的帶寬。
- 延遲控制:通過緩存機制控制數據包的發送時間,從而影響網絡延遲。
- 丟包策略:當隊列滿時決定哪些數據包被丟棄的策略,以防止擁塞。
- 公平性:確保多個數據流之間的公平帶寬分配。
? 舉例:
??Bash????????
tc qdisc add dev ens18 handle fff: htb default 22
? ?其中fff:就相當于這條隊列的特定標識符,也相當于唯一ID。
? ? ? ? 談到隊列大家可能有些熟悉,是數據結構中的隊列嗎?先進先出的那個?當然不是,這是由Linux做的一款流量整形隊列,你可以把它看作一條支流,對,小溪那種。
? ? ? ? ?在我們正常使用的情況下,其實LInux就已經給我們的網卡分配了一些隊列,應該也是用來整形穩定的一種。當我們對網口設置了一個新的隊列后,這個隊列就會被我的這個隊列給頂替下去。
? ? ? ? ?
整形隊列算法:
FIFO (First-In-First-Out)
這是最簡單的隊列紀律類型,沒有額外的管理機制。數據包按照它們到達的順序被發送出去。FIFO 不做任何排序或優先級處理,因此所有數據流都被平等對待。這在大多數情況下是默認的行為,但如果網絡負載很高,可能會導致一些數據包的延遲或丟失。
PFIFO (Priority FIFO)
PFIFO 提供了有限數量的優先級隊列,通常為三個:高、中、低。這允許網絡管理員根據數據包的類型或來源為其分配不同的優先級,從而確保關鍵數據包(如語音或視頻流)得到優先處理。然而,PFIFO 仍然依賴于簡單的先進先出原則,只是在不同的優先級隊列中。
SFQ (Stochastic Fair Queuing)
SFQ 是一種更復雜的隊列管理算法,旨在為每個數據流提供公平的帶寬分配,即使在高負載情況下也能保持良好的響應時間。它使用基于概率的算法來分類數據包,然后將它們放入不同的隊列中,確保即使小流量的數據流也能獲得一定的帶寬。
RED (Random Early Detection)
RED 是一種主動丟包機制,用于預防網絡擁塞。當隊列接近其最大容量時,RED 開始隨機丟棄一些數據包,而不是等到隊列完全填滿。這種提前丟棄數據包的策略有助于平滑網絡流量,減少擁塞的發生,從而改善整體網絡性能。
HTB (Hierarchical Token Bucket)
HTB 是一種非常靈活的隊列紀律,支持復雜的帶寬分配和優先級管理。它可以創建層次化的令牌桶,允許網絡管理員為不同的數據流設定具體的帶寬限制和優先級。HTB 特別適用于需要精細控制網絡資源分配的場景,如企業網絡和數據中心。
TBF (Token Bucket Filter)
TBF 是基于令牌桶算法的流量整形工具,主要用于限速和流量整形。它允許指定一個固定的帶寬速率,確保數據流不會超過這個速率,這對于避免網絡擁塞和保證服務質量非常有用。
NETEM (Network Emulator)
NETEM 是一個網絡仿真工具,用于模擬各種網絡狀況,如延遲、丟包和重復。它非常適合在開發和測試環境中模擬真實世界的網絡條件,幫助驗證應用程序在網絡問題下的表現。
CBQ (Class-based Queueing)
CBQ 是早期版本中常用的隊列紀律,類似于 HTB,但功能較少且配置更為復雜。它也支持基于類的隊列,允許為不同的數據流設置不同的優先級和帶寬限制。然而,由于 HTB 的出現,CBQ 在現代系統中的使用已大大減少。
上方這些算法中,如果你想進行一些簡單的流量控制,那么FIFO和PFIFO即可,如果想要進行真正管理級,邏輯稍微復雜一些的流量整控我推薦用HTB,關于HTB它可以進行優先級限制,src和dst IP限制,是一個功能非常強大的算法。SFQ的話是當你建立了多條類的話,用于流量平分用。比如果你從隊列里面開出了三條類,也可以理解為引出來了三條小溪流,害怕每條小溪流的水不一樣多怎么辦?這時候就給每條小溪都設上一個SFQ。
wondershaper源碼為例:
這里其他算法就不過多贅述了,專于對HTB算法進行詳細講解。
整形隊列流量方向管理:
-
Ingress:表示數據包進入網絡設備的方向。當數據包從網絡接口接收進來時,這個過程被稱為 ingress。在這個階段,設備可以執行諸如數據包過濾、流量整形、優先級標記等操作。
-
Egress:表示數據包離開網絡設備的方向。當數據包被發送到另一個網絡或設備時,這個過程被稱為 egress。在 egress 方向,設備也可能執行類似的操作,如基于策略的路由、QoS 保障、流量限速等。
在 Linux 的 Traffic Control (tc
) 工具中,ingress 和 egress 通常用來描述數據包在網卡或網絡設備上的流動方向。例如,當使用 tc
進行流量控制時,你可以分別對 ingress 和 egress 方向的流量應用不同的隊列紀律和過濾規則。這點其實是非常重要的,因為TC實際上是管發不管收的。也就是如果我們通過TC只能限制別人對我們的下載速度,沒辦法限制別人對我們的上傳速度。
這個東西在前期確實讓人很頭痛,那豈不是我們沒有辦法在自己的機器上對別人進行上傳限速?當然不是,Ingress和Egress就可以解決這個問題。這個在后續應用實例的時候去講。
Class(類) 和 Filter(過濾器):
class
在 tc
中扮演了組織者和控制器的角色。它允許你創建多個類別,每個類別都可以有自己的帶寬限制、優先級和調度策略。通過將數據包分配到不同的 class
中,你可以實現以下目標:
- 帶寬分配:為每個?
class
?設置不同的帶寬上限,確保每個數據流都得到公平或預定的帶寬份額。 - 優先級控制:為關鍵數據流分配更高的優先級,確保它們在擁塞時仍能快速傳輸。
- QoS 改善:通過精細調整?
class
?參數,改善整個網絡的服務質量,特別是對于實時應用如 VoIP 和視頻會議。
創建?class
class
的創建和配置通常與 qdisc
相結合。首先,你需要在根 qdisc
下創建一個父 class
,然后可以創建子 class
來進一步細分流量。例如,使用 htb
(Hierarchical Token Bucket)作為 qdisc
時,你可以這樣創建一個 class
:
Bash
# 創建父 qdisc
tc qdisc add dev <interface> root handle 1: htb default 11# 創建父 class
tc class add dev <interface> parent 1: classid 1:1 htb rate <rate># 創建子 class
tc class add dev <interface> parent 1:1 classid 1:11 htb rate <rate> ceil <max_rate>
在上述命令中,<interface>
是你想要控制的網絡接口,<rate>
是你想要分配給該 class
的帶寬速率,<max_rate>
是該 class
可以使用的最大帶寬。
使用?class
?和?filter
為了將特定的數據包分配到正確的 class
,你需要使用 filter
。filter
根據數據包的屬性(如源/目的IP、端口號、協議類型等)將它們導向特定的 class
。例如:
Bash
tc filter add dev <interface> protocol ip parent 1:0 prio 1 u32 match ip dst <destination_ip>/32 flowid 1:11
此命令創建了一個 filter
,將目的地為 <destination_ip>
的所有 IP 數據包導向 class
1:11
。
問題:
此時以文章最開始的包結構為例,這里的destination_ip就是我們包結構里面的?
[destination-ip]。假如由1.1.1.2給1.1.1.3發消息,那我們在1.1.1.3中收到的這個包的目標IP就是1.1.1.3,所以此時我們如果對1.1.1.3進行限速也就是對1.1.1.3進行限速。那如果我直接這個包的SRC進行限速呢?這不就完成了對客戶端上傳速度的限制?但是大家別忘了,TC是一個管發不管收的工具,既然不管收,那怎么對客戶端進行限速呢?
帶寬或者流速單位:
問題解決方法:
? ? 我們可以去將Ingress的流量進行一個導流,然后把導流的流量重定向到一個網卡上,為了穩定這個采用一個虛擬網卡,然后對虛擬網卡上的流量進行限速,就可以解決對收包進行限速了。
限制IP為1.1.1.3上傳速度實例:
? 創建虛擬網卡并啟用,暫定虛擬網卡名為ifb0
? Bash
modprobe ifb numifbs=1;
ip link set dev ifb0 up;
? 創建Ingress隊列并進行導流
? ?Bash
tc qdisc add dev ens18 handle ffff: ingress
tc filter add dev ens18 parent ffff: protocol ip u32 match u32 0 0 action mirred egress redirect dev ifb0;
? ?對ifb0進行限速即可
tc qdisc add dev ifb0 root handle 2: htb default 22;
tc class add dev ifb0 parent 2: classid 2:22 htb rate 10000mbit ceil 10000mbit burst 10000mbit cburst 10000mbit;
tc class add dev ifb0 parent 2: classid 2:1 htb rate 10mbit ceil 10mbit burst 10mbit cburst 10mbit ;tc filter add dev ifb0 protocol ip parent 2: prio 1 u32 match ip src 1.1.1.3 flowid 2:1;
如果想要限制其他的IP將IP改一下即可。
限制IP為1.1.1.3下載速度實例:
正常創建Htb隊列,default 22 就是如果沒有合適的filter去匹配的話,那就就去找classid為22的類去限速。
tc qdisc add dev ens18 root handle 1:0 htb default 22
創建限速類,這里22限制為10GB每秒,相當于未限速,然后對1.1.1.3限速為10mbit每秒。
tc class add dev ens18 parent 1:0 classid 1:1 htb rate 10mbit ceil 10mbittc class add dev ens18 parent 1:0 classid 1:22 htb rate 10000mbit ceil 10000mbit# dst->src
tc filter add dev ens18 parent 1:0 protocol ip prio 1 u32 match ip dst 1.1.1.3 flowid 1:1
u32匹配:
在Linux的tc
(Traffic Control)工具中,u32
是一種匹配器類型,用于基于數據包頭部的信息來過濾和分類網絡流量。u32
匹配器非常靈活,可以依據各種字段(如IP地址、端口號、協議類型等)來創建復雜的匹配規則,是實現高級流量控制策略的關鍵組件。
u32
匹配器的特點
-
靈活性:
u32
匹配器可以基于多種數據包頭部字段進行匹配,包括但不限于IP源地址、目的地址、TCP/UDP源端口、目的端口、協議類型等。 -
復雜規則支持:
u32
支持邏輯運算,如AND、OR、NOT,允許創建復合的匹配規則,以適應復雜的網絡策略需求。 -
性能高效:
u32
匹配器設計得非常高效,能夠快速處理大量的數據包,即使在高負載的網絡環境下也能保持良好的性能
-
基于IP地址匹配
-
源IP地址匹配:
Bashsudo tc filter add dev [interface] protocol ip parent 1:0 prio 1 u32 match ip src [source_ip] flowid 1:1
-
目的IP地址匹配:
Bashsudo tc filter add dev [interface] protocol ip parent 1:0 prio 1 u32 match ip dst [destination_ip] flowid 1:1
-
-
基于端口號匹配
-
TCP源端口號匹配:
Bashsudo tc filter add dev [interface] protocol tcp parent 1:0 prio 1 u32 match tcp sport [source_port] flowid 1:1
-
TCP目的端口號匹配:
Bashsudo tc filter add dev [interface] protocol tcp parent 1:0 prio 1 u32 match tcp dport [destination_port] flowid 1:1
-
UDP源端口號匹配:
Bashsudo tc filter add dev [interface] protocol udp parent 1:0 prio 1 u32 match udp sport [source_port] flowid 1:1
-
UDP目的端口號匹配:
Bashsudo tc filter add dev [interface] protocol udp parent 1:0 prio 1 u32 match udp dport [destination_port] flowid 1:1
-
-
基于協議類型匹配
-
匹配TCP協議:
Bashsudo tc filter add dev [interface] protocol tcp parent 1:0 prio 1 u32 flowid 1:1
-
匹配UDP協議:
Bashsudo tc filter add dev [interface] protocol udp parent 1:0 prio 1 u32 flowid 1:1
-
匹配ICMP協議:
Bashsudo tc filter add dev [interface] protocol icmp parent 1:0 prio 1 u32 flowid 1:1
-
?限速總結:? ?
? ? ?對于上傳和下載下載的規律是不變的,后續filter跟的一些匹配協議就由大家自由發揮了,例如端口,源端口,協議類型等一些東西都是非常多的,在此我也不一一列舉了,由大家自由發揮。