Try   HackMD

111-2專題研究筆記Week7-8

Performance Implications of Packet Filtering

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洪水攻擊時重複以上類似的實驗,這也是主要與之後的XDPsocket 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的部分還沒做,之後也要完成。