一、前言
最近工做須要對網站的關鍵字進行檢測,找出敏感詞。這個過程須要對報文進行收集、解碼、檢測和記錄日誌。當前只是簡單實現功能,根據關鍵字進行簡單的匹配,而沒有進行關鍵字的語義分析。致使的結果就是JAVA能夠匹配AV這個敏感關鍵字。報文檢測這方面,開源項目已經作得很是好了,我所瞭解的有snort、suircata、bro,這三個都是很是優秀的IDS(入侵檢測系統)。因爲對bro沒有深刻了解,咱們對比了snort和suricata,結合suricata的多線程和模塊化,全面兼容snort規則,咱們選用了suricata進行關鍵字檢測。
剛開始接觸suricata的時候,壓根不知道這個單詞怎麼發音,因而乎趕忙再詞典上查一下。suircata是一款支持IDS、IPS和NSM的系統。關於suircata的詳細介紹能夠參考官網:https://suricata-ids.org/。
備註:
IDS:英文「Intrusion Detection Systems」的縮寫,中文意思是「入侵檢測系統」。依照必定的安全策略,經過軟、硬件,對網絡、系統的運行情況進行監視,儘量發現各類攻擊企圖、攻擊行爲或者攻擊結果,以保證網絡系統資源的機密性、完整性和可用性。
IPS是英文「Intrusion Prevention System」的縮寫,中文意思是入侵防護系統。隨着網絡攻擊技術的不斷提升和網絡安全漏洞的不斷髮現,傳統防火牆技術加傳統IDS的技術,已經沒法應對一些安全威脅。在這種狀況下,IPS技術應運而生,IPS技術能夠深度感知並檢測流經的數據流量,對惡意報文進行丟棄以阻斷攻擊,對濫用報文進行限流以保護網絡帶寬資源。
NSM:英文「network security monitoring」的縮寫,中文意思是「網絡安全監控」。
二、整體架構
報文檢測系統一般四大部分,報文獲取、報文解碼、報文檢測、日誌記錄;suricata不一樣的功能安裝模塊劃分,一個模塊的輸出是另外一個模塊的輸入,suricata經過線程將模塊串聯起來。安全
接下來以IDS爲例來講明suircata的線程與模塊之間是如何鏈接起來的。
首先註冊runmods,運行方式指定suricata獲取報文的方式,例如libpcap、netmap、af-packet等,代碼以下圖所示:網絡
而後再根據設置suricata的工做模式,找到對應獲取報文的處理模塊。suircata默認是經過af-packet mmap獲取報文,而後調用獲取報文模塊固然入口函數,
入口函數中函數添加了解碼模塊、流處理模塊(檢測報文)、日誌處理模塊。經過slot鏈條安裝註冊順序串聯起來。每個線程都包含一個slot的鏈表,每一個結點都懸掛着不一樣的模塊,程序執行的時候會遍歷slot鏈表,按照加入鏈表的熟悉執行模塊。多線程
建立線程,並將模塊添加到slot鏈表過程代碼以下所示:架構
1 /* create the threads */ 2 for (thread = 0; thread < threads_count; thread++) { 3 char tname[TM_THREAD_NAME_MAX]; 4 ThreadVars *tv = NULL; 5 TmModule *tm_module = NULL; 6 const char *visual_devname = LiveGetShortName(live_dev); 7 8 if (single_mode) { 9 snprintf(tname, sizeof(tname), "%s#01-%s", thread_name, visual_devname); 10 } else { 11 snprintf(tname, sizeof(tname), "%s#%02d-%s", thread_name, 12 thread+1, visual_devname); 13 } 14 tv = TmThreadCreatePacketHandler(tname, 15 "packetpool", "packetpool", 16 "packetpool", "packetpool", 17 "pktacqloop"); 18 if (tv == NULL) { 19 SCLogError(SC_ERR_THREAD_CREATE, "TmThreadsCreate failed"); 20 exit(EXIT_FAILURE); 21 } 22 23 //添加收包模塊 24 tm_module = TmModuleGetByName(recv_mod_name); 25 if (tm_module == NULL) { 26 SCLogError(SC_ERR_INVALID_VALUE, "TmModuleGetByName failed for %s", recv_mod_name); 27 exit(EXIT_FAILURE); 28 } 29 TmSlotSetFuncAppend(tv, tm_module, aconf); 30 //添加解包模塊 31 tm_module = TmModuleGetByName(decode_mod_name); 32 if (tm_module == NULL) { 33 SCLogError(SC_ERR_INVALID_VALUE, "TmModuleGetByName %s failed", decode_mod_name); 34 exit(EXIT_FAILURE); 35 } 36 TmSlotSetFuncAppend(tv, tm_module, NULL); 37 //添加流處理模塊,用於檢測報文 38 tm_module = TmModuleGetByName("FlowWorker"); 39 if (tm_module == NULL) { 40 SCLogError(SC_ERR_RUNMODE, "TmModuleGetByName for FlowWorker failed"); 41 exit(EXIT_FAILURE); 42 } 43 TmSlotSetFuncAppend(tv, tm_module, NULL); 44 //添加阻斷模塊 45 tm_module = TmModuleGetByName("RespondReject"); 46 if (tm_module == NULL) { 47 SCLogError(SC_ERR_RUNMODE, "TmModuleGetByName RespondReject failed"); 48 exit(EXIT_FAILURE); 49 } 50 TmSlotSetFuncAppend(tv, tm_module, NULL); 51 //添加日誌處理模塊 52 SetupOutputs(tv); 53 54 TmThreadSetCPU(tv, WORKER_CPU_SET); 55 56 if (TmThreadSpawn(tv) != TM_ECODE_OK) { 57 SCLogError(SC_ERR_THREAD_SPAWN, "TmThreadSpawn failed"); 58 exit(EXIT_FAILURE); 59 } 60 } 61
在AF-PACKET工做模式下提供三種工做方式:模塊化
關於工做方式能夠參考:http://blog.csdn.net/firedb/article/details/7581853。
目前我只用過worker工做模式,整個流程經過一個線程來處理。函數
三、總結oop
這是目前對suricata的一個總體的認識,接下來認真研究每一個模塊之間是如何交互。須要深刻學習suricata是如何收集報文,如何將收集的報文傳遞給解碼模塊,解碼模塊作哪些工做,輸出是什麼。學習
suricata各模塊功能:
Receive:從NFQUEUE中接收數據包,並將封裝在Packet結構中,而後放入下一個緩衝區。
Decode:對數據包進行解碼,主要是對數據包頭部信息進行分析並保存在Packet結構中。
StreamTCP:對數據包進行TCP流重組。
Detect:檢測數據包是否包含入侵行爲。
Verdict:對檢測後的數據包進行斷定,並將斷定結果告訴內核(經過ipq_set_verdict函數),方便內核對數據包進行接收、丟棄等處理。
RespondReject:經過libnet對那些要執行Reject操做的數據包進行相應的迴應。網站