111-2專題研究筆記Week7-8 https://www.net.in.tum.de/fileadmin/bibtex/publications/papers/ITC30-Packet-Filtering-eBPF-XDP.pdf
現代的網路架構在防火牆上有一些缺失,主要有以下四個:
該被filter掉的packet太晚被filter掉導致效能出現不必要的overhead及隱藏的危險性
開發者對於送到自己的app的封包應該有最適的filtering規則,應該要能將自己的filtering policy與自己的app一起推出
就算管理者知道每個app的需求,還是需要應對數不清、不斷變動的網路相關configuration policy
最後就是效能的問題,與上面所述三者也都有相關
而現代所用的防火牆技術大部分是透過hook在kernel的module來達成的,比如iptables、nftables,但當一個packet被filter掉的時候,一些不必要的traffic早就造成了overhead,如 memory copy。為了解決上述問題,有兩種與以往不同的filter技術被推出,那就是將filter的場域從kernel分別往上移或往下移 – -往上移至user space或是將packet parsing的工作直接交由外部的FPGA類型網卡解決(見 https://www.xilinx.com/publications/about/ANCS_final.pdf )。
我們首先透過XDP將進入network stack之前的packet就先作過濾的動作,可以過濾掉可疑的host、Denial-of-Service flooding attack等較為簡單的情況(如之前正仁學長做過的實驗)。
還有是透過eBPF將傳統的rule set給break,讓app來handle他自己的packet,如此就可以將這條data path的rule給最簡化:因為他只需要顧到一個application。要達成上述的成果,我們需要使用socket attached packet filting,將filter的場所放置到socket level也就是user level的位置。
Image Not Showing
Possible Reasons
The image file may be corrupted The server hosting the image is unavailable The image path is incorrect The image format is not supported
Learn More →
基準測試:iptables with Moongen moongen
Image Not Showing
Possible Reasons
The image file may be corrupted The server hosting the image is unavailable The image path is incorrect The image format is not supported
Learn More →
https://github.com/emmericp/MoonGen
藉由lua script jit(Just-In-Time virtual machine)以及intel DPDK實現的packet flow generator,DPDK透過zero-copy技術將NIC收發的封包直接存入記憶體,app可以透過DPDK提供的API直接存取該段記憶體,徹底繞過了kernel,因此可以對傳出去的封包有著極大的操作空間,包括從單一位址發送多種host的packet,可以拿來自訂我們需要的測試流量,再加上定義封包使用的是lua script,其不需要經過編譯,因此速度上可大大加快。
照著github頁面裝之後還是遇到很多問題(在ubuntu18.04上),之後找到了一些還需安裝的部分:
libtbb-dev dpdk-igb-uio-dkms
Image Not Showing
Possible Reasons
The image file may be corrupted The server hosting the image is unavailable The image path is incorrect The image format is not supported
Learn More →
這是原先計劃的設計圖,但很快就遇到了許多問題 … 經過一兩個下午的推敲之後大概知道原因:Moongen使用的DPDK面向近代的高性能網路卡,且只有特定型號能支援,而具體的原因在travel過許多lua的bug後,推測為目前使用oracle vm模擬出來的虛擬網卡的型號與driver型號並不支援moongen專案的要求,舉例來說,一個sample script就會需要NIC上具備3個以上的TX及RX queue,而虛擬機提供的模擬NIC只有提供TX queue、RX queue各一個,因此使用moongen的辦法在現階段可能需要先行擱置。 基準測試:iptables with Iperf
Image Not Showing
Possible Reasons
The image file may be corrupted The server hosting the image is unavailable The image path is incorrect The image format is not supported
Learn More →
無法以論文的moongen方式來分析效能,於是我們採用了備用方案:測試流量的工具iperf。原先打算利用一台client與server的結構來先對number of rule與傳輸效率的關係做比較,但後來發現這樣傳輸的瓶頸不會在packet parsing上,且還有packet loss等問題,做出來的差距並不明顯,因此後來採用在本機端對自己做iperf,這樣瓶頸就會出現在packet parsing上了。以下的數據是ubuntu 18.04vm上進行,限制使用單核CPU且將效能壓在70%也就是約3 Ghz的頻率,並且將recieve buffer限制在1 kb避免其影響速率判斷,以不同的iptables rule數量來分析packet processing的效率,而最基準的數據也就是沒有開啟iptables時的數據為 1.98G per seconed :
Image Not Showing
Possible Reasons
The image file may be corrupted The server hosting the image is unavailable The image path is incorrect The image format is not supported
Learn More →
可以看到,隨著iptables規則的提升,處理packet的速度也顯著地下降。 接下來我們將實驗改成在阻擋ICMP洪水攻擊時重複以上類似的實驗,這也是主要與之後的 XDP 、 socket eBPF 比較的數值,架構圖如下:
Image Not Showing
Possible Reasons
The image file may be corrupted The server hosting the image is unavailable The image path is incorrect The image format is not supported
Learn More →
這次的rule就設立一條,主要是DROP掉所有來自attacker的攻擊。
在持續由attacker進行洪水攻擊的同時,處理正常封包的速度由原先的 1.98G per second 降至 0.939G per second ,但若沒有開啟iptables來阻擋便會只剩下 0.489G per second ,如下表
未遭受攻擊
遭受攻擊
遭受攻擊且有開iptables
1.98G per second
0.489G per second
0.939G per second
Image Not Showing
Possible Reasons
The image file may be corrupted The server hosting the image is unavailable The image path is incorrect The image format is not supported
Learn More →
基準測試:XDP with Iperf 透過在driver level提前利用簡單邏輯篩選掉封包,可以減少kernel的meta-data structure如sk_buff等的使用,有效減少系統over head。
這次為了方便起見,採用了之前正仁學長的專案,將bytecode load進去後一樣用與iptables相似的拓墣來實驗:
Image Not Showing
Possible Reasons
The image file may be corrupted The server hosting the image is unavailable The image path is incorrect The image format is not supported
Learn More →
而實驗結果如下表:
未遭受攻擊
遭受攻擊
遭受攻擊且有開XDP
1.98G per second
0.51G per second
1.05G per second
就結果而言與iptables相比,在遭受相同的攻擊時處理正常封包的效率能有10%以上的提升。
接著我們透過這個專案來測試XDP在rule的數量多起來的時候的表現:
https://github.com/gamemann/XDP-Firewall
這個專案可以將XDP規則寫在檔案裡,我們一樣測試32、64 … 之類數量的規則。
conf檔例子:
interface = "ens18";
updatetime = 15;
filters = (
{
enabled = true,
action = 0,
udp_enabled = true,
udp_dport = 27015
},
{
enabled = true,
action = 1,
tcp_enabled = true,
tcp_syn = true,
tcp_dport = 27015
},
{
enabled = true,
action = 0,
icmp_enabled = true,
icmp_code = 0
},
{
enabled = true,
action = 0,
srcip = "10.50.0.4"
}
);
但這裡遇到了些問題,自己對自己做iperf測速來觀察packet process效率的方法無法使用,因為packet似乎在一個host內傳送時根本不會傳到那麼底層,也就是說吃不到XDP的data path,因此這部分暫時無法做明顯的比較。
之後想到了解決辦法,自身IP loopback是藉由lo這個linux自帶NIC所完成的,所以將XDP load進lo上面,就可以讓loop back的流量經過XDP。
塞XDP的rule只有塞到128個,因為再多的話程式竟然會噴segmentation fault … 推測是kernel效能的問題。
Image Not Showing
Possible Reasons
The image file may be corrupted The server hosting the image is unavailable The image path is incorrect The image format is not supported
Learn More →
從圖表中看出來,塞無用rule的情況下XDP竟然效能來的比iptables差?這顯然不合預期。推測這樣判斷並不準確,問題應該是出由同個host不同網卡互傳的問題上,應該還是要將sender與reciever分開到兩個不同機器。
想到了有趣的問題,過去用iperf測試時都以頻寬作為測量標準,實際傳送出去的封包可能沒幾個,接下來會修正之前做的實驗,改以size小但數量大的封包flow來做測試。 iperf實在是很看出接收端的packets per seconed,換作其他測試工具:ostinato Testing with ostinato ostinato packets generator可以完全自訂所要傳送的packet,包括source、payload及protocal等等。
Image Not Showing
Possible Reasons
The image file may be corrupted The server hosting the image is unavailable The image path is incorrect The image format is not supported
Learn More →
這裡打算使用parser端建立一個udp socket program,循環將socket buffer中的封包讀出,並print出接收pps,並利用ostinato建立一個stream以每秒30000個封包的速度傳送udp封包給parser,每個封包大小為64byte。
Image Not Showing
Possible Reasons
The image file may be corrupted The server hosting the image is unavailable The image path is incorrect The image format is not supported
Learn More →
但在這裡又遇到了一些問題,原本是在parser端做一個socket program來取封包,結果不管加幾條rule都不會影響取封包的速度,摸索、嘗試很久後,了解到可能跟linux的udp、tcp bufer size有關。
因此透過
echo 'net.core.rmem_max=20000000' >> /etc/sysctl.conf
來將buffer size放大。
接下來開始測試增加rule對iptables處理封包的影響,一樣測試32、64 … 個無用rule對封包處理速度的影響。但是很奇怪的是不論加多少個rule,都不會影響每秒處理的封包量。
Image Not Showing
Possible Reasons
The image file may be corrupted The server hosting the image is unavailable The image path is incorrect The image format is not supported
Learn More →
比對論文的結果之後推測應該是因為硬體限制:
對於kernel的限制,應該是到處理1Mpps(每秒百萬個封包)以上等級才會體現出來,但目前透過虛擬機,就算如何壓低封包數量也最多只能每秒傳送10萬個左右的封包。
也有嘗試過將CPU 效能降低等來強制出現瓶頸的辦法,但也無法。推測應該使用論文裡說的以實體機器、實體線路對接,才有可能產生如此大量的封包流。
iptables with mixed packets 於是處理封包速率的實驗先暫時擱置,現在預計使用ostinato產生兩個封包流,其中一個的source ip被iptables drop掉,另一個可以通過,來觀察其表現。
Image Not Showing
Possible Reasons
The image file may be corrupted The server hosting the image is unavailable The image path is incorrect The image format is not supported
Learn More →
正常情況
30%為Drop封包
80%為Drop封包
70k packets per second
25k packets per second
11k packets per second
XDP with mixed packets
Image Not Showing
Possible Reasons
The image file may be corrupted The server hosting the image is unavailable The image path is incorrect The image format is not supported
Learn More →
這裡一樣用上面用過的簡易XDP防火牆,Drop掉來自192.168.88.117的封包,如上圖: 實驗結果如下:
正常情況
30%為Drop封包
80%為Drop封包
70k packets per second
45k packets per second
23k packets per second
待處理部分 1、接下來希望能夠用實體機器產生百萬級別的封包流,只有這樣才能真正反應parsing所帶來的效能瓶頸。
2、ostinato仍然有許多不方便的地方,如接收封包的部分,而moongen卻是能處理接收封包的邏輯,會嘗試在實體機器上嘗試。
3、Paper中還有講到 Socket eBPF 的部分還沒做,之後也要完成。