使用 iptables、ipset 和 tc 進行流量整形(–match-set 和 –set-mark)
我在我認為應該是一個相當簡單的流量整形問題上遇到了一些麻煩。
我有一個充當路由器/nat 的 Ubuntu (16.04) 伺服器。我想讓大多數使用者使用 2mbps 網際網路,同時將一些設備限制為 512kbps。
我在
ipset
. 我正在嘗試--mark-set
來自這些設備的數據包,以便tc
可以通過流量整形來定位它們。我目前的設置是:
tc qdisc del root dev $LAN tc qdisc add dev $LAN root handle 1: htb default 20 tc class add dev $LAN parent 1: classid 1:1 htb rate 6mbit burst 15k tc class add dev $LAN parent 1:1 classid 1:10 htb rate 5mbit burst 15k tc class add dev $LAN parent 1:1 classid 1:20 htb rate 2mbit ceil 2mbit burst 15k tc class add dev $LAN parent 1:1 classid 1:30 htb rate 512kbit ceil 512kbit burst 15k tc qdisc add dev $LAN parent 1:10 handle 10: sfq perturb 10 tc qdisc add dev $LAN parent 1:20 handle 20: sfq perturb 10 tc qdisc add dev $LAN parent 1:30 handle 30: sfq perturb 10 tc filter add dev $LAN protocol ip parent 1: prio 1 handle 6 fw flowid 1:30 $IPS create throttled hash:mac -exist $IPS add throttled 00:11:22:33:44:55 -exist $IPT -A PREROUTING -t mangle -m set --match-set throttled src,dst -j MARK --set-mark 6
這不會將我的速度降低到 512kbps(假設我的 mac 地址是提供的),它會回落到預設的 2mbps
如果我刪除該
--match-set
部分,它會正確地將所有設備降低到 512kbps(這讓我認為該tc
部分是正確的)但是,如果我
DROP
的數據包與該集合匹配,它會正確丟棄數據包(這讓我認為該iptables
部分是正確的)我在這裡遺漏了什麼,或者這兩個命令不能像這樣一起使用嗎?
非常感謝任何幫助。
謝謝,
希望一年後您已經解決了您的問題,但是為了後續人員的利益,以下是對您的至少 1 個問題的解釋。
根據
ipset
您提供的範例,您的iptables
規則無效。集合類型hash:mac
只儲存一個欄位。但是,您的 iptables 語句正在測試該集合,就好像它包含數據對(即兩個欄位,例如 mac,IP 或 mac,net)。因此,您正在使用數據包的源 MAC 地址和數據包中未定義的目標欄位匹配集合中的條目:ipset create throttled hash:mac -exist ipset add throttled 00:11:22:33:44:55 -exist iptables -A PREROUTING -t mangle -m set --match-set throttled src,dst -j MARK --set-mark 6
但是,由於使用的集合類型,您只能匹配單個欄位。以下 iptables 語句顯示了匹配集合中包含的源 MAC 地址的正確方法:
ipset create throttled hash:mac -exist ipset add throttled 00:11:22:33:44:55 -exist iptables -A PREROUTING -t mangle -m set --match-set throttled src -j MARK --set-mark 6
為了說明這一點,請考慮您是否有一個類型為
hash:net,port,net
on a firewall 的集合。該集合將儲存三元組(兩個網路和一個埠)。假設防火牆具有以下 ipset 條目和 iptables 規則:
# creates set ipset create throttled hash:net,port,net ipset add services 192.168.0.0/16,tcp:80,192.168.1.80/32 ipset add services 192.168.0.0/16,tcp:443,192.168.1.80/32 # clear all rules (to illustrate that conntrack is not being used) iptables -F FORWARD # allows traffic to web server iptables -A FORWARD -m set --match-set services src,dst,dst -j ACCEPT # allows traffic from web server iptables -A FORWARD -m set --match-set services dst,src,src -j ACCEPT # drop all other traffic iptables -P DROP
上述規則在功能上等價於:
# clear all rules (to illustrate that conntrack is not being used) iptables -F FORWARD # allows traffic to web server iptables -A FORWARD -s 192.168.0.0/16 -p tcp --dport 80 -d 192.168.1.80/32 -j ACCEPT iptables -A FORWARD -s 192.168.0.0/16 -p tcp --dport 443 -d 192.168.1.80/32 -j ACCEPT # allows traffic from web server iptables -A FORWARD -d 192.168.0.0/16 -p tcp --sport 80 -s 192.168.1.80/32 -j ACCEPT iptables -A FORWARD -d 192.168.0.0/16 -p tcp --sport 443 -s 192.168.1.80/32 -j ACCEPT # drop all other traffic iptables -P DROP
儘管上述兩種方法在功能上是等效的,但由於使用雜湊表查找而不是 iptables 規則的線性評估,ipset 方法在處理大量條目時會表現得更好。
使用集合時,集合類型指示使用了多少匹配欄位。iptables 語句指定數據包的源或目標欄位是否用於匹配集合的每個欄位。
以下是一些映射來說明:
ipset type | iptables match-set | Packet fields ------------------+--------------------+--------------------------------- hash:net,port,net | src,dst,dst | src IP address, dst port, dst IP address hash:net,port,net | dst,src,src | dst IP address, src port, src IP address hash:ip,port,ip | src,dst,dst | src IP address, dst port, dst IP address hash:ip,port,ip | dst,src,src | dst IP address, src port, src ip address hash:mac | src | src mac address hash:mac | dst | dst mac address hash:ip,mac | src,src | src IP address, src mac address hash:ip,mac | dst,dst | dst IP address, dst mac address hash:ip,mac | dst,src | dst IP address, src mac address
您可能在 TC/iptables 互動中遇到其他問題,但這至少應該解決您的 ipset/iptables 問題。