ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Zeek Analyzer 框架完全指南:动态管理协议分析器、注册端口与 DPD 违规处理

Zeek Analyzer 框架完全指南:动态管理协议分析器、注册端口与 DPD 违规处理 网络安全网络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 内置的base/frameworks/analyzer框架展开系统讲解如何动态启用/禁用协议分析器protocol analyzer、注册知名端口well-known ports、通过 DPD 动态协议检测处理违规以及将分析器违规写入analyzer.log。读者读完后将掌握Analyzer::enable_analyzer、Analyzer::register_for_ports、Analyzer::disable_all、DPD::ignore_violations等核心 API 的完整用法并理解其背后的 C 实现原理可直接用于编写高性能、可控的分析策略脚本。一、框架定位为什么需要 Analyzer 框架Zeek 的协议分析器负责解析网络流量中的具体协议如 HTTP、DNS、SSL。在默认配置下Zeek 会按端口映射和动态协议检测Dynamic Protocol DetectionDPD自动为新建连接挂载合适的分析器。但很多实际场景要求对分析器进行显式控制出于性能或隐私考虑只想对某些协议做分析其余一概关闭某些协议使用非常规端口需要把自定义端口注册给分析器协议违规protocol violation发生时希望自动禁用出错的分析器并记录日志提前获知某台主机即将产生特定协议流量希望预先调度分析器。base/frameworks/analyzer正是为此设计的统一入口。其入口脚本 scripts/base/frameworks/analyzer/main.zeek 说明“The analyzer framework allows to dynamically enable or disable analyzers, as well as to manage the well-known ports which automatically activate a particular analyzer for new connections.”即动态启用/禁用分析器 管理自动激活分析器的知名端口。框架的加载链非常简洁scripts/base/frameworks/analyzer/load.zeek 依次加载三个模块load ./main load ./dpd load ./logging对应三个职责模块职责main.zeek核心 API启用/禁用分析器、注册端口、调度分析器、生成 BPF 过滤器dpd.zeek协议违规处理违规时移除分析器维护conn.log的 service 字段logging.zeek把分析器违规写入analyzer.log二、分析器标识Analyzer::Tag 与 AllAnalyzers::Tag框架文档指出协议分析器由Analyzer::Tag类型的唯一标签标识例如Analyzer::ANALYZER_HTTP。这些标签由分析器自身内部定义并在各自分析器的说明文档中连同其产生的事件一起记载。更关键的是所有分析器标签还会被并入一个全局的AllAnalyzers::Tag枚举类型见 scripts/base/frameworks/analyzer/main.zeek。该类型同时包含全部Analyzer::Tag、PacketAnalyzer::Tag和Files::Tag的枚举值副本专门用于函数/钩子/事件定义的参数使一个接口能统一处理任意类型的分析器——例如Analyzer::register_for_ports就接受Analyzer::Tag而Analyzer::enable_analyzer接受更通用的AllAnalyzers::Tag。三种分析器类型与Analyzer::kind()函数的返回值对应关系如下见 scripts/base/frameworks/analyzer/main.zeek分析器类型kind() 返回值判断函数典型标签前缀协议分析器protocolis_protocol_analyzer()Analyzer::ANALYZER_*包分析器packetis_packet_analyzer()PacketAnalyzer::ANALYZER_*文件分析器fileis_file_analyzer()Files::ANALYZER_*当传入的标签不属于任何已知类别时kind()会发出Reporter::warning并返回unknown。标签到名称/类型的转换由 BIF 层实现Analyzer::name()通过__name()依次在analyzer_mgr、packet_mgr、file_mgr中查找组件找不到时返回字符串error见 src/analyzer/analyzer.bif。三、动态启用与禁用分析器3.1 核心 APIenable_analyzer 与 disable_analyzerscripts/base/frameworks/analyzer/main.zeek 中Analyzer::enable_analyzer()与Analyzer::disable_analyzer()是统一分发器根据标签类型将调用转发到三个底层实现之一function enable_analyzer(tag: AllAnalyzers::Tag) : bool { if ( is_packet_analyzer(tag) ) return PacketAnalyzer::__enable_analyzer(tag); if ( is_file_analyzer(tag) ) return Files::__enable_analyzer(tag); return __enable_analyzer(tag); }disable_analyzer()结构完全对称。两个函数都返回bool表示是否成功。启用后分析器能否真正作用于新建连接还取决于 Zeek 的动态协议检测DPD决策禁用后该分析器将不再参与后续连接的解析但已挂载到现有连接上的分析器实例不受影响。底层 BIF 定义位于 src/analyzer/analyzer.bif直接调用 C 的zeek::analyzer_mgr-EnableAnalyzer()/DisableAnalyzer()/DisableAllAnalyzers()。C 侧实现见 src/analyzer/Manager.cc启用/禁用本质上是把插件组件plugin::Component的 enabled 标志置位/复位DisableAllAnalyzers()则遍历GetComponents()将所有组件一次全部关闭。3.2 启动时控制disable_all、disabled_analyzers 与 requested_analyzers框架提供三个启动期配置变量全部支持redef修改变量默认值作用Analyzer::disable_allF若为T启动时先关闭所有可用分析器Analyzer::disabled_analyzers{ ANALYZER_TCPSTATS }默认禁用的分析器集合内含不再受支持的遗留分析器Analyzer::requested_analyzers{}配合disable_all使用记录启动时需要启用的分析器集合初始化顺序由 scripts/base/frameworks/analyzer/main.zeek 中两个带优先级的zeek_init()事件保证event zeek_init() priority5 { if ( disable_all ) __disable_all_analyzers(); for ( a in disabled_analyzers ) disable_analyzer(a); } event zeek_init() priority-5 { for ( a in requested_analyzers ) Analyzer::enable_analyzer(a); }即先高优先级执行全量禁用和默认禁用集合再低优先级按requested_analyzers精确放行指定的分析器。典型用法 1只保留 DNS 分析器。参考 testing/btest/scripts/base/frameworks/analyzer/enable-analyzer.zeekredef Analyzer::disable_all T; event zeek_init() { Analyzer::enable_analyzer(Analyzer::ANALYZER_DNS); }典型用法 2用 requested_analyzers 声明式启用。参考 testing/btest/scripts/base/frameworks/analyzer/request-analyzer.zeek该测试验证“只有 HTTP 分析器被启用不产生 dns.log”# 关闭全部分析器 redef Analyzer::disable_all T; # 仅启用 HTTP redef Analyzer::requested_analyzers { Analyzer::ANALYZER_HTTP, };典型用法 3运行时动态切换。参考 testing/btest/scripts/base/frameworks/analyzer/toggle-packet-analyzers.zeek该测试在raw_packet事件中统计包数第 4 个包时禁用 VXLAN 包分析器、第 8 个包时重新启用if ( all_packets 4 ) { local er Analyzer::disable_analyzer(PacketAnalyzer::ANALYZER_VXLAN); print Analyzer::disable_analyzer(PacketAnalyzer::ANALYZER_VXLAN), er; } # Packets 5 to 8 dont produce vxlan_packet events. if ( all_packets 8 ) { local dr Analyzer::enable_analyzer(PacketAnalyzer::ANALYZER_VXLAN); print Analyzer::enable_analyzer(PacketAnalyzer::ANALYZER_VXLAN), dr; }该测试证明disable_analyzer()对后续包立即生效5~8 号包不再触发vxlan_packet事件重新启用后恢复解析——这是包分析器与协议分析器行为的一个重要差异包分析器无连接状态切换即时生效。典型用法 4禁用文件分析器。参考 testing/btest/scripts/base/frameworks/analyzer/disabled-file-analyzers.zeek命令行上通过Analyzer::disabled_analyzers { Files::ANALYZER_PE }禁止 PE 文件分析器后不再产生pe.log随后又用-e event zeek_init() { Analyzer::enable_analyzer(Files::ANALYZER_PE); }在初始化时显式重新启用pe.log恢复生成。可见disabled_analyzers的禁用并非绝对——只要初始化阶段显式 enable 即可覆盖。四、知名端口注册让连接自动匹配分析器4.1 register_for_ports / register_for_port默认情况下分析器挂在哪些端口上由各协议脚本自行注册。框架允许用户追加注册核心函数为 scripts/base/frameworks/analyzer/main.zeek 中的global register_for_ports: function(tag: Analyzer::Tag, server_ports: set[port], non_server_ports: set[port] defaultset()) : bool; global register_for_port: function(tag: Analyzer::Tag, p: port) : bool;要点语义是“追加”而非“替换”新端口叠加在已有注册之上server_ports会自动并入全局likely_server_ports集合见下文 4.3non_server_ports如客户端端口则不会register_for_ports内部就是逐个调用register_for_port任一失败则整体返回F见 scripts/base/frameworks/analyzer/main.zeek。注册示例把自定义端口 8080 的 HTTP 分析与 5353 的 DNS 分析关联起来event zeek_init() { # 追加注册不影响已有注册 Analyzer::register_for_ports(Analyzer::ANALYZER_HTTP, { 8080/tcp }); Analyzer::register_for_ports(Analyzer::ANALYZER_DNS, { 5353/udp }); }注意register_for_ports第一个参数是Analyzer::Tag仅协议分析器而包分析器请使用PacketAnalyzer::register_for_port(s)详见 scripts/base/frameworks/analyzer/main.zeek 中的ports表注释。4.2 查询接口框架提供两个查询函数scripts/base/frameworks/analyzer/main.zeek# 查询单个分析器当前注册的所有端口 global registered_ports: function(tag: AllAnalyzers::Tag) : set[port]; # 查询全部“分析器 - 端口集合”映射 global all_registered_ports: function() : table[AllAnalyzers::Tag] of set[port];实现上它们直接读取框架维护的全局表Analyzer::ports类型为table[AllAnalyzers::Tag] of set[port]。该表是双重用途的既被 BPF 过滤使用也被 DPD 使用协议分析器通过Analyzer::register_for_port(s)写入包分析器通过PacketAnalyzer::register_for_port(s)写入。4.3 端口注册的连带效果likely_server_ports 与 BPF 过滤注册 server 端口会自动更新likely_server_ports见 scripts/base/frameworks/analyzer/main.zeek 中的likely_server_ports server_ports。likely_server_ports用于 Zeek 判断连接哪一端更像服务端从而正确设置方向。端口注册还会自动反映到 BPF 过滤器中# 依据某分析器的注册端口生成 BPF 过滤串 global analyzer_to_bpf: function(tag: Analyzer::Tag): string; # 依据所有协议分析脚本注册的端口生成完整 BPF 过滤串 global get_bpf: function(): string;实现见 scripts/base/frameworks/analyzer/main.zeekanalyzer_to_bpf()遍历ports[tag]用PacketFilter::combine_filters(output, or, PacketFilter::port_to_bpf(p))把每个端口转成 BPF 表达式并以 OR 连接未注册任何端口的标签返回空串。get_bpf()则对所有已注册标签执行相同操作。这套机制依赖load base/frameworks/packet-filter/utils见 scripts/base/frameworks/analyzer/main.zeek因此可以按注册端口自动生成“只抓感兴趣的协议流量”的内核级过滤规则。4.4 底层注册路径与启动时序BIF 层Analyzer::__register_for_port()调用zeek::analyzer_mgr-RegisterAnalyzerForPort(id-AsEnumVal(), p)src/analyzer/analyzer.bif。C 侧 src/analyzer/Manager.cc 有一个值得注意的时序逻辑bool Manager::RegisterAnalyzerForPort(const zeek::Tag tag, TransportProto proto, uint32_t port) { if ( initialized ) return RegisterAnalyzerForPort(std::make_tuple(tag, proto, port)); else { // Cannot register these before PostScriptInit() has run ... pending_analyzers_for_ports.emplace(tag, proto, port); return true; } }即在PostScriptInit()之前包分析尚未就绪端口注册请求会先进入pending_analyzers_for_ports队列缓存待初始化完成后统一处理见 src/analyzer/Manager.cc。因此在zeek_init()中调用注册函数是安全且推荐的。RegisterAnalyzerForPort会根据传输层协议TCP/UDP 等建立相应的端口→分析器映射供新建连接时自动挂载分析器。五、调度分析器预知流量的定向挂载Analyzer::schedule_analyzer()用于针对未来可能出现的连接预先调度分析器scripts/base/frameworks/analyzer/main.zeekglobal schedule_analyzer: function(orig: addr, resp: addr, resp_p: port, analyzer: Analyzer::Tag, tout: interval) : bool;参数语义orig未来连接的发端地址0.0.0.0可作通配符匹配任意源地址resp响应方地址resp_p响应方目的端口analyzer要挂载的分析器 IDtout超时区间若到期仍未看到该连接调度请求将被丢弃C 侧要求超时非零见 src/analyzer/Manager.h。底层由__schedule_analyzer()转发到zeek::analyzer_mgr-ScheduleAnalyzer(...)src/analyzer/analyzer.bif。C 注释说明一旦连接被看到BuildInitAnalyzerTree()就会把调度中指定的分析器加入该连接的分析树src/analyzer/Manager.h。典型场景是当 Zeek 从外部情报如 DNS 响应、证书信息获知某服务器将提供某种服务时预先调度分析器以跳过 DPD 探测阶段。六、标签转换与名称工具框架提供一组标签⇄名称的辅助函数scripts/base/frameworks/analyzer/main.zeek函数签名说明Analyzer::name(tag: Analyzer::Tag) : string标签 → 分析器名称字符串Analyzer::kind(tag: Analyzer::Tag) : string标签 → 类型protocol/packet/file/unknownAnalyzer::has_tag(name: string) : bool校验名称是否为合法分析器Analyzer::get_tag(name: string) : Analyzer::Tag名称 → 标签假定名称存在调用前应先has_tag校验has_tag与get_tag的 BIF 实现src/analyzer/analyzer.bif通过component_for_name()依次查询analyzer_mgr、packet_mgr、file_mgr三个管理器static zeek::plugin::Component* component_for_name(const char* name) { plugin::Component* component zeek::analyzer_mgr-Lookup(name); if ( ! component ) component zeek::packet_mgr-Lookup(name, false); if ( ! component ) component zeek::file_mgr-Lookup(name, false); return component; }注意查询时不做映射跟随false参数返回的是用户传入名称对应的原始组件。典型用法将命令行传入的分析器名转为标签再启用event zeek_init() { if ( Analyzer::has_tag(HTTP) ) Analyzer::enable_analyzer(Analyzer::get_tag(HTTP)); }七、DPD 违规处理自动禁用与 service 字段维护DPD动态协议检测机制在工作原理上默认情况下分析器会基于端口注册对连接进行探测确认confirmation后进入正式解析若发生协议违规violation框架可自动移除该分析器。dpd.zeekscripts/base/frameworks/analyzer/dpd.zeek实现了“违规即禁用 维护连接日志 service 字段”的策略。7.1 可调选项选项默认值作用DPD::ignore_violationsset()发生违规时不移除的分析器集合DPD::ignore_violations_after10 * 1024连接双向总字节数超过该值后忽略违规设为 0 表示从不忽略DPD::track_removed_services_in_connectionF为T时违规后不在conn.log删除该 service而是追加一条带-前缀的条目如http,-http7.2 核心事件处理链dpd.zeek注册了三个事件处理器形成完整闭环analyzer_confirmation_info优先级 10分析器确认后把分析器名称加入连接记录的c$service集合仅限协议/包分析器。这是conn.log中service字段的数据来源。analyzer_violation_info优先级 5违规发生时先做三项过滤——分析器在ignore_violations中则跳过连接总字节数超过ignore_violations_after则跳过 0时才生效随后调用disable_analyzer(c$id, aid, F)禁用该连接上的分析器实例成功禁用则触发analyzer_failed事件scripts/base/frameworks/analyzer/dpd.zeek。analyzer_failed优先级 -5低优先级执行允许其他处理器先检查分析器是否曾被确认。若 service 尚未确认或已失败过则直接返回默认从c$service中删除失败分析器并加入c$failed_analyzers开启track_removed_services_in_connection时则保留原名、追加-name条目scripts/base/frameworks/analyzer/dpd.zeek。同时dpd.zeek通过redef record connection { failed_analyzers: set[string] ... }给连接记录扩展了failed_analyzers字段记录“确认后又被违规移除”的分析器scripts/base/frameworks/analyzer/dpd.zeek。7.3 违规事件的产生源头analyzer_violation_info/analyzer_confirmation_info事件由分析器运行时主动触发。在 C 侧协议分析器通过Analyzer::EnqueueAnalyzerConfirmationInfo()/EnqueueAnalyzerViolationInfo()入队事件src/analyzer/Analyzer.cc事件类型定义在 src/event.bif。包分析器也有对应的EnqueueAnalyzerConfirmationInfo(session, tag)与EnqueueAnalyzerViolationInfo(session, reason, data, len, tag)src/packet_analysis/Analyzer.cc文件分析器则在 src/file_analysis/Analyzer.cc 中入队同类事件。自定义违规处理示例忽略 TLS 违规并缩短违规忽略阈值redef DPD::ignore_violations { Analyzer::ANALYZER_TLS }; # 连接 1 MB 之后发生的违规不再自动禁用分析器 redef DPD::ignore_violations_after 1024 * 1024;八、违规日志analyzer.log 输出8.1 日志流定义logging.zeekscripts/base/frameworks/analyzer/logging.zeek在zeek_init()中创建名为analyzer的日志流Log::create_stream(LOG, Log::Stream($columnsInfo, $pathanalyzer, $evlog_analyzer, $policylog_policy));记录类型Analyzer::Logging::Info的字段如下字段类型是否必填说明tstime是违规时间戳analyzer_kindstring是分析器类型packet/file/protocolanalyzer_namestring是Analyzer::name()生成的分析器名称uidstring可选连接 UID若有fuidstring可选文件 UID若有idconn_id可选连接标识若有prototransport_proto可选违规涉及的传输层协议failure_reasonstring是失败/违规原因failure_datastring可选导致违规的数据长度受failure_data_max_size截断配套选项与钩子option failure_data_max_size 40违规数据最多记录多少字节设为 0 则完整记录见 scripts/base/frameworks/analyzer/logging.zeek 的截断逻辑global log_analyzer: event(rec: Info)可被外部处理以在写日志前访问记录global log_policy: Log::PolicyHook该流的默认日志策略钩子。8.2 日志写入路径log_analyzer_failure()负责组装Info记录scripts/base/frameworks/analyzer/logging.zeek其组装逻辑值得注意从info$c提取id、uid并用get_port_transport_proto()推导proto从info$f提取fuid若连接信息缺失但fa_file恰好关联唯一连接则回填id/uidfailure_data按failure_data_max_size截断。写入分为两条路径scripts/base/frameworks/analyzer/logging.zeek协议分析器监听analyzer_failed事件仅记录“之前已确认、且尚未记录过违规”的服务避免重复刷日志分析器可能因 DPD 重新挂载而多次失败包/文件分析器监听analyzer_violation_info事件直接记录——因为这两类分析器永远不会被主动移除/禁用对应框架文档中“analyzer_failed目前仅对协议分析器触发”的说明。示例输出analyzer.log中一行典型违规记录#fields ts analyzer_kind analyzer_name uid id proto failure_reason failure_data #types time string string string conn_id enum string string 1700000000.000000 protocol HTTP CViC... 192.168.1.1:5000,10.0.0.1:80 tcp excess_data ...九、框架在真实项目中的使用模式综合以上 API一个完整的“最小化启用 端口注册 违规处理”策略脚本通常是这样组织的# 1. 只启用需要的协议分析器 redef Analyzer::disable_all T; redef Analyzer::requested_analyzers { Analyzer::ANALYZER_HTTP, Analyzer::ANALYZER_DNS, Analyzer::ANALYZER_SSL, }; # 2. 为非常规端口注册分析器 event zeek_init() { Analyzer::register_for_ports(Analyzer::ANALYZER_HTTP, { 8080/tcp, 8443/tcp }); Analyzer::register_for_ports(Analyzer::ANALYZER_DNS, { 5353/udp }); } # 3. 违规时保留 HTTP其余照常自动禁用 redef DPD::ignore_violations { Analyzer::ANALYZER_HTTP }; # 4. 追踪被移除的 serviceconn.log 中出现 http,-http redef DPD::track_removed_services_in_connection T; # 5. 在 analyzer.log 中多记录一些失败数据 redef Analyzer::Logging::failure_data_max_size 256; # 6. 自定义日志策略过滤掉内网扫描产生的噪声违规 event Analyzer::Logging::log_analyzer(rec: Analyzer::Logging::Info) { if ( rec?$id is_local_addr(rec$id$orig_h) rec$failure_reason excess_data ) break; }对应测试用例可在仓库的 testing/btest/scripts/base/frameworks/analyzer/ 目录中逐一验证例如enable-analyzer.zeek验证disable_all enable_analyzer后仅产生 DNS 服务request-analyzer.zeek验证disable_all requested_analyzers仅启用 HTTP且不产生dns.logtoggle-packet-analyzers.zeek验证包分析器的运行时启用/禁用即时生效disabled-file-analyzers.zeek验证disabled_analyzers对文件分析器的默认禁用与显式重新启用。十、小结Analyzer 框架是 Zeek 分析器管理的总控台贯穿协议、包、文件三类分析器启停控制enable_analyzer/disable_analyzer/disable_all/disabled_analyzers/requested_analyzers覆盖了从“全量关闭、精确放行”到“运行时动态切换”的完整控制面底层由 src/analyzer/Manager.cc 的EnableAnalyzer/DisableAnalyzer/DisableAllAnalyzers支撑端口管理register_for_ports/register_for_port以追加语义建立端口→分析器映射并自动联动likely_server_ports与 BPF 过滤定向调度schedule_analyzer可预知地针对未来连接挂载分析器带超时丢弃机制违规闭环dpd.zeek负责确认→违规→禁用→service 维护的完整链路logging.zeek将结果沉淀到analyzer.log。核心入口文档见 doc/scripts/base/frameworks/analyzer/index.rst完整 API 参考 scripts/base/frameworks/analyzer/main.zeekBIF 层实现见 src/analyzer/analyzer.bif。无论是做协议裁剪、非常规端口适配还是构建自动化的违规响应策略这套框架都是必须掌握的第一站。赞分享网络安全网络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 动态协议检测DPD与 analyzer.log 完全解读从协议违规日志到可疑流量识别Zeek 动态协议检测DPD与 analyzer.log 完全解读从协议违规日志到可疑流量识别 Zeek 的 analyzer.log 是动态协议检测D网络安全网络IDSZeek 分析器框架内部接口解析深入 Analyzer::__ 系列 BIF 函数与动态协议分析机制Zeek 分析器框架内部接口解析深入 Analyzer::__ 系列 BIF 函数与动态协议分析机制 导读 本文围绕 Zeek 仓库中 base/bif/an网络安全网络IDSMQTTnet异常处理完全手册连接断开、超时与协议违规的解决方案MQTTnet异常处理完全手册连接断开、超时与协议违规的解决方案 MQTTnet是一个高性能的.NET MQTT通信库提供了MQTT客户端和MQTT服务器物联网消息队列上一篇【亲测免费】 CefFlashBrowser 开源项目教程下一篇探索安全漏洞的利器Dependency-Check创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表