suricata中tv、slot和tm的關系必須要搞清楚。
在源碼中找到這三者的定義。
在threadvars.h中,有 ThreadVars 定義:
在tm-thread.h中,有 TmSlot 的定義:
在tm-modules.h中,有 TmModule 的定義:
三者的關系如下圖所示:
每個線程都包含壹個slot的鏈表,每個slot結點都懸掛著不同的模塊,程序執行時會遍歷slot鏈表,按照加入順序執行模塊。
SuricataMain函數中開頭就有函數InitGlobal,該函數體內調用了壹個 RunModeRegisterRunModes 函數,我們找到這個函數的定義:
其中每壹種運行模式調用RunModeRegisterNewRunMode註冊各自的Custom mode。例如
RunModeFilePcapRegister 函數:
RunModeRegisterNewRunMode函數會將回調函數(RunModeFilePcapSingle、RunModeFilePcapAutoFp)添加到runmodes全局數組中。
RunModes類型的全局數組==runmodes==保存運行模式,存儲結構如下圖:
註:這張圖應該比較老了,現在只有single、autofp和workers三種自定義模式。
RunMode和RunModes結構體的定義如下:
同時也可以看到,suricata有 single, autofp和workers 這幾種不同的自定義模式。這三種模式,在下文會細說。
在suricata.c中找到 RegisterAllModules 的定義,如下所示:
選擇其中壹個註冊函數打開:
可以發現模塊被保存到了 tmm_modules 數組中,是模塊類型TmModule的數組。
存儲結構如下圖所示:
模塊初始化的函數是 TmModuleRunInit ,定義如下:
該函數執行了模塊全局初始化函數Init()。
RunModeDispatch 函數的功能主要如下:
這個回調函數主要做了這些事:
首先,三種自定義模式的運行流程圖如下:
單工作線程完成所有工作。首個模塊完成抓包,其他模塊依次處理,沒有後續隊列。
根據監聽網卡數量和每個網卡可啟用的並行抓包線程數量確定工作線程數量。每個工作線程與single模式單線程工作流程壹樣,互不影響。
兩種數據包處理線程,分別是收包線程和檢測線程。收包線程和檢測線程間通過PacketQueue傳遞數據包進行處理,每個檢測線程對應壹個隊列,多個檢測線程時需要為數據包選擇隊列以確保同壹個流的數據包按順序傳遞給同壹個檢測線程。
其中的autofp模式是最復雜的,也是默認的自定義模式。如下所示:
同線程內的模塊之間主要是以參數的形式進行數據傳遞,不同線程之間以***享隊列的方式進行數據傳遞。
每個線程由ThreaVars結構體來抽象,ThreadVars對象指定線程輸入數據隊列inq和輸出數據隊列outq。
這些隊列在多個線程之間進行***享,壹個線程的輸出隊列可能是另壹個線程的輸入隊列。
[圖片上傳失敗...(image-3ca5b5-1627459445094)]
綠色線條表示數據的走向。從輸入隊列獲取數據包packet,經過slot函數(模塊函數)的處理後,再將加工後的packet放到輸出隊列中。
以上三張圖都是autofp模式下的運行流程圖。
從上面"autofp"模式中可以看出RX thread所處的位置和包含的功能模塊。它主要用於收集packets並對其進行解碼,將處理後的packets放到pickup queue中,以供下個模塊使用。
RX thread的作用體現為線程函數 TmThreadsSlotPktAcqLoop ,主要執行的任務為:
從上面"autofp"模式中可以看出W thread所處的位置和包含的功能模塊。它主要由FlowWorker模塊和壹些log模塊組成, 主要完成數據檢測和特定格式特定數據的日誌輸出。
W thread的作用體現為線程函數==TmThreadsSlotVar==,主要執行的任務為:
TX thread的功能就是根據Detect模塊檢測的結果,對Verdict模塊和RespondReject模塊對標記的包進行相應的處理。
藍色線條表示packet的傳遞路徑。