尧图网络科技YAOTU DIGITAL 获取报价
获取报价
首页 / 资讯中心 / 文章详情

Zeek 连接处理机制深度解析:校验和验证与连接方向翻转

发布时间:2026/9/28 20:52:29

资讯中心
01
ARTICLE

Zeek 连接处理机制深度解析:校验和验证与连接方向翻转

Zeek 连接处理机制深度解析:校验和验证与连接方向翻转
网络安全网络IDS【免费下载链接】zeekZeek is a powerful network analysis framework that is much different from the typical IDS you may know.项目地址https://gitcode.com/gh_mirrors/ze/zeek点击查看免费下载Zeek原 Bro作为一款强大的网络分析框架其对连接connection的追踪与建模贯穿了从底层 C 引擎到 Zeek 脚本层的整个体系。本文聚焦 Zeek 开发者文档 Connection Handling 中的两大核心主题校验和checksum行为与连接翻转flipping。通过阅读本文你将理解为何损坏校验和的报文仍可能出现在conn.log中但计数为零、掌握history字段中c/C与^标记的底层含义并能从源码层面解释 Zeek 如何决定连接的 originator发起方与 responder响应方以及这一决策在分析器树analyzer tree中的传递机制。一、校验和Checksum行为从直接丢弃到先建连后校验1.1 默认行为概览默认情况下Zeek 会忽略绝大多数携带无效校验和的报文mostly ignore packets that have invalid checksums。这里的关键词是mostly——不同层的校验和错误处理方式并不相同IPv4 头校验和错误Zeek 产生bad_IP_checksumweird并在连接查找步骤之前直接丢弃该报文L4 校验和错误TCP、UDP、ICMP 等自 Zeek 8.2 起Zeek仅在利用潜在损坏的 L4 头部信息完成连接的查找或创建之后才判断 L4 校验和是否无效。这一顺序差异是理解后续所有行为的根基L4 校验和错误的报文仍然参与了连接查找/创建只是不参与连接的分析与统计。1.2 源码链路连接查找与校验分离文档明确指出连接查找实现在IPBasedAnalyzer::AnalyzePacket()中校验验证则发生在各协议专属分析器的DeliverPacket()中。从源码结构看这条链路清晰可循连接查找在 src/packet_analysis/protocol/ip/IPBasedAnalyzer.cc 的IPBasedAnalyzer::AnalyzePacket()中Zeek 先通过InitConnKey()构造连接键IPBasedConnKey随后调用session_mgr-FindConnection(*key)查找已有连接未找到则调用NewConn()创建新连接。此时尚未进行任何 L4 校验和验证。IPv4 校验和检查在更早的 IP 层处理中src/packet_analysis/protocol/ip/IP.cc 会对 IPv4 头校验和进行检查——当! packet-l3_checksummed ! ignore_checksums ... in_cksum(...) ! 0xffff时产生Weird(bad_IP_checksum, packet)并直接返回false报文被丢弃不会进入连接查找阶段。这与文档描述的IPv4 校验和错误在连接查找前丢弃完全一致。L4 校验和验证连接建立后才在各协议层验证 L4 校验和TCPTCPAnalyzer::ValidateChecksum()src/packet_analysis/protocol/tcp/TCP.cc在满足! l4_checksummed ! ignore_checksums ! GetIgnoreChecksumsNets()-Contains(ip-IPHeaderSrcAddr())等条件时调用endpoint-ValidChecksum()验证失败则产生bad_TCP_checksumweird 并调用endpoint-ChecksumError()UDPUDPAnalyzer::DeliverPacket()src/packet_analysis/protocol/udp/UDP.cc中先调用adapter-DeliverPacket(...)把报文交给会话适配器保证packet_contents等事件仍能拿到数据随后才进行校验和验证失败时调用adapter-HandleBadChecksum(is_orig)src/packet_analysis/protocol/udp/UDPSessionAdapter.cc该函数产生bad_UDP_checksumweird 并记录历史同时TapPacket(pkt, PacketAction::Skip, SkipReason::BadChecksum)将报文标记为跳过。值得注意的细节UDP 分析器中存在针对 VXLAN 的特殊处理——当目的端口是已知 VXLAN 端口且校验和字段为零时跳过校验src/packet_analysis/protocol/udp/UDP.cc这体现了校验和可选协议的现实考量。1.3 校验和错误对统计与历史的双重影响校验和验证失败的关键后果是不计入连接统计无效校验和的报文不会被计入连接的orig_pkts或resp_pkts也不会传递给连接的协议分析器。写入历史字段报文的cresponder 方向的小写或Coriginator 方向的大写被以**对数方式logarithmic fashion**追加到连接的 history 字段。关于history字段的语义scripts/base/protocols/conn/main.zeek 中给出了权威说明c表示 packet with a bad checksum (applies to UDP too)来自 originator 的事件记为大写来自 responder 的记为小写c/g/t/w等类型采用对数记录方式——第二次出现代表该事件至少发生了 10 次第三次代表 100 次依此类推。其底层实现为Session::ScaledHistoryEntry()src/session/Session.cc内部维护一个计数器与缩放阈值每当counter scaling_threshold时写入历史字符并将阈值乘以缩放基数默认 10实现以对数步长压缩高频事件的效果。TCP 端点的ChecksumError()src/analyzer/protocol/tcp/TCP_Endpoint.cc与 UDP 会话适配器的HandleBadChecksum()src/packet_analysis/protocol/udp/UDPSessionAdapter.cc正是通过该机制分别写入C/c历史。当跨越阈值时还会触发tcp_multiple_checksum_errorssrc/analyzer/protocol/tcp/events.bif或udp_multiple_checksum_errorssrc/packet_analysis/protocol/udp/events.bif事件供脚本层响应。1.4 实战验证零包计数的 conn.log文档给出了两个可直接复现的实验命令。所用抓包文件均存在于本仓库的 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 场景回放坏校验和的 SYN 报文以 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 场景回放坏校验和的 DNS 报文# 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 }两个示例的history字段分别为C与Cc而orig_pkts、resp_pkts均为 0。这说明校验和错误的报文成功创建/匹配了连接并留下历史痕迹但从未被计入任何方向的数据包统计——这正是先建连后校验设计的最直接体现。conn_state为OTH也符合预期由于没有有效数据包参与状态机推进连接停留在无状态阶段。从conn.log的字段定义看scripts/base/protocols/conn/main.zeekorig_pkts、orig_ip_bytes、resp_pkts、resp_ip_bytes均标注 Only set ifuse_conn_size_analyzer T即由ConnSize_Analyzer分析器见下文负责填充。相关讨论可追溯至 Zeek 的 issue #5277bad checksum处理机制变更。1.5 相关配置项校验和验证并非无条件执行Zeek 提供了两个脚本层开关定义于 scripts/base/init-bare.zeekignore_checksums: bool默认F置为T可全局跳过所有校验和验证ignore_checksums_nets: set[subnet]默认空集指定网段的报文跳过校验和验证适用于已知存在网卡 offload 问题的网络环境。这两个开关在 src/packet_analysis/protocol/ip/IPBasedAnalyzer.cc 中被加载GetIgnoreChecksumsNets()并被 TCP/UDP 校验和验证逻辑引用scripts/base/packet-protocols/ip/main.zeek 中还有对应的选项变更处理器运行时修改ignore_checksums_nets会即时同步到底层。二、连接翻转Flippingoriginator 与 responder 的角色再定义2.1 核心概念谁先发谁就是 originatorZeek 以originator发起方与responder响应方的双端模型描述连接。这一概念在 Zeek 脚本层体现为is_orig: bool事件参数在底层 C API 中体现为Connection实例的访问器——如OrigAddr()/RespAddr()、OrigPort()/RespPort()。通常情况下连接的第一个报文决定哪一端是 originator、哪一端是 responder。但存在一个特例当首包的源端口位于likely_server_ports集合中时意味着源端口像是一个服务端端口例如 80、443、53Zeek 会翻转这一判定并在连接的 history 中追加^caret标记。likely_server_ports定义于 scripts/base/init-bare.zeek其典型语义是该端口上更可能是服务端scripts/base/frameworks/analyzer/main.zeek 中还会自动将各分析器声明的server_ports合并进likely_server_ports。2.2 源码视角翻转发生在哪里连接翻转的判断发生于IPBasedAnalyzer::NewConn()src/packet_analysis/protocol/ip/IPBasedAnalyzer.cc调用虚函数WantConnection(src_p, dst_p, payload, flip)询问各协议分析器是否接受该连接以及是否需要翻转角色各协议通过IsLikelyServerPort()src/packet_analysis/protocol/ip/IPBasedAnalyzer.cc查询likely_server_ports表该表被缓存以加速查找例如 UDP 分析器的WantConnection()src/packet_analysis/protocol/udp/UDP.cc即实现为flip_roles IsLikelyServerPort(src_port) ! IsLikelyServerPort(dst_port)若flip为真且响应地址不是广播地址! conn-RespAddr().IsBroadcast()则调用conn-FlipRoles()。翻转动作的核心实现在Connection::FlipRoles()src/Conn.cc它依次交换orig_addr/resp_addr、orig_port/resp_port以及 L2 地址、流标签等端点属性将conn_val脚本层的connection记录中的id记录与端点字段同步交换调用key-FlipRoles()让连接键IPBasedConnKey同步更新调用adapter-FlipRoles()递归翻转会话适配器通过analyzer_mgr-ApplyScheduledAnalyzers(this)重新调度分析器AddHistory(^)在 history 中记录翻转标记触发connection_flipped事件若注册了该事件处理器。值得一提的是IPBasedConnKey类本身就持有flipped成员并提供FlipRoles()APIsrc/packet_analysis/protocol/ip/conn_key/IPBasedConnKey.cc在InitTuple()中若addr_port_canon_lt(...)判定源端小于目的端按规范序比较则按原样存储并将flipped置为false否则交换存储并置为true。SrcAddr()/DstAddr()、SrcPort()/DstPort()的取值因此会依据flipped标志动态决定src/packet_analysis/protocol/ip/conn_key/IPBasedConnKey.h。2.3 翻转如何渗透各层分析器树的递归 FlipRoles翻转并非只发生在连接层——它需要渗透到整个分析器树analyzer tree。文档强调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.这一机制在 src/analyzer/Analyzer.cc 中实现Analyzer::FlipRoles()会对其子分析器递归调用FlipRoles()。以文档举例的ConnSize_Analyzer追踪各方向数据包与字节计数的分析器为例其FlipRoles()src/analyzer/protocol/conn-size/ConnSize.cc在调用基类版本后交换orig_bytes/resp_bytes与orig_pkts/resp_pkts确保后续DeliverPacket()调用中is_orig语义反转后计数仍然正确。该分析器正是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——当翻转发生在协议升级之后时还需处理其内部状态。此外分析器并非只能在连接建立时触发翻转例如 DNS 分析器在解析首个消息时发现QR位表明方向与预期相反会直接调用analyzer-Conn()-FlipRoles()src/analyzer/protocol/dns/DNS.cc——这属于运行时、由应用层逻辑驱动的翻转。2.4 第二包翻转与 stale is_orig 问题文档指出翻转通常发生在连接第一个包处理之前但较新的 Zeek 版本对应 PR #2191已支持在第二个包时进行翻转。从技术上讲任何分析器或逻辑都可以在任何时刻触发翻转——但这会带来一个棘手问题an in-flightForwardStream()orForwardPacket()invocation on a connections analyzer tree ends-up using a staleis_origparameter.也就是说当一次ForwardStream()/ForwardPacket()调用正在分析器树上进行时如果某个分析器触发了翻转那么随后对分析器树的DeliverPacket()调用将使用过期的is_orig栈变量。文档中观察到的真实案例即ConnSize_Analyzer它在TCPSessionAdapter::Process()调用之后被访问若Process()翻转了连接ConnSize_Analyzer的DeliverPacket()会拿到错误的is_orig导致单个包被错误记账。这一论述在源码层面成立DeliverPacket()的is_orig作为参数从调用链逐层传入而ConnSize_Analyzer::DeliverPacket()src/analyzer/protocol/conn-size/ConnSize.cc直接依赖is_orig决定累加到orig_*还是resp_*计数器期间并不重新查询连接的当前端点角色——因此一旦翻转发生在传递路径中途就会产生上述账目偏差。2.5 未来展望从 originator/responder 到 left/right文档最后提出了一项颇有深度的架构展望未来 Zeek 可以考虑将最底层设计为对 originator/responder 概念无感知——即始终以确定性规则如规范化排序命名端点例如left和right而把 originator/responder 的语义上移到更高层实现。依据在于IPBasedConnKey类当前已持有flipped成员并暴露FlipRoles()APIsrc/packet_analysis/protocol/ip/conn_key/IPBasedConnKey.h这意味着原始连接追踪层已经隐式承担了角色方向的逻辑。文档认为这并不合理——纯连接追踪层不应了解 originator/responder 概念因为这会引入相当可观的复杂度。这一构想可以理解为连接键层只负责稳定、可复现地标识一条流而方向语义谁主动、谁被动交由上层分析框架按需推导。三、总结与排查实践建议回到实战层面理解校验和与翻转机制有助于更准确地解读conn.log看到orig_pkts/resp_pkts全为 0 但 history 含c/C不要惊讶这是 Zeek 8.2 的预期行为——坏校验和报文参与了连接创建/查找与历史记录但未参与计数与分析。可结合bad_TCP_checksum、bad_UDP_checksumweird 进一步定位看到 history 中的^表示 Zeek 根据likely_server_ports或应用层逻辑翻转了连接方向脚本层可通过connection_flipped事件定义于 src/Conn.cc 的使用处感知并做出响应排查网络环境问题若因网卡 offload 导致大量校验和错误可评估设置ignore_checksums_nets或ignore_checksums选项避免噪声影响分析注意计数与字节字段的依赖orig_pkts等字段仅在启用use_conn_size_analyzer时由ConnSize_Analyzer填充见 scripts/base/protocols/conn/main.zeek解读日志前应先确认该开关状态。更多实现细节可进一步阅读 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字段语义说明。赞分享网络安全网络IDS【免费下载链接】zeekZeek is a powerful network analysis framework that is much different from the typical IDS you may know.项目地址https://gitcode.com/gh_mirrors/ze/zeek点击查看免费下载相关推荐Apache Arrow R 包 dplyr 连接操作join by 连接键校验与错误处理机制深度解析Apache Arrow R 包 dplyr 连接操作 join by 连接键校验与错误处理机制深度解析 本篇文章以 Apache Arrow R 包 ar数据工程大数据序列化数据分析COLMAP三维重建终极指南从照片到3D模型的魔法之旅 ✨COLMAP三维重建终极指南从照片到3D模型的魔法之旅 ✨ 你是否曾经想过如何将手机里的一堆普通照片变成精美的三维模型 想象一下通过简单的拍照就能重计算机视觉图形学图像处理Activepieces 连接-组件绑定强制校验引擎内执行的连接归属校验机制与配置实战Activepieces 连接 组件绑定强制校验引擎内执行的连接归属校验机制与配置实战 导读 在 Activepieces 的自动化流程中一个步骤Step工作流自动化低代码AI 应用人工智能AI AgentMCP 服务后端前端创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
02
RELATED NEWS

相关资讯

更多网站建设与数字化升级内容

03
WHY YAOTU

想打造同款高转化官网?

懂行业、懂生意,从建站到增长一站式陪跑

◈

场景化定制

不做模板站,围绕你的业务场景量身设计,小众不撞款。

◐

营销型架构

以转化目标组织内容与路径,让官网真正带来询盘。

▲

全周期服务

设计、开发、运营、运维一体,上线只是开始。

免费获取你的建站方案

留下需求,专属顾问 24 小时内为你输出方案建议。