linux控制流量控制
1. linux系統中如何限制網路流量
限制網路流量速率的一種方法是通過一個名為trickle的命令行工具。通過在程序運行時,預先載入一個速率限制 socket 庫 的方法,trickle 命令允許你改變任意一個特定程序的流量。 trickle 命令有一個很好的特性是它僅在用戶空間中運行,這意味著,你不必需要 root 許可權就可以限制一個程序的帶寬使用。要能使用 trickle 程序控製程序的帶寬,這個程序就必須使用非靜態鏈接庫的套接字介面。
將你的 scp 會話的最大上傳帶寬設定為 100 KB/s:
$ trickle -u 100 scp backup.tgz alice@remote_host.com:
另一種控制你的帶寬資源的方式是在每一個介面上限制帶寬。這在你與其他人分享你的網路連接的上行帶寬時尤為實用。同其他一樣,Linux 有一個工具來為你做這件事。wondershaper就是干這個的。
wondershaper 實際上是一個 shell 腳本,它使用 tc 來定義流量調整命令,使用 QoS 來處理特定的網路介面。外發流量通過放在不同優先順序的隊列中,達到限制傳出流量速率的目的;而傳入流量通過丟包的方式來達到速率限制的目的。
舉個例子, 將 eth0 的最大下載/上傳帶寬分別設定為 1000Kbit/s 和 500Kbit/s:
$ sudo wondershaper <interface> <download-rate> <upload-rate>
2. 如何在Linux上按國別阻止網路流量
作為一名維護生產環境Linux伺服器的系統管理員,在有些情況下,你需要根據地理位置,有選擇性地阻止或允許網路流量。比如說,你遇到了拒絕服務攻擊,這些攻擊主要源自在某一個國家注冊的IP地址。在其他情況下,出於安全方面的原因,你又想要阻止外國來歷不明SSH登錄請求;或者貴公司對在線視頻擁有發行權,因而只可以分發給某些國家;或者由於地域限制方面的公司政策,你需要防止本地主機將文檔上傳到非美國遠程雲存儲系統。
所有這些場景都需要能夠安裝一個防火牆,可以按國別對流量進行過濾。有幾種方法可以做到這一點。舉例說,你可以使用TCP包裝器(TCP wrapper),針對個別應用程序(比如SSH、NFS和httpd)設置有條件的阻止。其缺點是,你想要保護的那個應用程序在開發當初必須支持TCP包裝器。此外,TCP包裝器並非普遍出現在不同的平台上(比如說,Arch Linux已停止對TCP包裝器的支持)。另一種辦法就是,利用基於國家的GeoIP信息來設置ipset,然後將它運用於iptables規則。後一種方法更有希望,因為基於iptables的過濾與應用程序無關,而且易於設置。
我在本教程中將介紹另一種基於iptables的GeoIP過濾機制,這種機制實施了xtables-addons。有些讀者對它還不熟悉,所以有必要先介紹一下,xtables-addons是一套面向netfilter/iptables的擴展。xtables-addons內含了一個名為xt_geoip的模塊,該模塊擴展了netfilter/iptables的功能,可以根據來源/目的地國家,過濾、NAT或管理數據包。如果你想使用xt_geoip,不需要重新編譯內核或iptables,只需要構建xtables-addons模塊,並使用當前的內核構建環境(/lib/moles/`uname -r`/build)。也不需要重啟。一旦你構建並安裝好了xtables-addons,xt_geoip立即就可以與iptables結合使用。
至於xt_geoip和ipset之間的區別,官方來源(http://xtables-addons.sourceforge.net/geoip.php)提到,xt_geoip在內存佔用空間方面少於ipset。不過在匹配速度方面,基於散列的ipset可能具有優勢。
在本教程其餘部分,我會演示如何使用iptables/xt_geoip,根據來源/目的地國家,阻止網路流量。
將Xtables-addons安裝到Linux上
下面介紹如何編譯xtables-addons,並將它安裝到不同的Linux平台上。
想構建xtables-addons,你就需要先安裝幾個依賴程序包。
·將依賴程序包安裝到Debian、Ubuntu或Linux Mint上
$ sudo apt-get install iptables-dev xtables-addons-common libtext-csv-xs-perl pkg-config
·將依賴程序包安裝到CentOS、RHEL或Fedora上
CentOS/RHEL 6需要先安裝EPEL軟體庫(面向perl-Text-CSV_XS)。
$ sudo yum install gcc-c++ make automake kernel-devel-`uname -r` wget unzip iptables-devel perl-Text-CSV_XS
編譯和安裝Xtables-addons
從官方網站(http://xtables-addons.sourceforge.net)下載最新的xtables-addons源代碼,然後構建/安裝它,如下所示。
$wget http://downloads.sourceforge.net/project/xtables-addons/Xtables-addons/xtables-addons
-2.10.tar.xz
$ tar xf xtables-addons-2.10.tar.xz
$ cd xtables-addons-2.10
$ ./configure
$ make
$ sudo make install
請注意:如果是默認情況下已啟用SELinux的基於紅帽的系統(CentOS、RHEL、Fedora),有必要調整SELinux策略,如下所示。要不然,SELinux會阻止iptables裝入xt_geoip模塊。
$ sudo chcon -vR --user=system_u /lib/moles/$(uname -r)/extra/*.ko
$ sudo chcon -vR --type=lib_t /lib64/xtables/*.so
為Xtables-addons安裝GeoIP資料庫
下一步是安裝GeoIP資料庫,xt_geoip將用到該資料庫,用於IP與國別映射。很方便的是,xtables-addons源程序包隨帶兩個幫助腳本,可分別用來從MaxMind下載GeoIP資料庫,並將它轉換成xt_geoip可識別的二進制格式。這些腳本位於源程序包裡面的geoip文件夾下面。按照下列說明,即可構建GeoIP資料庫,並將它安裝到你系統上。
$ cd geoip
$ ./xt_geoip_dl
$ ./xt_geoip_build GeoIPCountryWhois.csv
$ sudo mkdir -p /usr/share/xt_geoip
$ sudo cp -r {BE,LE} /usr/share/xt_geoip
據MaxMind聲稱,其GeoIP資料庫的准確性達到99.8%,資料庫更每月都更新。為了確保本地安裝的GeoIP資料庫內容最新,你就需要設置每月執行的計劃任務,以便每月更新一次本地GeoIP資料庫。
阻止來自或發往某個國家的網路流量
一旦xt_geoip模塊和GeoIP資料庫都已安裝好,你就可以立即使用iptables命令中的geoip匹配選項。
$ sudo iptables -m geoip --src-cc country[,country...] --dst-cc country[,country...]
你想要阻止的國家使用兩個字母ISO3166代碼來指定,比如說US(美國)、CN(中國)、IN(印度)和FR(法國)。
比如說,如果你想阻止來自葉門(YE)和尚比亞(ZM)的入站流量,下面這個iptables命令就能實現。
$ sudo iptables -I INPUT -m geoip --src-cc YE,ZM -j DROP
如果你想阻止發往中國(CN)的出站流量,只要運行下面這個命令。
$ sudo iptables -A OUTPUT -m geoip --dst-cc CN -j DROP
匹配條件也可以被「抵消」,只要將「!」放在「--src-cc」或「--dst-cc」的前面。比如說:
如果你想在伺服器上阻止所有非美國的入站流量,可以運行這個命令:
$ sudo iptables -I INPUT -m geoip ! --src-cc US -j DROP
針對Firewall-cmd用戶
像CentOS/RHEL 7或Fedora這一些發行版已將iptables換成firewalld,作為默認防火牆伺服器。在這類系統上,你同樣可以利用xt_geoip,使用firewall-cmd阻止流量。上面三個例子可以用firewall-cmd來改寫,如下所示。
$ sudo firewall-cmd --direct --add-rule ipv4 filter INPUT 0 -m geoip --src-cc YE,ZM -j DROP
$ sudo firewall-cmd --direct --add-rule ipv4 filter OUTPUT 0 -m geoip --dst-cc CN -j DROP
$ sudo firewall-cmd --direct --add-rule ipv4 filter INPUT 0 -m geoip ! --src-cc US -j DROP
結束語
我在本教程中介紹了iptables/xt_geoip,這是一種簡單方法,可以根據來源/目的地國家,對網路數據包進行過濾。如果需要的話,可以將這件有用的武器部署到你的防火牆系統中。最後提醒一句,我應該提到:基於GeoIP的流量過濾並不是在你伺服器上阻止某些國家的萬無一失的方法。GeoIP資料庫天生就不準確/不完整,如果使用VPN、Tor或任何受到危及的中繼主機,就很容易欺騙來源/目的地國家。基於地域的過濾甚至會阻止本不該被禁止的合法流量。明白這個局限性後,再決定將它部署到你的生產環境中也不遲。
3. TC - Linux 流量控制工具
參考: TC - Linux 流量控制工具 | Life is magic. Coding is art. (int64.me)
TC(Linux下流量控制工具)詳細說明及應用_Gino的專欄-CSDN博客
本來打算直接列一波用法,但是總覺得,不記錄一下原理,操作起來也是一臉懵逼。 TC 通過建立處理數據包隊列,並定義隊列中數據包被發送的方式,從而實現進行流量控制。TC 模擬實現流量控制功能使用的隊列分為兩類:
classful 隊列規定(qdisc), 類(class)和過濾器(filter)這 3 個組件組成,繪圖中一般用圓形表示隊列規定,用矩形表示類,圖 自 Linux 下 TC 以及 netem 隊列的使用
都是以一個根 qdisc 開始的,若根 qdisc 是不分類的隊列規定,那它就沒有子類,因此不可能包含其他的子對象,也不會有過濾器與之關聯,發送數據時,數據包進入這個隊列裡面排隊,然後根據該隊列規定的處理方式將數據包發送出去。
分類的 qdisc 內部包含一個或多個類,而每個類可以包含一個隊列規定或者包含若干個子類,這些子類友可以包含分類或者不分類的隊列規定,如此遞歸,形成了一個樹。
句柄號:qdisc 和類都使用一個句柄進行標識,且在一棵樹中必須是唯一的,每個句柄由主號碼和次號碼組成 qdisc 的次號碼必須為 0(0 通常可以省略不寫)
根 qdisc 的句柄為 1:,也就是 1:0。類的句柄的主號碼與它的父輩相同(父類或者父 qdisc),如類 1:1 的主號碼與包含他的隊列規定 1:的主號碼相同,1:10 和 1:11 與他們的父類 1:1 的主號碼相同,也為 1。
新建一個類時,默認帶有一個 pfifo_fast 類型的不分類隊列規定,當添加一個子類時,這個類型的 qdisc 就會被刪除,所以,非葉子類是沒有隊列規定的,數據包最後只能到葉子類的隊列規定裡面排隊。
若一個類有子類,那麼允許這些子類競爭父類的帶寬,但是,以隊列規定為父輩的類之間是不允許相互競爭帶寬的。
默認 TC 的 qdisc 控制就是出口流量,要使用 TC 控制入口,需要把流量重定向到 ifb 網卡,其實就是加了一層,原理上還是控制出口 。
為何要先說 classless 隊列,畢竟這個簡單嘛,要快速使用,那麼這個就是首選了。基於 classless 隊列,我們可以進行故障模擬,也可以用來限制帶寬。
TC 使用 linux network netem 模塊進行網路故障模擬
網路傳輸並不能保證順序,傳輸層 TCP 會對報文進行重組保證順序,所以報文亂序對應用的影響比上面的幾種問題要小。
報文亂序可前面的參數不太一樣,因為上面的報文問題都是獨立的,針對單個報文做操作就行,而亂序則牽涉到多個報文的重組。模擬報亂序一定會用到延遲(因為模擬亂序的本質就是把一些包延遲發送),netem 有兩種方法可以做。
以 tbf (Token Bucket Filter) 為例,
參數說明:
限制 100mbit
限制延遲 100ms, 流量 100mbit
這個就復雜一些,同樣也特別靈活,可以限制特定的 ip 或者服務類型以及埠
以使用 htb 為例
使用 TC 進行入口限流,需要把流量重定向到 ifb 虛擬網卡,然後在控制 ifb 的輸出流量
4. linux伺服器要怎樣針對IP流量限制
不是木馬,是設置問題,下面是流量的控制方法一、Linux流量控制過程分二種:1、隊列控制即QOS,瓶頸處的發送隊列的規則控制,常見的有SFQPRIO2、流量控制即帶寬控制,隊列的排隊整形,一般為TBFHTB二、Linux流量控制演算法分二種:1、無類演算法用於樹葉級無分支的隊列,例如:SFQ2、分類演算法用於多分支的隊列,例如:PRIOTBFHTB三、具體實現:1.在網卡上建立以SFQ演算法的限流#tcqdiscadddeveth0roothandle1:sfqSFQ參數有perturb(重新調整演算法間隔)quantum基本上不需要手工調整:handle1:規定演算法編號..可以不用設置由系統指定..#tcqdiscshdeveth0顯示演算法#tcqddeldeveth0root刪除注:默認eht0支持TOS2.在網卡建立以TBF演算法的限流#tcqdadddeveth1roothandle1:速率256kbit突發傳輸10k最大延遲50ms#tc-sqdshdeveth1統計#tcqddeldeveth1root刪除3.在網卡建立PRIO#tcqdiscadddeveth0roothandle1:prio#此命令立即創建了類:1:1,1:2,1:3(預設三個子類)#tcqdiscadddeveth0parent1:1handle10:sfq#tcqdiscadddeveth0parent1:2handle20:注:此為TBF限速的另一寫法,前文有講解.#tcqdiscadddeveth0parent1:3handle30:sfq4.WEB伺服器的流量控制為5Mbps,SMTP流量控制在3Mbps上.而且二者一共不得超過6Mbps,互相之間允許借用帶寬#tcqdiscadddeveth0roothandle1:#tcclassadddeveth0parent1:0classid1:.這部分按慣例設置了根為1:0,並且綁定了類1:1.也就是說整個帶寬不能超過6Mbps.#tcclassadddeveth0parent1:1classid1:.#tcclassadddeveth0parent1:1classid1:.建立了2個類.注意我們如何根據帶寬來調整weight參數的.兩個類都沒有配置成"bounded",但它們都連接到了類1:1上,而1:1設置了"bounded".所以兩個類的總帶寬不會超過6Mbps.別忘了,同一個CBQ下面的子類的主號碼都必須與CBQ自己的號碼相一致!#tcqdiscadddeveth0parent1:3handle30:sfq#tcqdiscadddeveth0parent1:4handle40:sfq預設情況下,兩個類都有一個FIFO隊列規定.但是我們把它換成SFQ隊列,以保證每個數據流都公平對待.#tcfilteradddeveth0parent1::3#tcfilteradddeveth0parent1::46.過濾器過濾示例#::1在10:節點添加一個過濾規則,優先權1:凡是去往22口(精確匹配)的IP數據包,發送到頻道10:1..#::1在10:節點添加一個過濾規則,優先權1:凡是來自80口(精確匹配)的IP數據包,發送到頻道10:1..#:prio2flowid10:2在eth0上的10:節點添加一個過濾規則,它的優先權是2:凡是上二句未匹配的IP數據包,發送到頻道10:2..#tcfilteradddeveth0parent10:.3.2.1/32flowid10:1去往4.3.2.1的包發送到頻道10:1其它參數同上例#tcfilteradddeveth0parent10:.2.3.4/32flowid10:1來自1.2.3.4的包發到頻道10:1#:prio2flowid10:2凡上二句未匹配的包送往10:2#tcfilteradddeveth0parent10:.3.2.1/:1可連續使用match,匹配來自1.2.3.4的80口的數據包
5. linux中如何控制埠流量
配置網卡
建立一台虛擬機,並安裝完成後以橋接的方式在虛擬機上面添加兩張網卡。分別為eth0和eth1。
eth0: a.b.c.d(外網的上網地址)
eth1: 172.16.44.1(做為內網的網關)
Tip
原先我使用eth0:0的這種虛擬網卡的形式去配置一直不成功,後來使用雙網卡的時候一直忘了把eth0:0這張虛擬網卡刪掉導致了限速配置一直不成功,浪費了大把的青蔥。
配置iptables nat
#開啟ip_forward
echo "1">/proc/sys/net/ipv4/ip_forward
#清除原來的防火牆規則
iptables -F
iptables -t nat -F
iptables -t mangle -F
#添加nat轉發
iptables -t nat -A POSTROUTING -s 172.16.44.0/24 -o eth0 -j MASQUERADE
通過執行上面的代碼後,區域網內的電腦就可以上網了。
埠轉發
由於我的內網還掛了網站,所以要開啟80埠的轉發。
iptables -t nat -I PREROUTING -p tcp -d a.b.c.d --dport 80 -j DNAT --to 172.16.44.210:80
iptables -t nat -I POSTROUTING -p tcp -d 172.16.44.210 --dport 80 -j SNAT --to 172.16.44.1
這條命令指定外網地址a.b.c.d的80埠轉發到172.16.44.210:80上。由於是雙網卡,所以需要做一下迴路。
下載限速
下載限速要在eth1上面做,判斷數據包的目的地址來做限制。tc包括三部分:隊列、類、過濾器。我使用了htb方式去限制速度,也可以使用cbq,但cbq配置比較復雜一點,而且據說性能沒htb好。
#刪除原來的tc規則隊列
tc qdisc del dev eth1 root
#添加tc規則隊列
tc qdisc add dev eth1 root handle 10: htb default 256
#生成根類
tc class add dev eth1 parent 10: classid 10:1 htb rate 100mbit ceil 100mbit
#支類列表用於限制速度
#這里的rate指的是保證帶寬,ceil是最大帶寬。
tc class add dev eth1 parent 10:1 classid 10:10 htb rate 400kbps ceil 400kbps prio 1
#添加支類規則隊列
#採用sfq偽隨機隊列,並且10秒重置一次散列函數。
tc qdisc add dev eth1 parent 10:10 handle 101: sfq perturb 10
#建立網路包過濾器,設置fw。
tc filter add dev eth1 parent 10: protocol ip prio 10 handle 1 fw classid 10:10
#在iptables裡面設定mark值,與上面的handle值對應。
iptables -t mangle -A POSTROUTING -d 172.16.44.130 -j MARK --set-mark 1
通過上面的代碼就可以限制172.16.44.130這台機子的下載速度到400kbps。
Tip
經過實際測試這里的kbps實際上就是KB/S每秒千位元組。另一個單位是kbit,這個才是每秒千比特。這里的172.16.44.130也可以寫成一個網段,比如:172.16.44.0/24
上傳限速
上傳限速的原理其實跟下載的差不多,只不過限制的網卡不同,要在eth0上過濾來源地址去限制。
#刪除原來的tc規則隊列
tc qdisc del dev eth0 root
#添加tc規則隊列
tc qdisc add dev eth0 root handle 20: htb default 256
#生成根類
tc class add dev eth0 parent 20: classid 20:1 htb rate 100mbit ceil 100mbit
#支類列表用於限制速度
tc class add dev eth0 parent 20:1 classid 20:10 htb rate 40kbps ceil 40kbps prio 1
#添加支類規則隊列
tc qdisc add dev eth0 parent 20:10 handle 201: sfq perturb 10
#建立網路包過濾器
tc filter add dev eth0 parent 20: protocol ip prio 100 handle 2 fw classid 20:10
iptables -t mangle -A PREROUTING -s 172.16.44.130 -j MARK --set-mark 2
Tip
跟下載不同的是POSTROUTING要改成PREROUTING,-d改成-s。
觀察連接數
通過iptables的nat連接可以通過下面的代碼查看。至於統計連接數可以寫代碼實現,也可以利用awk,grep等工具。反正裡面的內容就是文本,處理起來也比較簡單。
cat /proc/net/ip_conntrack
寫在結尾
到此上網、埠轉發和流量限制都已經實現。下次再考慮配置個dhcp server和dnsmasq。至於一些路由器其它諸如mac地址綁定,限制上網等用到的時候再去研究研究。
6. linux cgroup機制
Cgroup是control group的縮寫,是Linux內核提供的一種用於限制,記錄,隔離進程組所使用物理資源(cpu,memory,io等)的機制。
cgroup提供了一系列的功能用於對Linux系統資源進行管理和限制,主要功能包括如下
1:限制進程組可以使用的資源數量,例如進程組對內存的使用上限。
2:進程組的執行優先順序限制。
3:記錄進程組所使用的資源數量,例如進程組所使用的cpu時間。
4:進程組隔離的能力。
在cgroup中有一些基本定義或概念
1:Task,理解為系統中需要被控制的進程。
2:Subsystem,可以被控制的資源系統,例如cpu,IO,內存等。
3:Cgroup,按照某種控制標准而劃分而成的控制族。
4:hierarchy,Cgroup可以組織成樹狀結構,子節點繼承父節點的控制標准。
在系統中創建新的hierarchy時,系統中的所有任務都屬於該層級的默認cgroup(root group)的成員。
一個子系統只能附加到一個層級上。
一個層級可以附加多個子系統。
一個任務可以是cgroup的成員,但這些cgroup必須在不同的hierarchy中。
任務創建的子任務(進程),子進程自動成為父進程cgroup的成員。
關系圖如下:
blkio -- 這個子系統為塊設備設定輸入/輸出限制,比如物理設備(磁碟,固態硬碟,USB 等等)。
cpu -- 這個子系統使用調度程序提供對 CPU 的 cgroup 任務訪問。
cpuacct -- 這個子系統自動生成 cgroup 中任務所使用的 CPU 報告。
cpuset -- 這個子系統為 cgroup 中的任務分配獨立 CPU(在多核系統)和內存節點。
devices -- 這個子系統可允許或者拒絕 cgroup 中的任務訪問設備。
freezer -- 這個子系統掛起或者恢復 cgroup 中的任務。
memory -- 這個子系統設定 cgroup 中任務使用的內存限制,並自動生成由那些任務使用的內存資源報告。
net_cls -- 這個子系統使用等級識別符(classid)標記網路數據包,可允許 Linux 流量控製程序(tc)識別從具體 cgroup 中生成的數據包。
ns -- 名稱空間子系統。
Linux系統中最多可以建12棵cgroup層級樹(每棵樹關聯一個子系統),也可以最少建一顆cgroup層級樹(關聯所有12個控制子系統)
可以通過mount命令完成
1.掛載一顆和所有subsystem關聯的cgroup樹到/sys/fs/cgroup
mount -t cgroup
xxx /sys/fs/cgroup
2.掛載一顆和cpuset
subsystem關聯的cgroup樹到/sys/fs/cgroup/cpuset
mkdir
/sys/fs/cgroup/cpuset
mount -t cgroup -o
cpuset xxx /sys/fs/cgroup/cpuset
3.掛載一顆與cpu和cpuacct
subsystem關聯的cgroup樹到/sys/fs/cgroup/cpu,cpuacct
mkdir
/sys/fs/cgroup/cpu,cpuacct
mount -t cgroup -o
cpu,cpuacct xxx /sys/fs/cgroup/cpu,cpuacct
4.掛載一棵cgroup樹,但不關聯任何subsystem
mkdir
/sys/fs/cgroup/systemd
mount -t cgroup -o
none,name=systemd xxx /sys/fs/cgroup/system
通過mount可以查看到cgroup的默認掛載點
每個目錄下,其中的文件描述了如何對資源進行限制。
在每個進程的/proc/$pid/cgroup文件中,描述了進程於cgroup的關系:
第一列描述cgroup的樹ID(該ID可以在/proc/cgroups中一一對應);第二列描述綁定的所有子系統;第三列描述進程在cgroup中的路徑。
當我們對某個任務需要進行限制時,不推薦直接在cgroup的各個子系統的root下修改配置,而是在對應的層級下建立單獨的控制節點。
例如如下,在cpu目錄下建立我們自己的子目錄:
進入我們創建的子目錄後,會看到系統已經創建好了資源控制文件,此時只需要修改這些配置文件滿足要求既可以。
要控制我們的進程,只需要將進程ID添加到tasks配置文件中即可以。