梁本來 朱 磊
1(中山職業技術學院信息工程學院 廣東 中山 528404) 2(西安理工大學計算機科學與工程學院 陜西 西安 710048)
高速率網絡帶來的流量激增,使得網絡入侵檢測系統(Network Intrusion Detection System, NIDS)的檢測性能出現瓶頸,傳統的單檢測引擎NIDS難以實時處理高速率流量。因此,基于多引擎并行檢測的NIDS是當今的研究重點與趨勢[1-2]。特別指出,并行NIDS與分布式NIDS 并不相同,分布式NIDS將多個檢測引擎分布在網絡的不同物理位置檢測不同處的網絡流量,而并行NIDS則將多個檢測引擎分布在網絡的同一個物理位置,檢測同一處的網絡流量。盡管兩者不同,但分布式NIDS也會用到并行檢測,兩者有相通之處[3-4]。
為充分發揮并行NIDS的高效性能, 應在保持攻擊證據的前提下,盡量通過流量調度實現多檢測引擎的負載均衡。目前,并行NIDS的負載均衡算法主要分為靜態算法和動態算法兩大類[5-6]。靜態算法按照設定的策略進行流量調度,多采用Hash函數映射來實現[7],該類算法的優點是不會破壞數據流的完整性,攻擊證據保持較好,缺點是難以適應實際動態網絡環境,各檢測引擎的負載均衡效果較差。動態算法根據檢測引擎負載的實時變化,動態調度網絡流量,優點是負載均衡效果較好,缺點是容易破壞流量的完整性,保持攻擊證據的難度相對較大,算法復雜度較高[8]。動態負載均衡算法又分為激活策略和前攝策略兩類,激活策略算法調度流量到檢測引擎前不考慮引擎負載,但當某個引擎負載超過設定閾值時,激活算法,將流量從負載較重的引擎遷移到負載較輕的引擎。文獻[9]提出的多檢測引擎監測的動態負載均衡算法,文獻[10]提出的分布式入侵檢測中基于能力與負載的數據分割算法,以及文獻[11]提出的動態層次負載均衡算法,均是激活策略算法。此類算法針對性強,負載均衡效果較好,但會帶來檢測引擎間的通信量較大的問題,在實際應用中會額外占用檢測引擎的計算資源,導致NIDS的檢測性能下降。前攝策略算法在流量調度前就根據各檢測引擎的實時負載,動態調度流量,確保各檢測引擎的負載均衡。文獻[12]提出的并行入侵檢測系統的預測負載均衡方法,以及文獻[13]提出的一種基于“最小PPS(Packet Per Second)”的動態流量調度策略,均采用了前攝策略思想。此類算法不需要檢測引擎間的大量通信,額外占用檢測引擎的計算資源較小,但需要采取較為科學的方法將流量按類劃分調度到不同的檢測引擎,且不能破壞數據流的完整性,盡量保持攻擊證據。但以上并行入侵檢測方法都存在相應優缺點,在保持攻擊證據與多引擎負載均衡之間難以全面提升。
分析攻擊特征,可將攻擊分為單連接攻擊以及多連接攻擊兩大類[14]。前者攻擊特征分布在同一條數據流的報文中,多數攻擊屬于此類攻擊,比如利用操作系統漏洞或程序漏洞發起的攻擊;后者攻擊特征分布在不同數據流的報文中,比如分布式拒絕服務(Distributed Denial of Service, DDoS)、掃描(Scan)等攻擊。
以上文獻提出的入侵檢測負載均衡算法多是分析單連接攻擊,而忽略了多連接攻擊,造成多連接攻擊的流量被調度至不同檢測引擎,而檢測引擎間又缺少互相通信獲取全局信息的機制,導致攻擊證據的丟失。為解決此類問題,本文提出基于攻擊分類的高性能并行入侵檢測方法,將NIDS分為單連接攻擊檢測和多連接攻擊檢測兩個子系統。其中,多連接攻擊檢測子系統采用單檢測引擎,快速掃描報文首部,識別相應攻擊行為;單連接攻擊檢測子系統采用多檢測引擎并行檢測,將流量按照傳輸層協議分類,以會話或五元組為單位,將流量調度至負載最輕的檢測引擎,既能保持攻擊證據,又動態實現了負載均衡,且額外占用檢測引擎的計算資源較少。
方法思路如圖1所示。

圖1 基于攻擊分類的并行入侵檢測方法實現結構圖
(1) 多連接攻擊檢測子系統由高性能檢測引擎SensorB組成,其從鏡像口2拷貝網絡流量。為提高檢測效率,SensorB基于Snort 3.0系統改進,在原有規則庫中僅保留多連接攻擊規則文件,快速檢測報文首部,識別多連接攻擊行為。
(2) 單連接攻擊檢測子系統由SensorA1、A2、…、An等檢測引擎組成,基于Snort 3.0系統改進,在原有規則庫中僅保留單連接攻擊規則文件。因單連接攻擊行為復雜多樣,為保持攻擊證據并實現各檢測引擎的負載均衡,先由負載均衡模塊對鏡像口1拷貝的網絡流量進行流量調度。
(3) 負載均衡模塊由流量調度及負載監控兩個子模塊組成。其中,負載監控子模塊實時監視SensorA1、A2、…、An的負載,計算出負載最輕的檢測引擎;流量調度子模塊將網絡流量按照TCP、UDP以及其他協議進行分類,并觸發以下流量調度策略。
① TCP流量以會話為單位進行調度。每個會話的第一個報文被調度至當前負載最輕的檢測引擎Am(m=1,2,…,n),相同會話的其他報文也被調度至Am。此方法可以保證同一會話的TCP報文被調度到同一個檢測引擎。
② UDP流量以五元組(源IP,源端口,目的IP,目的端口,協議類型)為單位進行調度。如果報文的五元組是第一次出現,則將該報文調度至當前負載最輕的檢測引擎Am,與該五元組相同的其他報文,統一被調度至Am。此方法可以保證相同五元組的UDP報文被調度到同一個檢測引擎。
③ 其他流量,則直接以報文為單位,調度至當前負載最輕的檢測引擎。
方法流程如圖2所示。

圖2 基于攻擊分類的并行入侵檢測方法流程
負載均衡算法運行在負載均衡模塊,是本文所提入侵檢測方法的核心算法,作用于單連接攻擊檢測子系統,在保持單連接攻擊證據的前提下實現多檢測引擎的負載均衡。
Pi:接收到的第i個報文,其中i=1,2,…;
Conn_num:目前所記錄的五元組數目(五元組信息不同時才計數,初始為0);
Max_num:一個周期內的五元組個數閾值;
Conn(Pi):報文Pi的五元組;
Conn(Pi).flag:Conn(Pi)的標記;
Conn(Pi).seq:Conn(Pi)的序號;
Conn(Pi).sensor:Conn(Pi) 指向的檢測引擎;
Am:當前負載最輕的檢測引擎;
Pi.SYN:TCP報文Pi的SYN位數值;
Pi.FIN:TCP報文Pi的FIN位數值;
Pi.RST:TCP報文Pi的RST位數值;
Pi.SEQ:TCP報文Pi的序號。
定義1報文五元組
報文Pi的五元組定義如下:
Conn(Pi)=(Pi.srcIP,Pi.srcPort,Pi.dstIP,Pi.dstPort,Pi.proType)
(1)
式中:srcIP表示源IP;srcPort表示源端口;dstIP表示目的IP;dstPort表示目的端口;proType表示傳輸層協議。
定義2相同五元組
如果報文Pi和Pj存在以下關系

(2)
則Conn(Pi)=Conn(Pj),相同五元組由同一個內存空間存儲,改變Conn(Pi)的flag、seq、sensor的取值,即是改變Conn(Pj)對應的數值。
定義3檢測引擎的負載
定義SensorAi的負載計算公式如下:
Load(Ai)=a·L(CPUi)+b·L(Memi)+c·L(Busi)
(3)
式中:L(CPUi)表示Ai的CPU利用率;L(Memi)表示Ai的內存利用率;L(Busi)表示Ai的鏈路帶寬利用率。a、b、c分別為權重系數,a+b+c=1。參考文獻[10],a取值為0.4,b取值為0.3,c取值為0.3。
定義4負載最輕的檢測引擎
如果Sensor Am的負載滿足以下公式:
Load(Am)=min{Load(A1),Load(A2),…,Load(An)}
(4)
則SensorAm就是負載最輕的檢測引擎。
以一個運行周期為例,算法偽代碼描述如下:
算法1負載均衡算法
For(Pi=P1;Conn_num<=Max_num;i++)
{if(Pi.proType!=TCP&&Pi.proType!=UDP)
//TCP、UDP之外的報文
Piwill be sent to SensorAm;
//當前負載最輕引擎Am
else
if(Conn(Pi) is new)
//該五元組是第一次出現
{Conn(Pi).flag=0;
//初始化flag
Conn_num++;
//五元組計數加1
if(Pi.proType==TCP)
//五元組是第一次出現,且是TCP報文
Conn(Pi).seq=0;}
//初始化seq
if(Pi.proType==TCP)
//TCP報文
{if(Conn(Pi).flag==0)
//會話的第一個報文
{Piwill be sent to SensorAm;
//當前負載最輕引擎Am
Conn(Pi).sensor=Am;
//該會話對應的引擎為Am
Conn(Pi).flag=1;}
else
//不是會話的第一個報文
Piwill be sent toConn(Pi).Sensor;
//被調度至會話對應的引擎
if(Pi.FIN==1&&Conn(Pi).seq==0)
//第一個FIN報文
Conn(Pi).seq=Pi.SEQ;
if(Pi.SEQ==Conn(Pi).seq+1‖Pi.RST==1)
//會話最后一個報文或異常關閉報文
{Conn(Pi).flag=0;
Conn(Pi).seq=0;}
if(Pi.proType==UDP)
//UDP報文
if(Conn (Pi).flag==0)
//該五元組第一個UDP報文
{Piwill be sent to SensorAm;
//當前負載最輕引擎Am
Conn (Pi).Sensor=Am;
//該五元組對應引擎為Am
Conn (Pi).flag=1;}
else
//不是該五元組第一個UDP報文
Piwill be sent to Conn (Pi).Sensor;
//被調度至該五元組對應的引擎
}
一個周期內,算法1需要循環調度Max_num個不同五元組的報文,假設每個五元組下包含的報文平均數為C,則需要調度的TCP、UDP報文數為C·Max_num;假設需要調度的TCP、UDP之外的報文數為Other_num,則算法1需要運行C·Max_num+Other_num次,而在循環體內并沒有嵌套循環,因此,以一個周期為計算單位,算法的時間復雜度為O(C·Max_num+Other_num)。
一個五元組中,IP地址占用32 bit存儲空間,端口占用16 bit存儲空間,proType只有TCP、UDP兩種狀態,需1 bit存儲空間,因此一個五元組占用97 bit的存儲空間。還需要記錄該五元組的sensor、flag和seq,假設檢測引擎個數為n,則sensor需要「log2n?bit的存儲空間;flag只有0,1兩種狀態,需要1 bit存儲空間;seq記錄報文的序號,需要32 bit的存儲空間。因此,每個五元組的sensor、flag和seq需要占用33+「log2n?bit的存儲空間。一個周期內,算法1處理的五元組數目為Max_num,因此總共需要(130+「log2n?)Max_numbit的存儲空間。另外,Conn_num變量最大取值為Max_num,需要占用「log2Max_num?bit的存儲空間。因此,算法1總共需要(130+「log2n?+「log2Max_num?)·Max_numbit的存儲空間。
通過以上分析可以看出,算法1的時空復雜度并不復雜,但仍可以通過降低Max_num數值減少時空復雜度。不過Max_num取值過小,會導致每一個運行周期過短,過渡切割了攻擊流量,難以完整地檢測到攻擊行為,因此Max_num的取值也是值得分析的一個問題。
以下定理都是基于同一個算法運行周期。
定理1TCP報文Pi被調度前,若Conn(Pi).flag標記為0時,則Pi是會話的第一個報文;Conn(Pi).flag標記為1時,則Pi不是會話的第一個報文。
證明: 基于Conn(Pi)五元組的TCP連接中可能包含多個會話,假設Pi是第一個會話的第一個報文,則Conn(Pi) 一定是新出現的五元組,因此Conn(Pi).flag被初始化為0,且因Pi為TCP報文,Conn(Pi).seq也被初始化為0;報文Pi被調度后,Conn(Pi).flag賦值為1。
該會話之后的報文被調度后,Conn(Pi).flag一直保持為1;第一個終止連接的報文被調度后,由于其FIN位為1,且Conn(Pi).seq==0,因此Conn(Pi).seq=Pi.SEQ;直到第一個會話的最后一個報文被調度完成后,由于滿足Pi.SEQ==Conn(Pi).seq+1,Conn(Pi).flag及Conn(Pi).seq均被重新賦值為0。
假如第一個會話過程中,碰到了Pi.RST==1的異常情況,則需要立即終止連接,Conn(Pi).flag及Conn(Pi).seq均被重新賦值為0。
因此,第二個會話的第一個報文被調度前,Conn(Pi).flag已被重新賦值為0。
以此類推可以得出,在Conn(Pi)連接中,每個會話的第一個報文被調度前,Conn(Pi).flag數值為0。每個會話的第一個報文被調度后,Conn(Pi).flag數值為1;之后Conn(Pi).flag數值保持為1不變,直到每個會話的最后一個報文被調度后,Conn(Pi).flag重新為0。
證畢。
定理2UDP報文Pi被調度前,若Conn(Pi).flag標記為0時,表示報文Pi是五元組Conn(Pi)的第一個報文;Conn(Pi).flag為1時,表示報文Pi不是Conn(Pi).的第一個報文。
證明:假設UDP報文Pi是五元組Conn(Pi)的第一個報文,則Conn(Pi)一定是新出現的五元組,因此Conn(Pi).flag被初始化為0,且報文Pi經過調度后,Conn(Pi).flag被賦值為1。
假設Pi是Conn(Pi)連接的第j(j≠1)個報文,經過上述分析得知,該報文被調度前,Conn(Pi).flag為1。
證畢。
定理3同一TCP會話下的所有報文,被調度至同一檢測引擎。
證明: 標記該TCP會話為S,由證明1可以得出,會話S的第一個報文PS1被調度前,由于Conn(PS1).flag標記為0,PS1被調度至當前負載最低的檢測引擎Am,且標記Conn(PS1).sensor=Am。
令PSi表示為會話S的第i個報文(i≠1),由于PSi和PS1同屬于會話S,則Conn(PSi)=Conn(PS1)。由于Conn(PSi).flag標記不為0,報文PSi被調度至Conn(PSi).sensor,即Conn[PS1].sensor,說明報文PSi也被調度至引擎Am。
證畢。
定理4同一五元組的所有UDP報文,被調度至同一檢測引擎。
證明:標記該組UDP五元組為U,由證明3可以得出,該五元組的第一個報文PU1被調度前,由于Conn(PU1).flag標記為0,PU1被調度至當前負載最輕的引擎Am,且標記Conn(PU1).sensor=Am。
令PUi表示為五元組U的第i個報文(i≠1),由于PUi和PU1的五元組相同,則Conn(PUi)=Conn(PU1)。由于Conn(PUi).flag標記不為0,報文PUi被調度至Conn(PUi).sensor,即Conn(PU1).sensor,說明報文PUi也被調度至引擎Am。
證畢。
構造如圖3所示的實驗拓撲,其中,交換機與路由器、交換機與負載均衡服務器,以及交換機與Sensor B之間鏈路最高傳輸速率為10 Gbit/s,其余鏈路最高傳輸速率為1 Gbit/s。為突出測試并行入侵檢測方法的性能,不宜采用性能超強的服務器用作檢測引擎,主機硬件配置見表1。

表1 主機硬件配置

圖3 實驗拓撲
其中,SensorA1-A4、SensorB及負載均衡服務器均安裝CentOS 7.0 64 bit操作系統,SensorA1-A4運行Snort3.0,僅保留單連接攻擊規則文件;Sensor B運行Snort3.0,僅保留多連接攻擊規則文件;負載均衡服務器監控SensorA1-A4的負載,運行算法1完成流量調度。
攻擊區共8臺主機,每臺主機安裝3個虛擬機,每個虛擬機分配1 GB內存,并輪詢使用10個IP地址;被攻擊區共4臺服務器,每臺服務器安裝3個虛擬機,并分別提供20個TCP服務和UDP服務,以上可以構造出57 600個不同的五元組,足以確保實驗質量。
攻擊區安裝Blade IDS Informer軟件[15],產生各種網絡攻擊行為,加上正常網絡流量,通過TcpReplay軟件重放實現包含以上攻擊行為的高速網絡流量[16]。
定義5NIDS檢測結果評價指標F-Measure。
參閱文獻[17],F-Measure(F)指標能全面準確評估NIDS的檢測結果,公式定義如下:
(5)
式中:R表示召回率;P表示查準率。
P=TP/(TP+FP)
(6)
R=TP/(TP+FN)
(7)
定義6NIDS檢測時延。
假設NIDS采集完網絡流量的時間為t1,NIDS最終檢測完成的時間t2,則NIDS的檢測時延Δt有如下公式:
Δt=t2-t1
(8)
定義7NIDS丟包率
假設NIDS檢測過程中丟失的報文數量為lp,待檢網絡流量總報文數量為ap,則丟包率L(loss_rate)有如下公式:
L=lp/ap
(9)


表2 不同Max_num取值下的實驗結果




本實驗包含多連接攻擊檢測以及單連接攻擊檢測, SensorA1-A4、SensorB以及負載均衡服務器全部工作。將本文方法與文獻[9]提出的多檢測引擎監測的動態負載均衡算法,文獻[10]提出的基于能力與負載的數據分割算法,文獻[11]提出的動態層次負載均衡算法,文獻[12]提出的預測負載均衡方法,文獻[13]提出的基于“最小PPS”的動態流量調度策略,統一采用4.1描述的實驗拓撲及環境,做不同方法的實驗對比。


圖4 單連接攻擊檢測的


圖5 多連接攻擊檢測的
分析原因,本文方法中多連接攻擊檢測子系統采用單檢測引擎,沒有攻擊證據的丟失。同時,為提高檢查效率,檢測引擎快速掃描報文首部,并只匹配多連接攻擊規則庫。而其他方法沒有區分單連接攻擊和多連接攻擊,統一采用多檢測引擎并行檢測,造成多連接攻擊的流量被調度至不同檢測引擎,而檢測引擎間又缺少互相通信獲取全局信息的機制,導致攻擊證據的丟失,檢測結果相對本文方法較差。


圖6 平均檢測時延

圖7 平均丟包率

實驗表明,本文方法在高速網絡環境下,具有更高的實用性和穩定性。
本文提出的基于攻擊分類的高性能并行入侵檢測方法,分為單連接攻擊檢測系統和多連接攻擊檢測系統,有效地解決了攻擊證據保持及負載均衡問題。實驗結果表明,相比其他并行入侵檢測方法,本文方法在單連接攻擊及多連接攻擊檢測中均表現優秀,F-Measure值提升顯著,檢測時延和丟包率也有一定降低。通過優化模式匹配算法及規則連設計方法,提升單個檢測引擎的檢測性能,從而提升并行NIDS的整體檢測性能,是作者今后的研究重點。