【網絡入侵檢測】基于Suricata源碼分析應用協議識別實現

【作者主頁】只道當時是尋常

【專欄介紹】Suricata入侵檢測。專注網絡、主機安全,歡迎關注與評論。

1. 概要

👋?本文聚焦Suricata網絡安全引擎的協議解析器實現,詳細剖析HTTP、SSL/TLS、FTP、SSH、SMTP等協議的解析流程。

2. 源碼分析

2.1 HTTP協議解析器

RegisterHTPParsers 函數實現注冊 HTTP 協議解析器。下面是該函數代碼實現:

/***  \brief  Register the HTTP protocol and state handling functions to APP layer*          of the engine.*/
void RegisterHTPParsers(void)
{SCEnter();const char *proto_name = "http";/** HTTP */if (AppLayerProtoDetectConfProtoDetectionEnabled("tcp", proto_name)) {AppLayerProtoDetectRegisterProtocol(ALPROTO_HTTP1, proto_name);if (HTPRegisterPatternsForProtocolDetection() < 0)return;} else {SCLogInfo("Protocol detection and parser disabled for %s protocol",proto_name);return;}if (AppLayerParserConfParserEnabled("tcp", proto_name)) {AppLayerParserRegisterStateFuncs(IPPROTO_TCP, ALPROTO_HTTP1, HTPStateAlloc, HTPStateFree);AppLayerParserRegisterTxFreeFunc(IPPROTO_TCP, ALPROTO_HTTP1, HTPStateTransactionFree);AppLayerParserRegisterGetTxFilesFunc(IPPROTO_TCP, ALPROTO_HTTP1, HTPGetTxFiles);AppLayerParserRegisterGetStateProgressFunc(IPPROTO_TCP, ALPROTO_HTTP1, HTPStateGetAlstateProgress);AppLayerParserRegisterGetTxCnt(IPPROTO_TCP, ALPROTO_HTTP1, HTPStateGetTxCnt);AppLayerParserRegisterGetTx(IPPROTO_TCP, ALPROTO_HTTP1, HTPStateGetTx);AppLayerParserRegisterStateProgressCompletionStatus(ALPROTO_HTTP1, HTP_REQUEST_COMPLETE, HTP_RESPONSE_COMPLETE);AppLayerParserRegisterGetEventInfo(IPPROTO_TCP, ALPROTO_HTTP1, HTPStateGetEventInfo);AppLayerParserRegisterGetEventInfoById(IPPROTO_TCP, ALPROTO_HTTP1, HTPStateGetEventInfoById);AppLayerParserRegisterTxDataFunc(IPPROTO_TCP, ALPROTO_HTTP1, HTPGetTxData);AppLayerParserRegisterStateDataFunc(IPPROTO_TCP, ALPROTO_HTTP1, HTPGetStateData);AppLayerParserRegisterSetStreamDepthFlag(IPPROTO_TCP, ALPROTO_HTTP1, AppLayerHtpSetStreamDepthFlag);AppLayerParserRegisterParser(IPPROTO_TCP, ALPROTO_HTTP1, STREAM_TOSERVER, HTPHandleRequestData);AppLayerParserRegisterParser(IPPROTO_TCP, ALPROTO_HTTP1, STREAM_TOCLIENT, HTPHandleResponseData);SC_ATOMIC_INIT(htp_config_flags);/* This parser accepts gaps. */AppLayerParserRegisterOptionFlags(IPPROTO_TCP, ALPROTO_HTTP1, APP_LAYER_PARSER_OPT_ACCEPT_GAPS);AppLayerParserRegisterParserAcceptableDataDirection(IPPROTO_TCP, ALPROTO_HTTP1, STREAM_TOSERVER | STREAM_TOCLIENT);/* app-layer-frame-documentation tag start: registering relevant callbacks */AppLayerParserRegisterGetFrameFuncs(IPPROTO_TCP, ALPROTO_HTTP1, HTTPGetFrameIdByName, HTTPGetFrameNameById);/* app-layer-frame-documentation tag end: registering relevant callbacks */HTPConfigure();} else {SCLogInfo("Parsed disabled for %s protocol. Protocol detection""still on.", proto_name);}
#ifdef UNITTESTSAppLayerParserRegisterProtocolUnittests(IPPROTO_TCP, ALPROTO_HTTP1, HTPParserRegisterTests);
#endifSCReturn;
}

2.1.1 配置開啟

AppLayerProtoDetectConfProtoDetectionEnabled 函數是一個通用的配置開啟檢查函數,通過第二個參數傳入"http"字符串用于檢測配置文件中 app-layer.protocols.http.enabled 選項是否開啟,若開啟則繼續注冊操作,如果未開啟則終止 HTTP 協議解析器的注冊操作。

2.1.2 協議識別

Suricata 中,HTTP 協議識別通過在應用數據中匹配特定模式串實現,協議識別器針對報文流方向(STREAM_TOSERVER STREAM_TOCLIENT)定義了不同的模式串,在 HTPRegisterPatternsForProtocolDetection 函數中實現了模式串的注冊。

(1)客戶端 -> 服務端

在下面這些字符串后面添加空格(|20|)或者制表符(|09|)作為模式串。

"GET", "PUT", "POST", "HEAD", "TRACE", "OPTIONS","CONNECT", "DELETE", "PATCH", "PROPFIND", "PROPPATCH", "MKCOL", "COPY", "MOVE", "LOCK", "UNLOCK", "CHECKOUT", "UNCHECKOUT", "CHECKIN", "UPDATE", "LABEL", "REPORT", "MKWORKSPACE", "MKACTIVITY", "MERGE", "INVALID", "VERSION-CONTROL", "BASELINE-CONTROL".

(2)服務端 -> 客戶端

下面字符串作為模式串。

"HTTP/0.9", "HTTP/1.0", "HTTP/1.1".

2.2 SSL協議解析器

RegisterSSLParsers 函數實現注冊 SSL 協議解析器。下面是該函數代碼實現:

/*** \brief Function to register the SSL protocol parser and other functions*/
void RegisterSSLParsers(void)
{const char *proto_name = "tls";SC_ATOMIC_INIT(ssl_config.enable_ja3);/** SSLv2  and SSLv23*/if (AppLayerProtoDetectConfProtoDetectionEnabled("tcp", proto_name)) {AppLayerProtoDetectRegisterProtocol(ALPROTO_TLS, proto_name);if (SSLRegisterPatternsForProtocolDetection() < 0)return;if (RunmodeIsUnittests()) {AppLayerProtoDetectPPRegister(IPPROTO_TCP,"443",ALPROTO_TLS,0, 3,STREAM_TOSERVER,SSLProbingParser, NULL);} else {if (AppLayerProtoDetectPPParseConfPorts("tcp", IPPROTO_TCP,proto_name, ALPROTO_TLS,0, 3,SSLProbingParser, NULL) == 0) {SCLogConfig("no TLS config found, ""enabling TLS detection on port 443.");AppLayerProtoDetectPPRegister(IPPROTO_TCP,"443",ALPROTO_TLS,0, 3,STREAM_TOSERVER,SSLProbingParser, NULL);}}} else {SCLogConfig("Protocol detection and parser disabled for %s protocol",proto_name);return;}if (AppLayerParserConfParserEnabled("tcp", proto_name)) {AppLayerParserRegisterParser(IPPROTO_TCP, ALPROTO_TLS, STREAM_TOSERVER,SSLParseClientRecord);AppLayerParserRegisterParser(IPPROTO_TCP, ALPROTO_TLS, STREAM_TOCLIENT,SSLParseServerRecord);AppLayerParserRegisterGetFrameFuncs(IPPROTO_TCP, ALPROTO_TLS, SSLStateGetFrameIdByName, SSLStateGetFrameNameById);AppLayerParserRegisterGetEventInfo(IPPROTO_TCP, ALPROTO_TLS, SSLStateGetEventInfo);AppLayerParserRegisterGetEventInfoById(IPPROTO_TCP, ALPROTO_TLS, SSLStateGetEventInfoById);AppLayerParserRegisterStateFuncs(IPPROTO_TCP, ALPROTO_TLS, SSLStateAlloc, SSLStateFree);AppLayerParserRegisterParserAcceptableDataDirection(IPPROTO_TCP, ALPROTO_TLS, STREAM_TOSERVER);AppLayerParserRegisterTxFreeFunc(IPPROTO_TCP, ALPROTO_TLS, SSLStateTransactionFree);AppLayerParserRegisterGetTx(IPPROTO_TCP, ALPROTO_TLS, SSLGetTx);AppLayerParserRegisterTxDataFunc(IPPROTO_TCP, ALPROTO_TLS, SSLGetTxData);AppLayerParserRegisterStateDataFunc(IPPROTO_TCP, ALPROTO_TLS, SSLGetStateData);AppLayerParserRegisterGetTxCnt(IPPROTO_TCP, ALPROTO_TLS, SSLGetTxCnt);AppLayerParserRegisterGetStateProgressFunc(IPPROTO_TCP, ALPROTO_TLS, SSLGetAlstateProgress);AppLayerParserRegisterStateProgressCompletionStatus(ALPROTO_TLS, TLS_STATE_FINISHED, TLS_STATE_FINISHED);ConfNode *enc_handle = ConfGetNode("app-layer.protocols.tls.encryption-handling");if (enc_handle != NULL && enc_handle->val != NULL) {SCLogDebug("have app-layer.protocols.tls.encryption-handling = %s", enc_handle->val);if (strcmp(enc_handle->val, "full") == 0) {ssl_config.encrypt_mode = SSL_CNF_ENC_HANDLE_FULL;} else if (strcmp(enc_handle->val, "bypass") == 0) {ssl_config.encrypt_mode = SSL_CNF_ENC_HANDLE_BYPASS;} else if (strcmp(enc_handle->val, "default") == 0) {ssl_config.encrypt_mode = SSL_CNF_ENC_HANDLE_DEFAULT;} else {ssl_config.encrypt_mode = SSL_CNF_ENC_HANDLE_DEFAULT;}} else {/* Get the value of no reassembly option from the config file */if (ConfGetNode("app-layer.protocols.tls.no-reassemble") == NULL) {int value = 0;if (ConfGetBool("tls.no-reassemble", &value) == 1 && value == 1)ssl_config.encrypt_mode = SSL_CNF_ENC_HANDLE_BYPASS;} else {int value = 0;if (ConfGetBool("app-layer.protocols.tls.no-reassemble", &value) == 1 && value == 1)ssl_config.encrypt_mode = SSL_CNF_ENC_HANDLE_BYPASS;}}SCLogDebug("ssl_config.encrypt_mode %u", ssl_config.encrypt_mode);#ifdef HAVE_JA3CheckJA3Enabled();
#endif /* HAVE_JA3 */
#ifdef HAVE_JA4CheckJA4Enabled();
#endif /* HAVE_JA4 */if (g_disable_hashing) {if (SC_ATOMIC_GET(ssl_config.enable_ja3)) {SCLogWarning("MD5 calculation has been disabled, disabling JA3");SC_ATOMIC_SET(ssl_config.enable_ja3, 0);}if (SC_ATOMIC_GET(ssl_config.enable_ja4)) {SCLogWarning("Hashing has been disabled, disabling JA4");SC_ATOMIC_SET(ssl_config.enable_ja4, 0);}} else {if (RunmodeIsUnittests()) {
#ifdef HAVE_JA3SC_ATOMIC_SET(ssl_config.enable_ja3, 1);
#endif /* HAVE_JA3 */
#ifdef HAVE_JA4SC_ATOMIC_SET(ssl_config.enable_ja4, 1);
#endif /* HAVE_JA4 */}}} else {SCLogConfig("Parsed disabled for %s protocol. Protocol detection""still on.", proto_name);}return;
}

2.2.1 配置開啟

AppLayerProtoDetectConfProtoDetectionEnabled 函數是一個通用的配置開啟檢查函數,通過第二個參數傳入"tls"字符串用于檢測配置文件中 app-layer.protocols.tls.enabled 選項是否開啟,若開啟則繼續注冊操作,如果未開啟則終止 SSL 協議解析器的注冊操作。

2.2.2 協議識別

Suricata 中,SSL 協議識別通過在應用數據中匹配特定模式串實現,協議識別器針對報文流方向(STREAM_TOSERVER STREAM_TOCLIENT)定義了不同的模式串,在 SSLRegisterPatternsForProtocolDetection 函數中實現了模式串的注冊。

Suricata 根據報文方向以及應用報文中攜帶的特定模式串判斷報文所在流的協議類型。下面是匹配規則(其中偏移為從應用數據 0 字節開始偏移,深度為從偏移開始指定字節內包含特定模式串):

  1. 客戶端->服務端,偏移為 2,深度為 5,命中"|01 00 02|"字節序列。

  2. 客戶端->服務端,偏移為 0,深度為 3,命中"|01 03 00|"字節序列。

  3. 客戶端->服務端,偏移為 0,深度為 3,命中"|16 03 00|"字節序列。

  4. 客戶端->服務端,偏移為 0,深度為 3,命中"|01 03 01|"字節序列。

  5. 客戶端->服務端,偏移為 0,深度為 3,命中"|16 03 01|"字節序列。

  6. 客戶端->服務端,偏移為 0,深度為 3,命中"|01 03 02|"字節序列。

  7. 客戶端->服務端,偏移為 0,深度為 3,命中"|16 03 02|"字節序列。

  8. 客戶端->服務端,偏移為 0,深度為 3,命中"|01 03 03|"字節序列。

  9. 客戶端->服務端,偏移為 0,深度為 3,命中"|16 03 03|"字節序列。

  10. 服務端->客戶端,偏移為 0,深度為 3,命中"|15 03 00|"字節序列。

  11. 服務端->客戶端,偏移為 0,深度為 3,命中"|16 03 00|"字節序列。

  12. 服務端->客戶端,偏移為 0,深度為 3,命中"|17 03 00|"字節序列。

  13. 服務端->客戶端,偏移為 0,深度為 3,命中"|15 03 01|"字節序列。

  14. 服務端->客戶端,偏移為 0,深度為 3,命中"|16 03 01|"字節序列。

  15. 服務端->客戶端,偏移為 0,深度為 3,命中"|17 03 01|"字節序列。

  16. 服務端->客戶端,偏移為 0,深度為 3,命中"|15 03 02|"字節序列。

  17. 服務端->客戶端,偏移為 0,深度為 3,命中"|16 03 02|"字節序列。

  18. 服務端->客戶端,偏移為 0,深度為 3,命中"|17 03 02|"字節序列。

  19. 服務端->客戶端,偏移為 0,深度為 3,命中"|15 03 03|"字節序列。

  20. 服務端->客戶端,偏移為 0,深度為 3,命中"|16 03 03|"字節序列。

  21. 服務端->客戶端,偏移為 0,深度為 3,命中"|17 03 03|"字節序列。

2.3 FTP協議解析器

RegisterFTPParsers 函數實現注冊 FTP 協議解析器。下面是該函數代碼實現:

void RegisterFTPParsers(void)
{const char *proto_name = "ftp";const char *proto_data_name = "ftp-data";/** FTP */if (AppLayerProtoDetectConfProtoDetectionEnabled("tcp", proto_name)) {AppLayerProtoDetectRegisterProtocol(ALPROTO_FTP, proto_name);if (FTPRegisterPatternsForProtocolDetection() < 0 )return;AppLayerProtoDetectRegisterProtocol(ALPROTO_FTPDATA, proto_data_name);}if (AppLayerParserConfParserEnabled("tcp", proto_name)) {AppLayerParserRegisterParser(IPPROTO_TCP, ALPROTO_FTP, STREAM_TOSERVER,FTPParseRequest);AppLayerParserRegisterParser(IPPROTO_TCP, ALPROTO_FTP, STREAM_TOCLIENT,FTPParseResponse);AppLayerParserRegisterStateFuncs(IPPROTO_TCP, ALPROTO_FTP, FTPStateAlloc, FTPStateFree);AppLayerParserRegisterParserAcceptableDataDirection(IPPROTO_TCP, ALPROTO_FTP, STREAM_TOSERVER | STREAM_TOCLIENT);AppLayerParserRegisterTxFreeFunc(IPPROTO_TCP, ALPROTO_FTP, FTPStateTransactionFree);AppLayerParserRegisterGetTx(IPPROTO_TCP, ALPROTO_FTP, FTPGetTx);AppLayerParserRegisterTxDataFunc(IPPROTO_TCP, ALPROTO_FTP, FTPGetTxData);AppLayerParserRegisterGetTxIterator(IPPROTO_TCP, ALPROTO_FTP, FTPGetTxIterator);AppLayerParserRegisterStateDataFunc(IPPROTO_TCP, ALPROTO_FTP, FTPGetStateData);AppLayerParserRegisterLocalStorageFunc(IPPROTO_TCP, ALPROTO_FTP, FTPLocalStorageAlloc,FTPLocalStorageFree);AppLayerParserRegisterGetTxCnt(IPPROTO_TCP, ALPROTO_FTP, FTPGetTxCnt);AppLayerParserRegisterGetStateProgressFunc(IPPROTO_TCP, ALPROTO_FTP, FTPGetAlstateProgress);AppLayerParserRegisterStateProgressCompletionStatus(ALPROTO_FTP, FTP_STATE_FINISHED, FTP_STATE_FINISHED);AppLayerRegisterExpectationProto(IPPROTO_TCP, ALPROTO_FTPDATA);AppLayerParserRegisterParser(IPPROTO_TCP, ALPROTO_FTPDATA, STREAM_TOSERVER,FTPDataParseRequest);AppLayerParserRegisterParser(IPPROTO_TCP, ALPROTO_FTPDATA, STREAM_TOCLIENT,FTPDataParseResponse);AppLayerParserRegisterStateFuncs(IPPROTO_TCP, ALPROTO_FTPDATA, FTPDataStateAlloc, FTPDataStateFree);AppLayerParserRegisterParserAcceptableDataDirection(IPPROTO_TCP, ALPROTO_FTPDATA, STREAM_TOSERVER | STREAM_TOCLIENT);AppLayerParserRegisterTxFreeFunc(IPPROTO_TCP, ALPROTO_FTPDATA, FTPDataStateTransactionFree);AppLayerParserRegisterGetTxFilesFunc(IPPROTO_TCP, ALPROTO_FTPDATA, FTPDataStateGetTxFiles);AppLayerParserRegisterGetTx(IPPROTO_TCP, ALPROTO_FTPDATA, FTPDataGetTx);AppLayerParserRegisterTxDataFunc(IPPROTO_TCP, ALPROTO_FTPDATA, FTPDataGetTxData);AppLayerParserRegisterStateDataFunc(IPPROTO_TCP, ALPROTO_FTPDATA, FTPDataGetStateData);AppLayerParserRegisterGetTxCnt(IPPROTO_TCP, ALPROTO_FTPDATA, FTPDataGetTxCnt);AppLayerParserRegisterGetStateProgressFunc(IPPROTO_TCP, ALPROTO_FTPDATA, FTPDataGetAlstateProgress);AppLayerParserRegisterStateProgressCompletionStatus(ALPROTO_FTPDATA, FTPDATA_STATE_FINISHED, FTPDATA_STATE_FINISHED);AppLayerParserRegisterGetEventInfo(IPPROTO_TCP, ALPROTO_FTP, ftp_get_event_info);AppLayerParserRegisterGetEventInfoById(IPPROTO_TCP, ALPROTO_FTP, ftp_get_event_info_by_id);sbcfg.buf_size = 4096;sbcfg.Calloc = FTPCalloc;sbcfg.Realloc = FTPRealloc;sbcfg.Free = FTPFree;FTPParseMemcap();} else {SCLogInfo("Parsed disabled for %s protocol. Protocol detection""still on.", proto_name);}FTPSetMpmState();#ifdef UNITTESTSAppLayerParserRegisterProtocolUnittests(IPPROTO_TCP, ALPROTO_FTP, FTPParserRegisterTests);
#endif
}

2.3.1 配置開啟

AppLayerProtoDetectConfProtoDetectionEnabled 函數是一個通用的配置開啟檢查函數,通過第二個參數傳入"ftp"字符串用于檢測配置文件中 app-layer.protocols.ftp.enabled 選項是否開啟,若開啟則繼續注冊操作,如果未開啟則終止 FTP 協議解析器的注冊操作。

2.3.2 協議識別

Suricata 中,FTP 協議識別通過在應用數據中匹配特定模式串實現,協議識別器針對報文流方向(STREAM_TOSERVER STREAM_TOCLIENT)定義了不同的模式串,在 FTPRegisterPatternsForProtocolDetection 函數中實現了模式串的注冊。

Suricata 根據報文方向以及應用報文中攜帶的特定模式串判斷報文所在流的協議類型。下面是匹配規則(其中偏移為從應用數據 0 字節開始偏移,深度為從偏移開始指定字節內包含特定模式串):

  1. 服務端->客戶端,偏移為 0,深度為 5,命中"220 ("字符串。

  2. 客戶端->服務端,偏移為 0,深度為 4,命中"FEAT"字符串。

  3. 客戶端->服務端,偏移為 0,深度為 5,命中"USER "字符串。

  4. 客戶端->服務端,偏移為 0,深度為 5,命中"PASS "字符串。

  5. 客戶端->服務端,偏移為 0,深度為 5,命中"PORT "字符串。

2.4 SSH協議解析器

RegisterSSHParsers 函數實現注冊 SSH 協議解析器。下面是該函數代碼實現:

void RegisterSSHParsers(void)
{const char *proto_name = "ssh";if (AppLayerProtoDetectConfProtoDetectionEnabled("tcp", proto_name)) {AppLayerProtoDetectRegisterProtocol(ALPROTO_SSH, proto_name);if (SSHRegisterPatternsForProtocolDetection() < 0)return;/* Check if we should generate Hassh fingerprints */int enable_hassh = SSH_CONFIG_DEFAULT_HASSH;const char *strval = NULL;if (ConfGet("app-layer.protocols.ssh.hassh", &strval) != 1) {enable_hassh = SSH_CONFIG_DEFAULT_HASSH;} else if (strcmp(strval, "auto") == 0) {enable_hassh = SSH_CONFIG_DEFAULT_HASSH;} else if (ConfValIsFalse(strval)) {enable_hassh = SSH_CONFIG_DEFAULT_HASSH;} else if (ConfValIsTrue(strval)) {enable_hassh = true;}if (RunmodeIsUnittests() || enable_hassh) {rs_ssh_enable_hassh();}}SCLogDebug("Registering Rust SSH parser.");rs_ssh_register_parser();#ifdef UNITTESTSAppLayerParserRegisterProtocolUnittests(IPPROTO_TCP, ALPROTO_SSH, SSHParserRegisterTests);
#endif
}

2.4.1 配置開啟

AppLayerProtoDetectConfProtoDetectionEnabled 函數是一個通用的配置開啟檢查函數,通過第二個參數傳入"ssh"字符串用于檢測配置文件中 app-layer.protocols.ssh.enabled 選項是否開啟,若開啟則繼續注冊操作,如果未開啟則終止 SSH 協議解析器的注冊操作。

2.4.2 協議識別

Suricata 在 SSHRegisterPatternsForProtocolDetection 函數中實現模式串的注冊。

Suricata 根據報文方向以及應用報文中攜帶的特定模式串判斷報文所在流的協議類型。下面是匹配規則(其中偏移為從應用數據 0 字節開始偏移,深度為從偏移開始指定字節內包含特定模式串):

  1. 服務端->客戶端,偏移為 0,深度為 4,命中"SSH-"字符串。

  2. 客戶端->服務端,偏移為 0,深度為 4,命中"SSH-"字符串。

2.5 SMTP協議解析器

RegisterSMTPParsers 函數實現注冊 SMTP 協議解析器。下面是該函數代碼實現:

void RegisterSMTPParsers(void)
{const char *proto_name = "smtp";if (AppLayerProtoDetectConfProtoDetectionEnabled("tcp", proto_name)) {AppLayerProtoDetectRegisterProtocol(ALPROTO_SMTP, proto_name);if (SMTPRegisterPatternsForProtocolDetection() < 0 )return;} else {SCLogInfo("Protocol detection and parser disabled for %s protocol.",proto_name);return;}if (AppLayerParserConfParserEnabled("tcp", proto_name)) {AppLayerParserRegisterStateFuncs(IPPROTO_TCP, ALPROTO_SMTP, SMTPStateAlloc, SMTPStateFree);AppLayerParserRegisterParser(IPPROTO_TCP, ALPROTO_SMTP, STREAM_TOSERVER,SMTPParseClientRecord);AppLayerParserRegisterParser(IPPROTO_TCP, ALPROTO_SMTP, STREAM_TOCLIENT,SMTPParseServerRecord);AppLayerParserRegisterGetEventInfo(IPPROTO_TCP, ALPROTO_SMTP, SMTPStateGetEventInfo);AppLayerParserRegisterGetEventInfoById(IPPROTO_TCP, ALPROTO_SMTP, SMTPStateGetEventInfoById);AppLayerParserRegisterLocalStorageFunc(IPPROTO_TCP, ALPROTO_SMTP, SMTPLocalStorageAlloc,SMTPLocalStorageFree);AppLayerParserRegisterTxFreeFunc(IPPROTO_TCP, ALPROTO_SMTP, SMTPStateTransactionFree);AppLayerParserRegisterGetTxFilesFunc(IPPROTO_TCP, ALPROTO_SMTP, SMTPGetTxFiles);AppLayerParserRegisterGetStateProgressFunc(IPPROTO_TCP, ALPROTO_SMTP, SMTPStateGetAlstateProgress);AppLayerParserRegisterGetTxCnt(IPPROTO_TCP, ALPROTO_SMTP, SMTPStateGetTxCnt);AppLayerParserRegisterGetTx(IPPROTO_TCP, ALPROTO_SMTP, SMTPStateGetTx);AppLayerParserRegisterGetTxIterator(IPPROTO_TCP, ALPROTO_SMTP, SMTPGetTxIterator);AppLayerParserRegisterTxDataFunc(IPPROTO_TCP, ALPROTO_SMTP, SMTPGetTxData);AppLayerParserRegisterStateDataFunc(IPPROTO_TCP, ALPROTO_SMTP, SMTPGetStateData);AppLayerParserRegisterStateProgressCompletionStatus(ALPROTO_SMTP, 1, 1);} else {SCLogInfo("Parsed disabled for %s protocol. Protocol detection""still on.", proto_name);}SMTPSetMpmState();SMTPConfigure();#ifdef UNITTESTSAppLayerParserRegisterProtocolUnittests(IPPROTO_TCP, ALPROTO_SMTP, SMTPParserRegisterTests);
#endifreturn;
}

2.5.1 配置開啟

AppLayerProtoDetectConfProtoDetectionEnabled 函數是一個通用的配置開啟檢查函數,通過第二個參數傳入"smtp"字符串用于檢測配置文件中 app-layer.protocols.smtp.enabled 選項是否開啟,若開啟則繼續注冊操作,如果未開啟則終止 smtp 協議解析器的注冊操作。

2.5.2 協議識別

Suricata 在 SMTPRegisterPatternsForProtocolDetection 函數中實現模式串的注冊。

Suricata 根據報文方向以及應用報文中攜帶的特定模式串判斷報文所在流的協議類型。下面是匹配規則(其中偏移為從應用數據 0 字節開始偏移,深度為從偏移開始指定字節內包含特定模式串):

  1. 客戶端->服務端,偏移為 0,深度為 4,命中"EHLO"字符串。

  2. 客戶端->服務端,偏移為 0,深度為 4,命中"QUIT"字符串。

2.6 總結

上述協議類型僅為 Suricata 支持的部分協議。除模式串匹配外,其還支持其他識別方式:如 MQTT 協議解析器會監控 1883 端口流量,通過探測函數解析應用數據,若格式符合 MQTT 協議規范則判定為 MQTT 流。此外,部分協議識別器采用 Rust 語言編寫并嵌入 C 語言工程。如需了解更多協議解析器實現,可關注`AppLayerParserRegisterProtocolParsers`函數。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/86240.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/86240.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/86240.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Nginx SSL/TLS協議棧中配置深度解析與實踐指南-優雅草卓伊凡

Nginx SSL/TLS協議棧中配置深度解析與實踐指南-優雅草卓伊凡 引言&#xff1a;SSL/TLS的重要性與Nginx配置挑戰 在當今互聯網環境中&#xff0c;SSL/TLS加密已成為網站安全的基本要求。根據Google透明度報告顯示&#xff0c;截至2023年&#xff0c;全球Chrome瀏覽器加載的網頁…

C++字符串的行輸入

1、字符串的輸入 下面用一個真實的示例來進行演示&#xff1a; #include<iostream> #include<string>int main() {using namespace std;const int ArSize 20;char name[ArSize];char dessert[ArSize];cout << "Enter your name:\n";cin >>…

征服分布式系統:阿里云 Linux 多機互聯與資源共享實戰指南

征服分布式系統&#xff1a;阿里云 Linux 多機互聯與資源共享實戰指南 文章目錄 征服分布式系統&#xff1a;阿里云 Linux 多機互聯與資源共享實戰指南一、分布式系統架構概述二、阿里云網絡基礎架構解析三、多機互聯基礎配置1. 環境準備2. 網絡連通性測試3. SSH 密鑰認證配置 …

AI三步診斷心理:比ChatGPT更懂人心

用人工智能(大語言模型)輔助心理治療的研究 解決心理治療中專業人員不足的問題,提出了一種叫“思維診斷”(DoT)的方法,讓AI通過三個步驟來識別患者的“認知扭曲”(也就是負面、不合理的思維模式)。 背景:心理治療的困境 全世界約八分之一的人有心理問題,但心理咨詢師…

C++【生存游戲】開發:荒島往事 第一期

字幕君已上線...... 副字幕君已上線...... 計數君已上線...... 彩色字幕君 ( 花了重金請來的 ) 已上線...... Doge智能系統已上線...... Doge:嗨嗨我又來了&#xff01; 觀眾們......已上線&#xff01;&#xff01;&#xff01;&#xff01;&#xff01; OK LETS GO&am…

k8s強制刪除podpvpvc和nsnamespace

k8s如何強制刪除pod&pv&pvc和ns&namespace方法 namespace、pod、pv、pvc全部處于“Terminating”狀態時&#xff0c;此時的該名稱空間下的所有控制器都已經被刪除了&#xff0c;之所以出現pod、pvc、pv、ns無法刪除&#xff0c;那是因為kubelet 阻塞&#xff0c;有…

Python基礎--4--Python常用代碼示例

1、文件讀寫操作&#xff08;常用于日志處理、數據導入導出&#xff09; 1、代碼示例 &#xff08;1&#xff09;讀取文本文件內容 with open("data.txt", "r", encoding"utf-8") as f:content f.read()print(content)&#xff08;2&#xf…

單項循環鏈表及帶頭指針的鏈表

單項循環鏈表及其帶頭指針的鏈表 對于鏈表我們要仔細深入的學習它&#xff0c;為何呢&#xff0c;因為他是我們在后面學習非線性數據結構的基礎&#xff0c;像后面的樹&#xff0c;圖等結構都是由鏈表演變出來的&#xff0c;所以我們這篇博客繼續探究鏈表 帶頭指針的鏈表 我…

八股文——JAVA基礎:解釋下什么是面向對象?面向對象和面向過程的區別

面向對象和面向過程是編程的不同思想&#xff1a; 面向過程如c語言的編程形式&#xff0c;在編程時定義的是一個方法&#xff0c;然后后續執行只需要關注這個方法的作用&#xff0c;而不會將方法進行抽象&#xff0c;也就是只關注程序執行的過程細節。 面向對象如java&#x…

SuperMap iServer 關閉數據目錄(datacatalog)、地圖打印(webprinting)等服務

背景 漏洞掃描發現有部分低危 web 漏洞&#xff0c;項目又暫未使用數據目錄服務&#xff0c;所以最簡單的方案是直接關閉服務。 查閱文檔發現處理自動化服務可以修改webapps\iserver\WEB-INF\iserver-geoprocessing.xml 的 enable 屬性為 false 關閉&#xff0c;機器學習服務…

PyTorch 張量(Tensors)全面指南:從基礎到實戰

文章目錄 什么是張量&#xff1f;張量初始化方法1. 直接從數據創建2. 從 NumPy 數組轉換3. 基于現有張量創建4. 使用隨機值或常量 張量屬性張量操作設備轉移索引和切片連接張量算術運算單元素張量轉換 原地操作&#xff08;In-place Operations&#xff09;PyTorch 與 NumPy 互…

Maven是什么?

Maven是一個流行的Java項目管理和構建工具&#xff0c;主要用于自動化項目構建、依賴管理和項目文檔生成等工作。以下是對它的簡單介紹&#xff1a; 核心功能 依賴管理&#xff1a;自動管理項目所需的第三方庫&#xff08;如JAR包&#xff09;&#xff0c;通過在配置文件中聲…

etcd教程-快速入門使用(截圖實操)集群搭建 + 原理解釋

大家好&#xff0c;我是此林。 etcd 是一個高可用的鍵值對存儲系統&#xff0c;常用于分布式系統中保存配置、服務發現和協調信息。它是 CNCF 旗下的項目之一&#xff0c;也是 Kubernetes 的核心組件之一&#xff0c;用來存儲集群狀態。 可以說&#xff0c;云原生場景下經常使…

OpenSSL 混合加密

openssl 中文網&#xff1a; https://www.openssl.net.cn/ 目錄 對稱加密特點常見算法案例&#xff08;使用 AES&#xff09; 非對稱加密特點常見算法案例&#xff08;使用 RSA&#xff09; 混合加密場景加密&#xff08;使用 AES&#xff09;解密 總結 對稱加密 特點 加密和解…

AI驅動的DevOps運維與云服務部署自動化

引言 當前&#xff0c;云計算和DevOps實踐讓開發者能夠管理成百上千臺服務器和容器&#xff0c;但隨之而來的運維復雜度也急劇提升。運維工程師經常需要部署多環境應用、維護大規模云主機、排查集群故障等任務。這些任務不僅涉及繁瑣的腳本編寫和命令行操作&#xff0c;還需要對…

Spring Boot動態數據源切換:優雅實現多數據源管理

在復雜的企業應用中&#xff0c;多數據源管理是常見需求。本文將介紹如何基于Spring Boot實現優雅的動態數據源切換方案&#xff0c;通過自定義注解和AOP實現透明化切換。 核心設計思路 通過三層結構實現數據源動態路由&#xff1a; 1. 注解層&#xff1a;聲明式標記數據源 2…

如何挑選一款1588PTP時鐘同步服務器?

在當今數字化程度極高的時代&#xff0c;高精度時間同步對于眾多關鍵領域的高效、穩定運行起著決定性作用。PTP&#xff08;精確時間協議&#xff09;時鐘作為實現高精度時間同步的核心設備&#xff0c;其性能優劣直接關乎系統整體表現。挑選一款合適的 ptp網絡同步時鐘&#x…

Harmony狀態管理 @Local和@Param

深入理解ArkUI中的Param與Local裝飾器 引言 在ArkUI的狀態管理系統中&#xff0c;Param和Local是兩個核心裝飾器&#xff0c;它們分別用于處理組件間的數據傳遞和組件內部狀態管理。本文將詳細介紹這兩個裝飾器的使用場景、特性差異以及最佳實踐。 Param裝飾器&#xff1a;組…

物聯網攝像頭模塊的應用場景

一、智慧城市治理 ?智能交通優化? ?動態信號控制?&#xff1a;杭州部署20萬物聯網攝像頭&#xff0c;實時分析車流密度并聯動1200個紅綠燈&#xff0c;早高峰通行效率提升40%。 ?違規行為識別?&#xff1a;搭載GB/T28181協議的攝像頭AI抓拍交通違章&#xff0c;車牌識…

k8s Ingress、Service配置各樣例大全

目錄 壹、k8s Ingress 樣例大全&#x1f527; 一、基礎路由與 TLS 終止&#x1f504; 二、高級路由控制1. **URL 重寫**&#xff08;適用后端服務路徑與入口路徑不一致&#xff09;2. **多路徑路由到不同服務** &#x1f6a6; 三、流量治理策略1. **金絲雀發布&#xff08;灰度…