ARTICLE DETAIL

资讯详情

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

Zeek Storage Framework 完全指南:`base/frameworks/storage` 包的结构、API 与实战用法

Zeek Storage Framework 完全指南:`base/frameworks/storage` 包的结构、API 与实战用法 网络安全网络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 的存储框架Storage Framework为脚本层提供了一套可插拔的长短期数据落盘机制用于把从流量中分析出的数据工件而非报文本身以键值对形式持久化到 Redis、SQLite 等后端。本文以base/frameworks/storage脚本包的加载入口load.zeek.rst 为骨架深入讲解该包的三个组成模块main、async、sync、核心类型与可重定义选项、操作返回码体系、内置 Redis/SQLite 后端的完整配置项并给出可直接运行的同步/异步代码示例与源码级实现佐证。读完本文你将能够在自己编写的 Zeek 脚本中打开后端、写入/读取/删除键值对并正确选择同步或异步调用方式。一、包结构__load__.zeek加载了什么base/frameworks/storage/__load__.zeek是存储框架脚本包的入口它只有三行load指令把整个框架的三个脚本模块串联起来见load.zeekload ./async load ./main load ./sync也就是说只要load base/frameworks/storage或load base/frameworks/storage/__load__以下三个模块会同时生效模块文件命名空间职责main.zeekStorage框架基础定义BackendOptions、PutArgs类型、后端/序列化器枚举及可重定义选项async.zeekStorage::Async异步操作open_backend/close_backend/put/get/erase必须配合when使用sync.zeekStorage::Sync同步操作同名的 5 个函数阻塞等待后端返回官方文档 doc/frameworks/storage.rst 对三个模块的定位做了总结存储框架提供的是基于插件的短/长期数据存储系统可从 Zeek 脚本层访问它本质是一个简单的键值存储键和值都直接使用 Zeek 值类型。该框架自 Zeek 7.2 引入.. versionadded:: 7.2。为什么把同步/异步拆成两个模块两个模块的 API 签名完全一致唯一的区别是调用方式异步模式Storage::Async函数必须放在when条件中调用否则直接返回错误调用后返回码通常为IN_PROGRESS结果通过when的续体接收。同步模式Storage::Sync既可以放在when里也可以直接调用直接调用时函数会阻塞直到后端返回数据。从 async.zeek 的包装函数 可以看到一个关键设计异步函数内部会先检查options$forced_sync如果打开后端时设置了强制同步则异步 API 实际会转发到Storage::Sync::__open_backend。同理put/get/erase/close_backend都会通过Storage::is_forced_sync(backend)判断当前后端句柄是否处于强制同步模式见 async.zeek。Storage::is_forced_sync是 C 侧实现的 BIF定义于 src/storage/storage.bif它从opaque of Storage::BackendHandle句柄中取出底层Backend对象并返回IsForcedSync()。一个值得注意的运行时行为同样来自 doc/frameworks/storage.rst当用zeek -r读取 pcap 文件时所有后端在内部都以同步方式工作以保证 Zeek 的定时器正确推进此时即便调用异步函数也会被翻译成同步调用。二、核心类型与可重定义选项Storage::mainStorage::main模块是整个框架的类型基石全部定义在 scripts/base/frameworks/storage/main.zeek 中。2.1 可重定义选项# Default value for the BackendOptions::forced_sync field. const default_forced_sync: bool F redef; # The histogram buckets to use for operation latency metrics, in seconds. const latency_metric_bounds: vector of double { 0.001, 0.01, 0.1, 1.0, } redef;Storage::default_forced_syncbool默认FBackendOptions::forced_sync字段的默认值。强制同步模式下所有操作即使调用的是异步函数都会同步执行。文档明确建议仅在测试期间设置为T。Storage::latency_metric_boundsvector of double默认[0.001, 0.01, 0.1, 1.0]单位秒操作延迟指标使用的直方图桶边界。这对应 C 侧OperationMetrics结构中的telemetry::HistogramPtr latency指标见 src/storage/Backend.h每个操作类型/后端类型/后端配置都会产生独立的成功率、失败率、错误数、超时数与延迟直方图。2.2Storage::BackendOptions所有后端共用的基类配置记录backend 插件可通过redef record Storage::BackendOptions {...}扩展字段type BackendOptions: record { serializer: Storage::Serializer defaultStorage::STORAGE_SERIALIZER_JSON; forced_sync : bool defaultStorage::default_forced_sync; };serializer用于转换 Zeek 数据的序列化器默认Storage::STORAGE_SERIALIZER_JSON目前唯一内置的序列化器见Storage::Serializer枚举。forced_sync强制同步开关默认取Storage::default_forced_sync即F。从源码结构看BackendOptions是一个刻意保持开放的记录——内置的 SQLite/Redis 策略脚本都通过redef向其追加专属字段详见第四节第三方后端插件也可以照此模式扩展。2.3Storage::PutArgs传给put的参数记录type PutArgs: record { key: any; # 要存储的键 value: any; # 与键关联的值 overwrite: bool defaultT; # 是否覆盖该键已存在的条目 expire_time: interval default0sec; # 条目自动过期删除的时间间隔0 表示永不过期 };overwrite默认T若设为F且键已存在后端应返回KEY_EXISTS错误码。expire_time默认0 secs不过期后端原生不支持过期时框架侧还有一个Storage::expire_interval 15.0 secs的自动过期扫描间隔常量定义于 scripts/base/init-bare.zeek。2.4 枚举类型Storage::Backend后端类型标签目前含Storage::STORAGE_BACKEND_REDIS与Storage::STORAGE_BACKEND_SQLITE由加载的后端插件定义外部包可实现更多。Storage::Serializer序列化器类型标签目前含Storage::STORAGE_SERIALIZER_JSON。序列化器插件负责把 Zeek 值转换成后端可用的不透明字节缓冲且设计上对后端中立——任何序列化器产生的数据任何后端都应能处理。三、操作 APIStorage::Sync与Storage::Async两个模块都提供完全对称的 5 个函数签名与语义一一对应。下表汇总函数定义见 sync.zeek 与 async.zeek函数签名说明open_backend(btype: Storage::Backend, options: Storage::BackendOptions, key_type: any, val_type: any) : Storage::OperationResult根据配置对象打开一个新的后端连接。btype为后端插件定义的类型标签key_type/val_type声明键值的脚本层类型用于后续操作的校验与类型转换。成功后value字段为opaque of Storage::BackendHandleclose_backend(backend: opaque of Storage::BackendHandle) : Storage::OperationResult关闭现有后端连接put(backend: opaque of Storage::BackendHandle, args: Storage::PutArgs) : Storage::OperationResult向后端插入新条目get(backend: opaque of Storage::BackendHandle, key: any) : Storage::OperationResult按键查询条目成功时value字段返回与open_backend声明类型一致的值erase(backend: opaque of Storage::BackendHandle, key: any) : Storage::OperationResult按键删除条目所有函数返回Storage::OperationResult。异步版本Storage::Async的文档强调必须通过when条件调用否则返回错误——这是 Zeek 事件驱动模型下异步回调的标准用法。3.1 操作返回码与结果记录Storage::OperationResult记录定义于 scripts/base/init-bare.zeektype OperationResult: record { code: ReturnCode; # 操作结果代码后端可扩展 error_str: string optional; # 失败时的可选错误信息 value: any optional; # open_backend 返回句柄 / get 返回值 };Storage::ReturnCode枚举scripts/base/init-bare.zeek提供了一套通用状态码后端插件可以通过redef追加自定义代码代码含义SUCCESS操作成功VAL_TYPE_MISMATCH传入的值类型与打开后端时声明的值类型不符KEY_TYPE_MISMATCH传入的键类型与打开后端时声明的键类型不符NOT_CONNECTED后端未连接TIMEOUT操作超时CONNECTION_LOST连接意外丢失OPERATION_FAILED通用操作失败KEY_NOT_FOUND请求的键在后端中不存在KEY_EXISTS请求覆盖的键已存在对应overwriteFCONNECTION_FAILED连接建立失败区别于中途丢失DISCONNECTION_FAILED断开失败INITIALIZATION_FAILED初始化失败IN_PROGRESS异步操作正在等待结果在 C 侧src/storage/Backend.h 中的zeek::storage::OperationResult结构与脚本层一一对应codeEnumValPtr、err_strstd::string、valueValPtr并通过BuildVal()构造脚本层的Storage::OperationResult记录值——这就是脚本层看到的结果记录的底层来源。3.2 事件backend_opened与backend_lost框架定义了两个事件见 src/storage/storage-events.bifevent Storage::backend_opened%(tag: Storage::Backend, options: any%); event Storage::backend_lost%(tag: Storage::Backend, options: any, reason: string%);backend_opened后端连接成功打开时自动生成options是打开时传入配置的副本。backend_lost连接丢失包括正常关闭与意外断开时可能生成。注意文档明确指出该事件依赖后端实现处理并非由框架自动触发意外断开场景下它给脚本层提供了重连等容错机会。options参数类型为any是因为不同后端的配置记录结构不同取决于加载了哪个后端策略。四、内置后端SQLite 与 Redis 的配置详解框架本身只定义通用 API具体存储介质由后端插件提供。Zeek 默认内置 SQLite 与 Redis 两个后端对应策略脚本位于 scripts/policy/frameworks/storage/backend 下。加载后端策略后Storage::BackendOptions会被redef追加专属字段。4.1 SQLite 后端加载方式load policy/frameworks/storage/backend/sqlite。配置记录Storage::Backend::SQLite::Options定义于 scripts/policy/frameworks/storage/backend/sqlite/main.zeek字段类型/默认值说明database_pathstring数据库文件路径设为:memory:使用内存数据库相对路径相对于 Zeek 启动目录解析不会自动创建中间目录table_namestring存储数据的表名同一数据库文件可用于两张不同的表table_name不同即可busy_timeoutinterval默认5 secs数据库连接超时等价于busy_timeoutpragma该 pragma 会被此字段覆盖pragma_commandstable[string] of string默认 4 条打开数据库时执行的 pragma 命令键值表无第二参数的 pragma 值设为空字符串integrity_check会自动执行无需写入busy_timeoutpragma 写在这里会被忽略pragma_timeoutinterval默认500 msec单个 pragma 命令的总重试时限超时返回初始化错误设为 0 表示无限重试pragma_wait_on_busyinterval默认5 msecpragma 失败后的重试等待间隔默认pragma_commandstable( [quick_check] , [journal_mode] WAL, [synchronous] normal, [temp_store] memory ) ordered文档 doc/frameworks/storage.rst 对 SQLite 后端给出两条重要注意事项默认journal_mode为WAL而WAL 模式在网络文件系统上不可用——数据库文件必须放在所有打开它的 Zeek 进程所在的同一台机器上。使用内存数据库:memory:时数据不会在节点间同步每个进程在自己的内存空间中维护独立数据库。4.2 Redis 后端加载方式load policy/frameworks/storage/backend/redis。配置记录Storage::Backend::Redis::Options定义于 scripts/policy/frameworks/storage/backend/redis/main.zeek字段类型/默认值说明server_hoststringoptional服务器地址或主机名server_portport默认6379/tcp服务器端口server_unix_socketstringoptional本地 unix socket 文件可替代地址端口使用前提server_host必须未设置key_prefixstring默认存储键的前缀用于在同一服务器上区分不同类型的数据建议每个打开的 Redis 后端设为唯一值connect_timeoutinterval默认5 secs连接超时超时返回CONNECTION_FAILEDoperation_timeoutinterval默认5 secs操作请求超时超时返回TIMEOUTusernamestringoptionalACL 保护下的认证用户名passwordstringoptional简单密码或 ACL 认证密码两个可重定义常量Storage::Backend::Redis::default_connect_timeout与default_operation_timeout均默认5 secs可全局调整默认超时单个连接用上述字段覆盖。Redis 后端的构建与运行前提出自 doc/frameworks/storage.rst 的 Notes 部分构建需要系统安装hiredis库至少1.1.0版本2022 年 11 月发布。需要Redis 服务器 6.2.0 或更高版本或实现等价 API 级别的第三方服务器因为后端使用到该版本才提供的 API 特性。4.3 后端标签与序列化器枚举打开后端时第一个参数从Storage::Backend枚举中选择Storage::STORAGE_BACKEND_SQLITE或Storage::STORAGE_BACKEND_REDIS。序列化器统一使用Storage::STORAGE_SERIALIZER_JSONBackendOptions的默认值也可显式指定。五、实战示例完整可运行的 Zeek 脚本官方文档 doc/frameworks/storage.rst 提供了完整示例下面按打开/关闭后端与存储/检索/删除数据两个阶段展开并补充仓库测试用例中的真实写法。5.1 打开与关闭后端同步方式load base/frameworks/storage/sync load policy/frameworks/storage/backend/sqlite local opts: Storage::BackendOptions; local backend: Storage::BackendHandle; # 加载 sqlite 策略后该字段被追加到选项记录中。 # database_path 为数据库文件路径table_name 为表名。 opts$sqlite [$database_pathtest.sqlite, $table_nametesting]; # 序列化器默认就是 JSON这里展示如何显式设置。 opts$serializer Storage::STORAGE_SERIALIZER_JSON; local res Storage::Sync::open_backend(Storage::STORAGE_BACKEND_SQLITE, opts, string, string); if ( res$code Storage::SUCCESS ) backend res$value; # ... 使用 backend 进行操作 ... res Storage::Sync::close_backend(backend);要点后端的键/值类型在open_backend时以string, string声明之后使用其他类型的键或值会触发Storage::KEY_TYPE_MISMATCH/VAL_TYPE_MISMATCH。后端句柄可以像普通值一样存入全局变量例如在zeek_init事件中打开、在整个运行期复用。成功打开时触发Storage::backend_opened事件成功关闭时触发Storage::backend_lost。5.2 存储、检索与删除数据# 写入keyabcvaluedef45 秒后自动过期 local res Storage::Sync::put(backend, [$keyabc, $valuedef, $expire_time45sec]); if ( res$code ! Storage::SUCCESS ) { print(res$error_str); return; } # 读取 res Storage::Sync::get(backend, abc); if ( res$code ! Storage::SUCCESS ) { print(res$error_str); return; } # 成功时值在 res$value 中 # 删除 res Storage::Sync::erase(backend, abc); if ( res$code ! Storage::SUCCESS ) { print(res$error_str); return; }put传入的键值类型必须与open_backend声明一致expire_time指明数据何时被自动移除。get若键已被删除手动或过期后端应返回Storage::KEY_NOT_FOUNDerase同样在键不存在时返回KEY_NOT_FOUND。5.3 异步写法when条件的标准模式异步调用必须包在when中并为每个请求配置超时分支。仓库测试 testing/btest/scripts/base/frameworks/storage/sqlite/basic.zeek 展示了完整的嵌套写法load base/frameworks/storage/async load policy/frameworks/storage/backend/sqlite global b : opaque of Storage::BackendHandle; event zeek_init() { local opts: Storage::BackendOptions; opts$serializer Storage::STORAGE_SERIALIZER_JSON; opts$sqlite [ $database_pathtest.sqlite, $table_nametesting ]; local key key1234; local value value5678; when [opts, key, value] ( local open_res Storage::Async::open_backend( Storage::STORAGE_BACKEND_SQLITE, opts, string, string) ) { print open result, open_res; b open_res$value; when [key, value] ( local put_res Storage::Async::put(b, [ $keykey, $valuevalue ]) ) { print put result, put_res; when [key, value] ( local get_res Storage::Async::get(b, key) ) { print get result, get_res; if ( get_res$code Storage::SUCCESS get_res?$value ) print get result same as inserted, value ( get_res$value as string ); } timeout 5sec { print get request timed out; terminate(); } } timeout 5sec { print put request timed out; terminate(); } } timeout 5sec { print open request timed out; terminate(); } }该测试还展示了异步操作的结果中get_res$code Storage::SUCCESS且get_res?$value存在时可用get_res$value as string把返回值转换回声明类型。5.4 同步与异步混用读取 pcap 场景测试 basic-reading-pcap.zeek 展示了一个实用组合用同步open_backend打开后端再对put/get使用异步when调用最后同步关闭——验证了在zeek -r读取 pcap 时异步操作同样正常工作框架内部会以同步方式推进。5.5 复杂类型的键值序列化器能力验证存储框架的键值并不限于简单类型。测试 compound-types.zeek 用open_backend(..., Rec, tbl)打开后端其中键是一个包含string/bool/count/int/double/string_vec/enum/port/time/interval/addr/subnet/pattern/set等十余种字段的记录值是table[count] of string——这些数据通过 JSON 序列化器完整往返存取证明框架对 Zeek 复合类型的支持。但需注意键值类型必须在open_backend时显式声明且一旦声明后续put/get只能使用相同类型。六、从源码看框架的实现原理6.1 同步/异步的内部分流C 侧提供了两组底层 BIFsrc/storage/storage-sync.bif 定义Storage::Sync::__open_backend、__close_backend、__put、__get、__erase__前缀用于区分脚本层同名包装函数src/storage/storage-async.bif 定义对应的异步版本并处理异步结果回调——从源码注释看异步流程会先确认 triggerwhen条件已建立再启动操作并在后端不支持异步或正在读取 trace 时假扮异步handle_async_result中处理了相应分支。脚本层的Storage::Sync::open_backend直接转发到__open_backend见 sync.zeek而Storage::Async::open_backend会先判断options$forced_sync若为T则转投同步实现见 async.zeek——这就是强制同步模式的落地路径。6.2 句柄与指标后端句柄是opaque of Storage::BackendHandleStorage::is_open与Storage::is_forced_sync两个 BIFsrc/storage/storage.bif负责从句柄反查底层后端状态。每个后端连接在 C 侧持有OperationMetricssrc/storage/Backend.h包含成功/失败/错误/超时四个计数器与一个延迟直方图标签维度为操作类型、后端类型与后端配置。测试 metrics.zeek 通过Telemetry::collect_metrics(zeek, storage*)采集并打印这些指标验证了框架与 Zeek 遥测框架的集成。6.3 可扩展性ReturnCode、BackendOptions、后端/序列化器枚举都设计为可扩展外部后端插件可以redef枚举追加自定义状态码、redef record Storage::BackendOptions追加配置字段并注册新的Storage::Backend标签。文档还提到testing/btest/plugin/storage-src目录下有示例存储插件从当前仓库结构看对应测试插件位于testing/btest/plugins/storage.zeek等文件可作为实现自定义后端的参考起点。七、使用建议与常见陷阱同步还是异步事件处理如zeek_init、连接事件里适合同步直调对延迟敏感或需要并发处理大量请求时用异步 whentimeout避免阻塞事件循环。when是硬约束异步函数脱离when调用会直接返回错误文档原文This method must be called via awhencondition or an error will be returned。键值类型一经声明不可变open_backend的key_type/val_type参数决定整个连接后续可用的类型混用会得到KEY_TYPE_MISMATCH/VAL_TYPE_MISMATCH。SQLite 路径与 WAL相对路径相对 Zeek 启动目录网络文件系统上务必关闭 WAL调整pragma_commands:memory:数据库不跨进程共享。Redis 键前缀key_prefix建议每个后端连接设为唯一值避免同一服务器上不同数据集互相干扰。forced_sync仅用于测试生产环境保持默认F否则会丧失异步带来的并发能力。连接丢失容错监听Storage::backend_lost带reason参数可以在意外断连时实现重连逻辑。八、进一步阅读框架总览与完整示例doc/frameworks/storage.rst包级 API 文档与本文对应的自动生成文档doc/scripts/base/frameworks/storage/load.zeek.rstdoc/scripts/base/frameworks/storage/main.zeek.rstdoc/scripts/base/frameworks/storage/async.zeek.rstdoc/scripts/base/frameworks/storage/sync.zeek.rst脚本实现scripts/base/frameworks/storage后端策略scripts/policy/frameworks/storage/backendC 实现src/storage测试用例testing/btest/scripts/base/frameworks/storage/sqlite赞分享网络安全网络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 Storage 框架通用 BIF 深入解析Storage::is_open 与 Storage::is_forced_sync 的底层实现与实战Zeek Storage 框架通用 BIF 深入解析Storage::is_open 与 Storage::is_forced_sync 的底层实现与实战 导网络安全网络IDSCANN ops-transformer MoeTokenPermuteWithEp 算子深度解析MoE EP 场景下的 Token Permute 实现与 aclnn 接口调用指南CANN ops transformer MoeTokenPermuteWithEp 算子深度解析MoE EP 场景下的 Token Permute 实现与网络安全网络IDSZeek Storage Framework 实战指南基于插件体系的长短期数据键值存储Zeek Storage Framework 实战指南基于插件体系的长短期数据键值存储 导读 Zeek原 Bro是一个强大的网络分析框架。除了对包流量进行网络安全网络IDS上一篇iii CLI 实战指南命令发现、函数触发、引擎启动与自我更新下一篇Genkit Dart 集成 Firebase AI通过 genkit_firebase_ai 插件调用 Gemini API创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表