我們在進行安全性監(jiān)控、測試的過程中,難免會遇到這樣的問題:需要部署大量基于鏡像流量的安全設備,如IPS,異常流量,數(shù)據(jù)庫審計,流量分析等,可是交換機上可以做鏡像流量的端口數(shù)量有限制,購買專業(yè)的設備又太昂貴。
本文就針對此種情況,從Linux內核模塊對網絡數(shù)據(jù)庫包進行處理,解決上述問題。
應用場景
我們在進行安全性監(jiān)控、測試的過程中,難免會遇到這樣的問題:需要部署大量基于鏡像流量的安全設備,如IPS,異常流量,數(shù)據(jù)庫審計,流量分析等,可是交換機上可以做鏡像流量的端口數(shù)量有限制,購買專業(yè)的設備又太昂貴。
本文就針對此種情況,從Linux內核模塊對網絡數(shù)據(jù)庫包進行處理,解決上述問題。這里也感謝“白金PT”給予的幫助。
架構設計

內核模塊的流程比較簡單,轉發(fā)配置從用戶態(tài)提交給內核模塊,如”eth1@eth2_eth1@eth3_eth1/eth4@eth5“,這段的配置是:
來自eth1的流量,復制給eth2和eth3
來自eth1和eth4的流量,聚合給eth5
MIRROR內核模塊中,只需要實現(xiàn)參數(shù)讀取,配置分析,網卡判斷(源,目的)即可。
算法、代碼實現(xiàn)
參數(shù)輸入

這段代碼的功能是,將前面提到的如“eth1@eth2_eth1@eth3_eth1/eth4@eth5“這樣的參數(shù),按照”_”進行拆分,分段提交給參數(shù)設置函數(shù)”option_setup”
參數(shù)設置

這里我們把得到的參數(shù)”eth0@eth1”進行進一步的拆分,分出了源網卡eth0,目的網卡eth1,在內核模塊的全局變量中,有一個結構
”__read_mostly __u8 ethout_bits[MAX_OUT] ={0};“
用來存儲每個網卡對應分發(fā)的網卡號,可以這樣理解,如果服務器有8個網卡,那么每個網都會有一個8位的二進制數(shù)來標明它的轉發(fā),比如eth0復制到eth1,那么ethout_bits[0]就等于01000000,以此類推,如果我要把eth0復制到其他所有網卡,就會是01111111。
同時用一個全局的8字節(jié)變量,來存儲哪些網卡是鏡像流量口,防止多余的資源浪費。
__read_mostly__u8 ifindex_bits = 0;
Skb包復制和轉發(fā)

當Linux內核收到一個skb結構的數(shù)據(jù)包時,判斷這個數(shù)據(jù)包是不是在轉發(fā)列表里,也就是網卡是不是鏡像源。

接著我用了一個循環(huán),來遍歷存儲的轉發(fā)目的網口,如果匹配的話,就使用skb_clone函數(shù)將數(shù)據(jù)包復制一份,然后通過dev_queue_xmit函數(shù)直接發(fā)送出去。
最后清理skb_buff結構。
啟動腳本
為了方便調試和快速提交參數(shù),可以使用如下的shell腳本:

實測效果
編譯,填充參數(shù)并執(zhí)行
執(zhí)行sh sh.sh
Dmesg輸出

鏡像流量效果

這里可以看到流量統(tǒng)計由于網卡速率,時間差等,并不會100%一樣,是正常的。
CPU占用
當流量已經達到400M左右的時候,CPU占用仍然比較低。

MIRROR.c源代碼與pdf格式下載