制深度解析:校驗(yàn)和驗(yàn)證與連接方向翻轉(zhuǎn))
網(wǎng)絡(luò)安全網(wǎng)絡(luò)IDS【免費(fèi)下載鏈接】zeekZeek is a powerful network analysis framework that is much different from the typical IDS you may know.項(xiàng)目地址https://gitcode.com/gh_mirrors/ze/zeek點(diǎn)擊查看免費(fèi)下載Zeek原 Bro作為一款強(qiáng)大的網(wǎng)絡(luò)分析框架其對連接connection的追蹤與建模貫穿了從底層 C 引擎到 Zeek 腳本層的整個(gè)體系。本文聚焦 Zeek 開發(fā)者文檔 Connection Handling 中的兩大核心主題校驗(yàn)和checksum行為與連接翻轉(zhuǎn)flipping。通過閱讀本文你將理解為何損壞校驗(yàn)和的報(bào)文仍可能出現(xiàn)在conn.log中但計(jì)數(shù)為零、掌握history字段中c/C與^標(biāo)記的底層含義并能從源碼層面解釋 Zeek 如何決定連接的 originator發(fā)起方與 responder響應(yīng)方以及這一決策在分析器樹analyzer tree中的傳遞機(jī)制。一、校驗(yàn)和Checksum行為從直接丟棄到先建連后校驗(yàn)1.1 默認(rèn)行為概覽默認(rèn)情況下Zeek 會忽略絕大多數(shù)攜帶無效校驗(yàn)和的報(bào)文mostly ignore packets that have invalid checksums。這里的關(guān)鍵詞是mostly——不同層的校驗(yàn)和錯(cuò)誤處理方式并不相同IPv4 頭校驗(yàn)和錯(cuò)誤Zeek 產(chǎn)生bad_IP_checksumweird并在連接查找步驟之前直接丟棄該報(bào)文L4 校驗(yàn)和錯(cuò)誤TCP、UDP、ICMP 等自 Zeek 8.2 起Zeek僅在利用潛在損壞的 L4 頭部信息完成連接的查找或創(chuàng)建之后才判斷 L4 校驗(yàn)和是否無效。這一順序差異是理解后續(xù)所有行為的根基L4 校驗(yàn)和錯(cuò)誤的報(bào)文仍然參與了連接查找/創(chuàng)建只是不參與連接的分析與統(tǒng)計(jì)。1.2 源碼鏈路連接查找與校驗(yàn)分離文檔明確指出連接查找實(shí)現(xiàn)在IPBasedAnalyzer::AnalyzePacket()中校驗(yàn)驗(yàn)證則發(fā)生在各協(xié)議專屬分析器的DeliverPacket()中。從源碼結(jié)構(gòu)看這條鏈路清晰可循連接查找在 src/packet_analysis/protocol/ip/IPBasedAnalyzer.cc 的IPBasedAnalyzer::AnalyzePacket()中Zeek 先通過InitConnKey()構(gòu)造連接鍵IPBasedConnKey隨后調(diào)用session_mgr-FindConnection(*key)查找已有連接未找到則調(diào)用NewConn()創(chuàng)建新連接。此時(shí)尚未進(jìn)行任何 L4 校驗(yàn)和驗(yàn)證。IPv4 校驗(yàn)和檢查在更早的 IP 層處理中src/packet_analysis/protocol/ip/IP.cc 會對 IPv4 頭校驗(yàn)和進(jìn)行檢查——當(dāng)! packet-l3_checksummed ! ignore_checksums ... in_cksum(...) ! 0xffff時(shí)產(chǎn)生Weird(bad_IP_checksum, packet)并直接返回false報(bào)文被丟棄不會進(jìn)入連接查找階段。這與文檔描述的IPv4 校驗(yàn)和錯(cuò)誤在連接查找前丟棄完全一致。L4 校驗(yàn)和驗(yàn)證連接建立后才在各協(xié)議層驗(yàn)證 L4 校驗(yàn)和TCPTCPAnalyzer::ValidateChecksum()src/packet_analysis/protocol/tcp/TCP.cc在滿足! l4_checksummed ! ignore_checksums ! GetIgnoreChecksumsNets()-Contains(ip-IPHeaderSrcAddr())等條件時(shí)調(diào)用endpoint-ValidChecksum()驗(yàn)證失敗則產(chǎn)生bad_TCP_checksumweird 并調(diào)用endpoint-ChecksumError()UDPUDPAnalyzer::DeliverPacket()src/packet_analysis/protocol/udp/UDP.cc中先調(diào)用adapter-DeliverPacket(...)把報(bào)文交給會話適配器保證packet_contents等事件仍能拿到數(shù)據(jù)隨后才進(jìn)行校驗(yàn)和驗(yàn)證失敗時(shí)調(diào)用adapter-HandleBadChecksum(is_orig)src/packet_analysis/protocol/udp/UDPSessionAdapter.cc該函數(shù)產(chǎn)生bad_UDP_checksumweird 并記錄歷史同時(shí)TapPacket(pkt, PacketAction::Skip, SkipReason::BadChecksum)將報(bào)文標(biāo)記為跳過。值得注意的細(xì)節(jié)UDP 分析器中存在針對 VXLAN 的特殊處理——當(dāng)目的端口是已知 VXLAN 端口且校驗(yàn)和字段為零時(shí)跳過校驗(yàn)src/packet_analysis/protocol/udp/UDP.cc這體現(xiàn)了校驗(yàn)和可選協(xié)議的現(xiàn)實(shí)考量。1.3 校驗(yàn)和錯(cuò)誤對統(tǒng)計(jì)與歷史的雙重影響校驗(yàn)和驗(yàn)證失敗的關(guān)鍵后果是不計(jì)入連接統(tǒng)計(jì)無效校驗(yàn)和的報(bào)文不會被計(jì)入連接的orig_pkts或resp_pkts也不會傳遞給連接的協(xié)議分析器。寫入歷史字段報(bào)文的cresponder 方向的小寫或Coriginator 方向的大寫被以**對數(shù)方式logarithmic fashion**追加到連接的 history 字段。關(guān)于history字段的語義scripts/base/protocols/conn/main.zeek 中給出了權(quán)威說明c表示 packet with a bad checksum (applies to UDP too)來自 originator 的事件記為大寫來自 responder 的記為小寫c/g/t/w等類型采用對數(shù)記錄方式——第二次出現(xiàn)代表該事件至少發(fā)生了 10 次第三次代表 100 次依此類推。其底層實(shí)現(xiàn)為Session::ScaledHistoryEntry()src/session/Session.cc內(nèi)部維護(hù)一個(gè)計(jì)數(shù)器與縮放閾值每當(dāng)counter scaling_threshold時(shí)寫入歷史字符并將閾值乘以縮放基數(shù)默認(rèn) 10實(shí)現(xiàn)以對數(shù)步長壓縮高頻事件的效果。TCP 端點(diǎn)的ChecksumError()src/analyzer/protocol/tcp/TCP_Endpoint.cc與 UDP 會話適配器的HandleBadChecksum()src/packet_analysis/protocol/udp/UDPSessionAdapter.cc正是通過該機(jī)制分別寫入C/c歷史。當(dāng)跨越閾值時(shí)還會觸發(fā)tcp_multiple_checksum_errorssrc/analyzer/protocol/tcp/events.bif或udp_multiple_checksum_errorssrc/packet_analysis/protocol/udp/events.bif事件供腳本層響應(yīng)。1.4 實(shí)戰(zhàn)驗(yàn)證零包計(jì)數(shù)的 conn.log文檔給出了兩個(gè)可直接復(fù)現(xiàn)的實(shí)驗(yàn)命令。所用抓包文件均存在于本倉庫的 testing/btest/Traces 目錄下Traces/tcp/syn-bad.pcap、Traces/dns/dns-corrupt.pcap其全局路徑分別為 testing/btest/Traces/tcp/syn-bad.pcap 與 testing/btest/Traces/dns/dns-corrupt.pcap。TCP 場景回放壞校驗(yàn)和的 SYN 報(bào)文以 JSON 格式輸出conn.log# zeek -D -b -r Traces/tcp/syn-bad.pcap base/protocols/conn LogAscii::use_jsonT # jq conn.log { ts: 1362692526.869344, uid: CJKFoj4bpHEhTeaRoj, id.orig_h: 141.142.228.5, id.orig_p: 59856, id.resp_h: 192.150.187.43, id.resp_p: 80, proto: tcp, conn_state: OTH, local_orig: false, local_resp: false, missed_bytes: 0, history: C, orig_pkts: 0, orig_ip_bytes: 0, resp_pkts: 0, resp_ip_bytes: 0, ip_proto: 6 }UDP 場景回放壞校驗(yàn)和的 DNS 報(bào)文# zeek -b -r Traces/dns/dns-corrupt.pcap base/protocols/conn LogAscii::use_jsonT # jq conn.log { ts: 1777450586.006844, uid: CJKFoj4bpHEhTeaRoj, id.orig_h: 192.168.0.109, id.orig_p: 34357, id.resp_h: 8.8.8.8, id.resp_p: 53, proto: udp, conn_state: OTH, local_orig: true, local_resp: false, missed_bytes: 0, history: Cc, orig_pkts: 0, orig_ip_bytes: 0, resp_pkts: 0, resp_ip_bytes: 0, ip_proto: 17 }兩個(gè)示例的history字段分別為C與Cc而orig_pkts、resp_pkts均為 0。這說明校驗(yàn)和錯(cuò)誤的報(bào)文成功創(chuàng)建/匹配了連接并留下歷史痕跡但從未被計(jì)入任何方向的數(shù)據(jù)包統(tǒng)計(jì)——這正是先建連后校驗(yàn)設(shè)計(jì)的最直接體現(xiàn)。conn_state為OTH也符合預(yù)期由于沒有有效數(shù)據(jù)包參與狀態(tài)機(jī)推進(jìn)連接停留在無狀態(tài)階段。從conn.log的字段定義看scripts/base/protocols/conn/main.zeekorig_pkts、orig_ip_bytes、resp_pkts、resp_ip_bytes均標(biāo)注 Only set ifuse_conn_size_analyzer T即由ConnSize_Analyzer分析器見下文負(fù)責(zé)填充。相關(guān)討論可追溯至 Zeek 的 issue #5277bad checksum處理機(jī)制變更。1.5 相關(guān)配置項(xiàng)校驗(yàn)和驗(yàn)證并非無條件執(zhí)行Zeek 提供了兩個(gè)腳本層開關(guān)定義于 scripts/base/init-bare.zeekignore_checksums: bool默認(rèn)F置為T可全局跳過所有校驗(yàn)和驗(yàn)證ignore_checksums_nets: set[subnet]默認(rèn)空集指定網(wǎng)段的報(bào)文跳過校驗(yàn)和驗(yàn)證適用于已知存在網(wǎng)卡 offload 問題的網(wǎng)絡(luò)環(huán)境。這兩個(gè)開關(guān)在 src/packet_analysis/protocol/ip/IPBasedAnalyzer.cc 中被加載GetIgnoreChecksumsNets()并被 TCP/UDP 校驗(yàn)和驗(yàn)證邏輯引用scripts/base/packet-protocols/ip/main.zeek 中還有對應(yīng)的選項(xiàng)變更處理器運(yùn)行時(shí)修改ignore_checksums_nets會即時(shí)同步到底層。二、連接翻轉(zhuǎn)Flippingoriginator 與 responder 的角色再定義2.1 核心概念誰先發(fā)誰就是 originatorZeek 以originator發(fā)起方與responder響應(yīng)方的雙端模型描述連接。這一概念在 Zeek 腳本層體現(xiàn)為is_orig: bool事件參數(shù)在底層 C API 中體現(xiàn)為Connection實(shí)例的訪問器——如OrigAddr()/RespAddr()、OrigPort()/RespPort()。通常情況下連接的第一個(gè)報(bào)文決定哪一端是 originator、哪一端是 responder。但存在一個(gè)特例當(dāng)首包的源端口位于likely_server_ports集合中時(shí)意味著源端口像是一個(gè)服務(wù)端端口例如 80、443、53Zeek 會翻轉(zhuǎn)這一判定并在連接的 history 中追加^caret標(biāo)記。likely_server_ports定義于 scripts/base/init-bare.zeek其典型語義是該端口上更可能是服務(wù)端scripts/base/frameworks/analyzer/main.zeek 中還會自動將各分析器聲明的server_ports合并進(jìn)likely_server_ports。2.2 源碼視角翻轉(zhuǎn)發(fā)生在哪里連接翻轉(zhuǎn)的判斷發(fā)生于IPBasedAnalyzer::NewConn()src/packet_analysis/protocol/ip/IPBasedAnalyzer.cc調(diào)用虛函數(shù)WantConnection(src_p, dst_p, payload, flip)詢問各協(xié)議分析器是否接受該連接以及是否需要翻轉(zhuǎn)角色各協(xié)議通過IsLikelyServerPort()src/packet_analysis/protocol/ip/IPBasedAnalyzer.cc查詢likely_server_ports表該表被緩存以加速查找例如 UDP 分析器的WantConnection()src/packet_analysis/protocol/udp/UDP.cc即實(shí)現(xiàn)為flip_roles IsLikelyServerPort(src_port) ! IsLikelyServerPort(dst_port)若flip為真且響應(yīng)地址不是廣播地址! conn-RespAddr().IsBroadcast()則調(diào)用conn-FlipRoles()。翻轉(zhuǎn)動作的核心實(shí)現(xiàn)在Connection::FlipRoles()src/Conn.cc它依次交換orig_addr/resp_addr、orig_port/resp_port以及 L2 地址、流標(biāo)簽等端點(diǎn)屬性將conn_val腳本層的connection記錄中的id記錄與端點(diǎn)字段同步交換調(diào)用key-FlipRoles()讓連接鍵IPBasedConnKey同步更新調(diào)用adapter-FlipRoles()遞歸翻轉(zhuǎn)會話適配器通過analyzer_mgr-ApplyScheduledAnalyzers(this)重新調(diào)度分析器AddHistory(^)在 history 中記錄翻轉(zhuǎn)標(biāo)記觸發(fā)connection_flipped事件若注冊了該事件處理器。值得一提的是IPBasedConnKey類本身就持有flipped成員并提供FlipRoles()APIsrc/packet_analysis/protocol/ip/conn_key/IPBasedConnKey.cc在InitTuple()中若addr_port_canon_lt(...)判定源端小于目的端按規(guī)范序比較則按原樣存儲并將flipped置為false否則交換存儲并置為true。SrcAddr()/DstAddr()、SrcPort()/DstPort()的取值因此會依據(jù)flipped標(biāo)志動態(tài)決定src/packet_analysis/protocol/ip/conn_key/IPBasedConnKey.h。2.3 翻轉(zhuǎn)如何滲透各層分析器樹的遞歸 FlipRoles翻轉(zhuǎn)并非只發(fā)生在連接層——它需要滲透到整個(gè)分析器樹analyzer tree。文檔強(qiáng)調(diào)the Analyzer API offers a virtualFlipRoles()method that is executed recursively on the analyzer tree when endpoint flipping happens. All analyzers have to update their internal state upon such an event.這一機(jī)制在 src/analyzer/Analyzer.cc 中實(shí)現(xiàn)Analyzer::FlipRoles()會對其子分析器遞歸調(diào)用FlipRoles()。以文檔舉例的ConnSize_Analyzer追蹤各方向數(shù)據(jù)包與字節(jié)計(jì)數(shù)的分析器為例其FlipRoles()src/analyzer/protocol/conn-size/ConnSize.cc在調(diào)用基類版本后交換orig_bytes/resp_bytes與orig_pkts/resp_pkts確保后續(xù)DeliverPacket()調(diào)用中is_orig語義反轉(zhuǎn)后計(jì)數(shù)仍然正確。該分析器正是conn.log中orig_pkts、resp_pkts、orig_ip_bytes、resp_ip_bytes字段的填充者src/analyzer/protocol/conn-size/ConnSize.cc。類似的還有HTTP_Analyzer::FlipRoles()src/analyzer/protocol/http/HTTP.cc——當(dāng)翻轉(zhuǎn)發(fā)生在協(xié)議升級之后時(shí)還需處理其內(nèi)部狀態(tài)。此外分析器并非只能在連接建立時(shí)觸發(fā)翻轉(zhuǎn)例如 DNS 分析器在解析首個(gè)消息時(shí)發(fā)現(xiàn)QR位表明方向與預(yù)期相反會直接調(diào)用analyzer-Conn()-FlipRoles()src/analyzer/protocol/dns/DNS.cc——這屬于運(yùn)行時(shí)、由應(yīng)用層邏輯驅(qū)動的翻轉(zhuǎn)。2.4 第二包翻轉(zhuǎn)與 stale is_orig 問題文檔指出翻轉(zhuǎn)通常發(fā)生在連接第一個(gè)包處理之前但較新的 Zeek 版本對應(yīng) PR #2191已支持在第二個(gè)包時(shí)進(jìn)行翻轉(zhuǎn)。從技術(shù)上講任何分析器或邏輯都可以在任何時(shí)刻觸發(fā)翻轉(zhuǎn)——但這會帶來一個(gè)棘手問題an in-flightForwardStream()orForwardPacket()invocation on a connections analyzer tree ends-up using a staleis_origparameter.也就是說當(dāng)一次ForwardStream()/ForwardPacket()調(diào)用正在分析器樹上進(jìn)行時(shí)如果某個(gè)分析器觸發(fā)了翻轉(zhuǎn)那么隨后對分析器樹的DeliverPacket()調(diào)用將使用過期的is_orig棧變量。文檔中觀察到的真實(shí)案例即ConnSize_Analyzer它在TCPSessionAdapter::Process()調(diào)用之后被訪問若Process()翻轉(zhuǎn)了連接ConnSize_Analyzer的DeliverPacket()會拿到錯(cuò)誤的is_orig導(dǎo)致單個(gè)包被錯(cuò)誤記賬。這一論述在源碼層面成立DeliverPacket()的is_orig作為參數(shù)從調(diào)用鏈逐層傳入而ConnSize_Analyzer::DeliverPacket()src/analyzer/protocol/conn-size/ConnSize.cc直接依賴is_orig決定累加到orig_*還是resp_*計(jì)數(shù)器期間并不重新查詢連接的當(dāng)前端點(diǎn)角色——因此一旦翻轉(zhuǎn)發(fā)生在傳遞路徑中途就會產(chǎn)生上述賬目偏差。2.5 未來展望從 originator/responder 到 left/right文檔最后提出了一項(xiàng)頗有深度的架構(gòu)展望未來 Zeek 可以考慮將最底層設(shè)計(jì)為對 originator/responder 概念無感知——即始終以確定性規(guī)則如規(guī)范化排序命名端點(diǎn)例如left和right而把 originator/responder 的語義上移到更高層實(shí)現(xiàn)。依據(jù)在于IPBasedConnKey類當(dāng)前已持有flipped成員并暴露FlipRoles()APIsrc/packet_analysis/protocol/ip/conn_key/IPBasedConnKey.h這意味著原始連接追蹤層已經(jīng)隱式承擔(dān)了角色方向的邏輯。文檔認(rèn)為這并不合理——純連接追蹤層不應(yīng)了解 originator/responder 概念因?yàn)檫@會引入相當(dāng)可觀的復(fù)雜度。這一構(gòu)想可以理解為連接鍵層只負(fù)責(zé)穩(wěn)定、可復(fù)現(xiàn)地標(biāo)識一條流而方向語義誰主動、誰被動交由上層分析框架按需推導(dǎo)。三、總結(jié)與排查實(shí)踐建議回到實(shí)戰(zhàn)層面理解校驗(yàn)和與翻轉(zhuǎn)機(jī)制有助于更準(zhǔn)確地解讀conn.log看到orig_pkts/resp_pkts全為 0 但 history 含c/C不要驚訝這是 Zeek 8.2 的預(yù)期行為——壞校驗(yàn)和報(bào)文參與了連接創(chuàng)建/查找與歷史記錄但未參與計(jì)數(shù)與分析??山Y(jié)合bad_TCP_checksum、bad_UDP_checksumweird 進(jìn)一步定位看到 history 中的^表示 Zeek 根據(jù)likely_server_ports或應(yīng)用層邏輯翻轉(zhuǎn)了連接方向腳本層可通過connection_flipped事件定義于 src/Conn.cc 的使用處感知并做出響應(yīng)排查網(wǎng)絡(luò)環(huán)境問題若因網(wǎng)卡 offload 導(dǎo)致大量校驗(yàn)和錯(cuò)誤可評估設(shè)置ignore_checksums_nets或ignore_checksums選項(xiàng)避免噪聲影響分析注意計(jì)數(shù)與字節(jié)字段的依賴orig_pkts等字段僅在啟用use_conn_size_analyzer時(shí)由ConnSize_Analyzer填充見 scripts/base/protocols/conn/main.zeek解讀日志前應(yīng)先確認(rèn)該開關(guān)狀態(tài)。更多實(shí)現(xiàn)細(xì)節(jié)可進(jìn)一步閱讀 src/packet_analysis/protocol/ip/IPBasedAnalyzer.cc、src/packet_analysis/protocol/tcp/TCP.cc、src/packet_analysis/protocol/udp/UDP.cc 與 src/Conn.cc以及 scripts/base/protocols/conn/main.zeek 中的history字段語義說明。贊分享網(wǎng)絡(luò)安全網(wǎng)絡(luò)IDS【免費(fèi)下載鏈接】zeekZeek is a powerful network analysis framework that is much different from the typical IDS you may know.項(xiàng)目地址https://gitcode.com/gh_mirrors/ze/zeek點(diǎn)擊查看免費(fèi)下載相關(guān)推薦Apache Arrow R 包 dplyr 連接操作join by 連接鍵校驗(yàn)與錯(cuò)誤處理機(jī)制深度解析Apache Arrow R 包 dplyr 連接操作 join by 連接鍵校驗(yàn)與錯(cuò)誤處理機(jī)制深度解析 本篇文章以 Apache Arrow R 包 ar數(shù)據(jù)工程大數(shù)據(jù)序列化數(shù)據(jù)分析COLMAP三維重建終極指南從照片到3D模型的魔法之旅 ?COLMAP三維重建終極指南從照片到3D模型的魔法之旅 ? 你是否曾經(jīng)想過如何將手機(jī)里的一堆普通照片變成精美的三維模型 想象一下通過簡單的拍照就能重計(jì)算機(jī)視覺圖形學(xué)圖像處理Activepieces 連接-組件綁定強(qiáng)制校驗(yàn)引擎內(nèi)執(zhí)行的連接歸屬校驗(yàn)機(jī)制與配置實(shí)戰(zhàn)Activepieces 連接 組件綁定強(qiáng)制校驗(yàn)引擎內(nèi)執(zhí)行的連接歸屬校驗(yàn)機(jī)制與配置實(shí)戰(zhàn) 導(dǎo)讀 在 Activepieces 的自動化流程中一個(gè)步驟Step工作流自動化低代碼AI 應(yīng)用人工智能AI AgentMCP 服務(wù)后端前端創(chuàng)作聲明:本文部分內(nèi)容由AI輔助生成(AIGC),僅供參考