- 网络安全
- 网络
- IDS
【免费下载链接】zeek
Zeek is a powerful network analysis framework that is much different from the typical IDS you may know.
本文围绕 Zeek 集群框架(Cluster framework)的公共数据类型与可重定义选项展开,以 scripts/base/frameworks/cluster/types.zeek 及其生成的 API 文档 doc/scripts/base/frameworks/cluster/types.zeek.rst 为骨架,结合 main.zeek、load.zeek 与 C++ 后端源码,讲清集群节点角色模型、节点拓扑记录、事件 pub/sub 载体、WebSocket 服务器与 TLS 选项的定义、默认值与底层行为。读完本文,你将能够准确理解Cluster::nodes拓扑配置中每个字段的含义,并能正确配置基于 WebSocket 的外部客户端接入参数。
概览:Cluster 框架的公共接口
Zeek 的集群框架(加载方式为@load base/frameworks/cluster)允许把多个 Zeek 实例组织成 manager、worker、proxy、logger 等角色协同工作。框架对外暴露的接口分为两大类:
- 可重定义选项(Redefinable Options):全局常量,可通过
redef在本地脚本中调整,用于控制 WebSocket 事件分发器的默认队列容量与默认 ping 间隔。 - 公共类型(Types):
NodeType枚举、Node/NamedNode/Event/NetworkInfo/EndpointInfo记录类型,以及WebSocketServerOptions/WebSocketTLSOptions两个 WebSocket 服务器配置记录。
全部类型与常量定义在单一文件 scripts/base/frameworks/cluster/types.zeek 中,位于module Cluster;命名空间之下,并被 main.zeek 通过@load ./types引入。
NodeType:集群节点角色枚举
Cluster::NodeType定义了允许参与集群配置的节点类型,源码位于 types.zeek 第 7–23 行:
| 枚举值 | 含义 |
|---|---|
NONE | 哑节点类型,表示本地节点未运行在集群环境中 |
CONTROL | 允许查看/操作集群中其他节点配置的节点类型 |
LOGGER | 负责日志管理的节点类型 |
MANAGER | 负责策略(policy)管理的节点类型 |
PROXY | 负责中继 worker 节点通信、同步 worker 节点状态的节点类型 |
WORKER | 执行实际流量分析的节点类型 |
这一枚举是所有集群拓扑配置的基石:Cluster::nodes表中每个节点记录的node_type字段即取自该枚举。load.zeek 依据Cluster::local_node_type()的返回值决定加载哪一套节点逻辑脚本(manager 加载./nodes/manager、logger 加载./nodes/logger、proxy 加载./nodes/proxy、worker 加载./nodes/worker),从源码结构可以推断,本地节点的角色完全由拓扑表中自身条目的node_type驱动。
Node:集群节点的核心记录类型
Cluster::Node是描述集群中单个节点的记录类型(types.zeek 第 26–46 行),也是Cluster::nodes拓扑表中值的类型。字段如下:
| 字段 | 类型 | 属性/默认值 | 说明 |
|---|---|---|---|
node_type | NodeType | 必填 | 标识该节点在本节点配置中的角色 |
ip | addr | 必填 | 集群节点的 IP 地址 |
zone_id | string | &default="",可选 | 当ip为非全局 IPv6 地址时,可指定 RFC 4007 的zone_id |
p | port | &default=0/unknown,可选 | 该节点监听对等连接的端口;值为0/unknown表示该节点未预先配置监听 |
manager | string | 可选 | 该节点使用的 manager 节点名称(worker 和 proxy 使用) |
id | string | 可选 | broker 框架分配给节点的唯一标识,仅在节点处于连接状态时设置 |
metrics_port | port | 可选 | 向 Prometheus 暴露指标的端口;在集群配置中设置它会覆盖该节点Telemetry::metrics_port的设置 |
其中id字段由 broker 运行时动态填充,不应由用户配置。main.zeek 中的hello事件处理器(优先级 10)在收到对端 hello 消息后会更新n$id,并将其加入active_node_ids集合;node_down事件处理器则负责在节点断连时删除n$id并从活跃集合中移除对应 ID。也就是说,id是"运行时才存在"的连接态字段。
metrics_port与 Prometheus 遥测集成相关:main.zeek 提供的local_node_metrics_port()函数会依次检查节点是否启用、节点是否存在于拓扑表、metrics_port字段是否存在,任一条件不满足则返回0/unknown。
NamedNode、NetworkInfo 与 EndpointInfo
NamedNode:带名字的节点
Cluster::NamedNode(types.zeek 第 49–52 行)由name: string与node: Node两个字段构成,用于"名称 + 节点信息"成对传递。例如 main.zeek 中的nodes_with_type()遍历Cluster::nodes表,把同一node_type的条目组装成NamedNode($name=name, $node=n)向量返回;nodeid_to_node(id)则根据 broker 分配的节点 ID 反向查找到对应的NamedNode,未找到时返回一个name为空的"null"实例。
NetworkInfo:端点的网络信息
Cluster::NetworkInfo(第 114–119 行)只含两个字段:
address: string——端点监听的 IP 地址或主机名;bound_port: port——端点绑定到的端口。
EndpointInfo:WebSocket 端点信息
Cluster::EndpointInfo(第 122–127 行)描述一个 WebSocket 端点,包含:
id: string——端点标识;network: NetworkInfo——网络信息;application_name: string(可选)——X-Application-NameHTTP 头的值(若存在)。
EndpointInfo主要服务于 WebSocket 外部客户端的事件回调。在 main.zeek 中,format_endpoint_info()将端点格式化为'<id>' (<address>:<bound_port>),若存在application_name则追加输出;websocket_client_added与websocket_client_lost事件则分别利用它记录客户端订阅与断开信息到集群日志。在 C++ 侧,WebSocket.cc 的Process(const WebSocketOpen&)会校验X-Application-Name头(仅允许字母数字及/ _ - . = : * @等字符),非法值会触发invalid_application_name错误并以 1008 状态码关闭连接。
Event:集群 pub/sub 的事件载体
Cluster::Event(第 57–62 行)是集群发布/订阅机制中一次事件实例的载体:
ev: any——要在远端节点上调用的事件处理器;args: vector of any——该事件的参数列表。
该类型与 Cluster::publish 和Cluster::make_event配套使用:事件处理器与参数被封装进Event记录,经序列化后通过 broker 或 WebSocket 通道投递给远端节点执行。pub/sub 的订阅原语(Cluster::subscribe/Cluster::unsubscribe)定义在 pubsub.zeek 中,底层委托给base/bif/cluster.bif中由 C++ 实现的__subscribe/__unsubscribe内建函数。
两个可重定义选项:WebSocket 事件分发器参数
types.zeek 中定义了两个全局可重定义常量(均声明为&redef),用于控制 WebSocket 事件分发器(WebSocketEventDispatcher)的行为:
Cluster::default_websocket_max_event_queue_size
- 类型:
count,属性:&redef,默认值:32。
这是 WebSocket 事件分发器实例的默认最大队列大小。当队列达到上限时,来自外部 WebSocket 客户端的事件将被暂缓(stalled),直到队列被排空后才继续处理。
关键的可观测性行为:当队列达到上限时,名为cluster_onloop_queue_stalls的内部指标会被递增,并带有WebSocketEventDispatcher:<host>:<port>标签。该标签格式与 C++ 实现直接对应——WebSocket.cc 第 219–229 行在构造WebSocketEventDispatcher时以"WebSocketEventDispatcher:" + ident为名称创建OnLoopProcess并注册到 IO 循环,而ident在 Manager.cc 的ListenWebSocket()中被构造为"%s:%d"(即 host 与 port)。队列与背压机制由zeek::detail::OnLoopProcess模板(位于 src/script_opt/OnLoop.h)提供。
Cluster::default_websocket_ping_interval
- 类型:
interval,属性:&redef,默认值:5.0 secs。
WebSocket 客户端的默认 ping 间隔。WebSocket 服务器会按该间隔向客户端发送 ping 帧以维持连接活性。
WebSocketTLSOptions:WebSocket 服务器的 TLS 配置
Cluster::WebSocketTLSOptions(第 81–94 行)用于为 WebSocket 服务器配置 TLS:
| 字段 | 类型 | 默认值 | 说明 |
|---|---|---|---|
cert_file | string | 可选 | 使用的证书文件 |
key_file | string | 可选 | 使用的私钥文件 |
enable_peer_verification | bool | F | 期望对端发送客户端证书 |
ca_file | string | "" | 用于对端验证的 CA 证书或 CA 捆绑包;为空时,在enable_peer_verification为T的情况下使用实现自身的默认 CA |
ciphers | string | "" | 使用的密码套件;为空时使用实现默认值 |
启用/禁用规则:如果cert_file与key_file均被设置,则 TLS 启用;两者均未设置则 TLS 禁用;其他任何组合(只设置其一)都是错误配置。
WebSocketServerOptions:WebSocket 服务器配置
Cluster::WebSocketServerOptions(第 97–111 行)是传给Cluster::listen_websocket的服务器选项记录:
| 字段 | 类型 | 默认值 | 说明 |
|---|---|---|---|
listen_addr | addr | 可选 | 监听地址;不能与listen_host同时使用 |
listen_port | port | 必填 | WebSocket 服务器应监听的端口 |
max_event_queue_size | count | default_websocket_max_event_queue_size(即 32) | 该服务器的事件队列上限 |
ping_interval | interval | default_websocket_ping_interval(即 5.0 secs) | ping 间隔;不响应 ping 的客户端会被断开;设为负值可禁用 ping;当前不支持亚秒级间隔 |
tls_options | WebSocketTLSOptions | WebSocketTLSOptions()(即 TLS 禁用) | 该服务器使用的 TLS 选项 |
从调用链看,脚本层Cluster::listen_websocket(options)(main.zeek 第 376–379 行)会委托给 C++ 内建函数Cluster::__listen_websocket;C++ 侧 Manager.cc 的ListenWebSocket()以(host, port)为键维护已启动的 WebSocket 服务器集合,重复监听同一地址且选项相同会直接返回成功,选项不同则报错Already listening on <host>:<port>。随后它根据options.max_event_queue_size构造WebSocketEventDispatcher,这正是default_websocket_max_event_queue_size的用武之地。另外,WebSocket.cc 第 287–295 行要求客户端连接 URI 必须为/v1/messages/json,否则发送invalid_uri错误并以 1008 关闭——这是接入外部 WebSocket 客户端时必须注意的协议细节。
实战:在 cluster-layout.zeek 中使用这些类型
集群框架的使用约定(见 main.zeek 头部注释与load.zeek):
- 在 Zeek 脚本搜索路径(ZEEKPATH)中放置一个名为
cluster-layout.zeek的文件,其中只应包含Cluster::nodes的定义,避免加载其他脚本或用redef修改除Cluster::nodes以外的内容,以免因加载过早引发循环加载问题; - 通过环境变量
CLUSTER_NODE指定当前实例扮演的节点名(等价于设置Cluster::node); - 以
@load base/frameworks/cluster方式加载框架。
一个使用上述类型的典型拓扑定义示例(ZeekControl 会自动生成类似文件):
# cluster-layout.zeek redef Cluster::nodes = { ["manager"] = [$node_type=Cluster::MANAGER, $ip=127.0.0.1, $p=5000/tcp], ["worker-1"] = [$node_type=Cluster::WORKER, $ip=127.0.0.1, $p=5001/tcp, $manager="manager"], ["worker-2"] = [$node_type=Cluster::WORKER, $ip=127.0.0.1, $p=5002/tcp, $manager="manager"], ["logger"] = [$node_type=Cluster::LOGGER, $ip=127.0.0.1, $p=5003/tcp], };若要让外部 WebSocket 客户端接入,可在启动脚本中调用Cluster::listen_websocket(),例如:
event zeek_init() { local opts = Cluster::WebSocketServerOptions( $listen_addr = 0.0.0.0, $listen_port = 9000/tcp, $max_event_queue_size = 64, $ping_interval = 10 secs ); Cluster::listen_websocket(opts); }如需启用 TLS,则补充tls_options:
local tls = Cluster::WebSocketTLSOptions( $cert_file = "/path/to/cert.pem", $key_file = "/path/to/key.pem", $enable_peer_verification = T, $ca_file = "/path/to/ca.pem" );注意listen_addr与listen_host二选一,TLS 的cert_file/key_file必须成对设置,ping_interval取负值可禁用 ping。
小结
Cluster::types.zeek是集群框架的"公共契约":NodeType定义了六种节点角色,Node/NamedNode描述节点拓扑,Event承载 pub/sub 事件,NetworkInfo/EndpointInfo描述端点,而WebSocketServerOptions/WebSocketTLSOptions连同两个默认常量(队列上限 32、ping 间隔 5 秒)构成了 WebSocket 外部接入的完整配置面。这些定义不仅在脚本层被 main.zeek 与load.zeek 直接消费,也精确映射到 C++ 后端 src/cluster/Manager.cc 与 src/cluster/websocket/WebSocket.cc 的实现细节(如WebSocketEventDispatcher:<host>:<port>指标标签、/v1/messages/json路径约束),理解它们即可对集群拓扑与 WebSocket 接入行为建立端到端的把握。
- 网络安全
- 网络
- IDS
【免费下载链接】zeek
Zeek is a powerful network analysis framework that is much different from the typical IDS you may know.
相关推荐
Hapi.js 服务器配置与核心API详解
Hapi.js 服务器配置与核心API详解 概述 Hapi.js 是一个用于构建应用程序和服务的强大 Node.js 框架,以其配置优先的理念和丰富的功能集著称
后端HashiCorp Nomad 服务器配置详解:构建高可用集群的核心参数解析
HashiCorp Nomad 服务器配置详解:构建高可用集群的核心参数解析 什么是Nomad服务器模式 Nomad作为现代化的集群调度器,其服务器模式是整个系
任务调度云原生运维后端如何一抬手锁屏、通知同步到手腕:Essentials × WearOS 智能手表完整指南
如何一抬手锁屏、通知同步到手腕:Essentials × WearOS 智能手表完整指南 Essentials ( README https://link.gi
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考