网络安全网络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 在 7.1 版本起内置了一个基于 Spicy 的 PostgreSQL 协议分析器用于从 5432/tcp 端口捕获的流量中还原 PostgreSQL 会话的完整行为登录用户与数据库、启动参数、SQL 查询、认证方式、错误信息以及返回行数。本文以 postgresql.log 参考文档 为核心结合 Spicy 协议解析器、Zeek 日志脚本 与 btest 回归测试 的源码证据讲解postgresql.log的字段语义、SQL 查询日志化流程、TLS 升级交接机制以及如何运行示例、复现测试与定制日志内容。读完本文你将能独立解读和部署 Zeek 的 PostgreSQL 分析能力并为自己的环境扩展日志字段。postgresql.log 是什么postgresql.log是 Zeek 为 PostgreSQL 协议会话单独生成的日志流。它与传统的conn.log连接四元组、字节统计互补conn.log只告诉你“谁和谁在 5432 端口上通信”而postgresql.log告诉你“会话里实际发生了什么”——谁登录了、连的是哪个数据库、客户端程序是什么、执行了哪些 SQL、是否成功、返回了多少行。从源码结构看该分析器由两层组成Spicy 解析层src/analyzer/protocol/postgresql/postgresql.spicy负责按 PostgreSQL 3.0 协议参考 官方协议文档逐字节解析客户端Frontend与服务端Backend消息Zeek 事件与日志层scripts/base/protocols/postgresql/main.zeek把解析结果映射为PostgreSQL::Info记录并写入日志流同时提供log_postgresql钩子供脚本层二次加工。分析器通过 Analyzer::register_for_ports 在zeek_init时注册到默认端口{ 5432/tcp }定义于 main.zeek 的ports常量可重定义。日志流本身由Log::create_stream(PostgreSQL::LOG, ...)创建路径名为postgresql。运行示例与日志样例在编译启用了 Spicy 的 Zeek 环境中可以用官方测试抓包直接复现文档中的示例$ zeek -C LogAscii::use_jsonT -r testing/btest/Traces/postgresql/psql-create-insert-select-delete-drop.pcap $ jq postgresql.log其中-C表示不校验校验和测试抓包常需该选项LogAscii::use_jsonT让 ASCII 写入器输出 JSON 格式便于用jq查看-r pcap离线读取抓包。文档中的示例输出节选展示了CREATE TABLE与INSERT两条简单查询产生的日志{ ts: 1725368066.79174, uid: C68Wxi3EStaTmxaUVl, id.orig_h: 127.0.0.1, id.orig_p: 40190, id.resp_h: 127.0.0.1, id.resp_p: 5432, user: postgres, database: postgres, application_name: psql, frontend: simple_query, frontend_arg: CREATE TABLE IF NOT EXISTS t (i int, s varchar, t time);, success: true, rows: 0 }第二条 INSERT 记录的ts、uid、user等字段与上一条相同区别仅在于frontend_arg中的 SQL 文本。注意user、database、application_name来自客户端连接启动时的 StartupMessage因此同一条连接上的后续查询记录都会携带这些上下文信息源码见 main.zeek 的startup_parameter事件处理。日志字段详解日志列的完整定义位于 scripts/base/protocols/postgresql/main.zeek 的PostgreSQL::Info记录。文档用:zeek:see:指令提示读者以该记录为准下面逐一说明字段类型说明tstime活动发生时的时间戳uidstring连接的唯一 IDidconn_id连接四元组源/目的 IP 与端口userstringStartupMessage 中的用户名databasestringStartupMessage 中的数据库名application_namestringStartupMessage 中的客户端应用名如 psqlfrontendstring客户端发送的命令或消息类型如startup、simple_query、terminate、ssl_requestfrontend_argstring该命令的参数如 SQL 文本backendstring服务端返回的消息类型如auth_ok、error、ssl_replybackend_argstring服务端回复的参数如认证方式、错误详情successbool登录或查询是否成功rowscount返回或影响的行数其中ts、uid、id为log必填字段其余字段均为optional log即“出现才记录”未出现时在 TSV 输出中为-参见下方基线示例。字段的填充时机字段填充逻辑散落在 main.zeek 的多个事件处理器中startup_parameter把user、database、application_name存入连接状态postgresql_state待日志写出时再复制进Infoemit_log函数见 main.zeeksimple_query设置frontendsimple_query与frontend_arg查询文本并把行数清零data_row每次收到一条 DataRow 消息就对rows计数main.zeekready_for_query在查询结束时写出日志若此前无人显式设置success则根据事务状态I空闲/T事务中判定为成功E失败事务块判为失败main.zeekerror_response设置backenderror、successF并写出日志main.zeek。错误与提示信息的可读化服务端返回的 ErrorResponse / NoticeResponse 中每个“标识字段”是一字节码加值。Zeek 在 scripts/base/protocols/postgresql/consts.zeek 中定义了error_ids映射表把S、V、C、M、D、H、P、p、q、W、s、t、c、d、n、F、L、R等码翻译成SeverityLocalized、Code、Message、Detail、Hint、Schema、Table等可读名称未识别的码则回退为UnknownErrorIdcode。认证请求的auth_ids表consts.zeek把认证标识 2/3/5/7/8/9/10/11/12 分别映射为KerberosV5、CleartextPassword、MD5Password、GSSAPI、GSSAPIContinue、SSPI、SASL、SASLContinue、SASLFinal。因此一次失败的查询在日志中会呈现为类似simple_query INSERT INTO t VALUES (now(), now(), now()); error SeverityLocalizedERROR,SeverityERROR,Code42804,Messagecolumn i is of type integer but expression is of type timestamp with time zone,HintYou will need to rewrite or cast the expression.,Position23,Fileparse_target.c,Line586,RoutinetransformAssignedExpr F -以上内容来自 psql-insert-fail-drop-fail 的基线文件它同时展示了同一连接上一条成功查询DROP TABLE IF EXISTS t;附带 NOTICE 提示、successT、rows0与失败查询的完整对比以及会话结束时terminate消息产生的记录。SQL 查询如何被记录一次查询的完整生命周期结合 postgresql.spicy 与 main.zeek一条SELECT/INSERT等简单查询的日志生命周期如下StartupMessage 解析客户端发送 8 字节长度 协议版本号 若干StartupParameteruser、database、application_name等。Spicy 单元StartupMessage要求主版本号为 3协议 3.0参数由正则[-_\/A-Za-z0-9]与[\x20-\x7e]约束。解析完成后通过%done触发 zeek::confirm_protocol() 确认协议。FrontendMessage 分发客户端后续每个消息以 1 字节类型码开头FrontendMessage单元按类型码分发——Q为 SimpleQuery、X为 Terminate、p为认证响应PasswordMessage/SASLInitial 等暂仅透传原始字节其余类型记为not_implementedpostgresql.spicy。事件上抛Spicy 侧通过 postgresql.evt 把解析结果映射为 Zeek 事件例如SimpleQuery→PostgreSQL::simple_query($conn, query)、ReadyForQuery→PostgreSQL::ready_for_query($conn, transaction_status)。Zeek 侧状态机simple_query记录查询文本data_row累计行数ready_for_query判定成败、写入rows并调用emit_log把Info记录写进日志main.zeek。连接收尾terminate事件写出最后一条记录即使连接异常结束也会由连接移除钩子finalize_postgresql兜底写出残留记录main.zeek。btest 测试 psql-create-insert-select.zeek 正是对这一流程的端到端验证它用zeek -b -r ...psql-create-insert-select-delete-drop.pcap跑完整会话并把conn.log与postgresql.log的关键列与基线比对。TLS 升级SSLRequest 与握手交接PostgreSQL 协议允许客户端在连接建立后立即请求把会话升级为 TLS。Zeek 的分析器完整处理了这一机制并把后续加密流量交接给 Zeek 的 TLS 分析器。这解释了文档示例中conn.log的service字段为何是postgresql,ssl一个连接先被识别为 PostgreSQLTLS 握手后被追加为 ssl 服务。文档给出了使用 AWS 抓包psql-aws-ssl-preferred.pcap的复现命令$ zeek -C LogAscii::use_jsonT -r testing/btest/Traces/postgresql/psql-aws-ssl-preferred.pcap $ jq postgresql.log输出中的 SSL 交接记录为{ ts: 1670520068.267888, uid: CAcbxM1ou0N1V2cGpe, id.orig_h: 192.168.123.132, id.orig_p: 39910, id.resp_h: 52.200.36.167, id.resp_p: 5432, frontend: ssl_request, backend: ssl_reply, backend_arg: S, success: true }而conn.log中同一 uid 记录显示{ ts: 1670520068.15752, uid: CAcbxM1ou0N1V2cGpe, id.orig_h: 192.168.123.132, id.orig_p: 39910, id.resp_h: 52.200.36.167, id.resp_p: 5432, proto: tcp, service: postgresql,ssl, duration: 0.931433916091919, orig_bytes: 786, resp_bytes: 4542, ... }TLS 交接的源码实现Spicy 侧在 postgresql.spicy 定义了Context结构通过ssl_frontend_state/ssl_backend_state两个枚举在客户端与服务端两个解析单元之间同步 SSL 状态客户端首个消息若是 8 字节长度 魔数80877103即 SSLRequestversion_or_magic钩子会置ssl_frontend_state Requestedpostgresql.spicy并抛出ssl_request事件服务端首个字节若是S或NMaybeBackendSSL单元的ssl_byteS表示同意升级此时把共享的SSLSink连接到两端加密后的所有字节被当作 TLS 数据转交N表示拒绝则继续用PlainBackendMessages解析明文postgresql.spicy由于乱序、重组等情况下客户端数据可能先于服务端响应到达两端各自维护buffered缓冲上限MAX_BUFFERED 4个 chunk待 SSL 状态确定后再把缓冲数据写入正确的 sinkpostgresql.spicyZeek 侧在 postgresql_zeek.spicy 中SSLSink的%init调用zeek::protocol_begin(SSL)、每个 chunk 调用zeek::protocol_data_in(...)从而把加密流无缝喂给 Zeek 内置的 TLS 分析器看到ssl_byte时同样会zeek::confirm_protocol()postgresql_zeek.spicy。因此文档中的frontendssl_request、backendssl_reply、backend_argS、successtrue正是对ssl_request/ssl_reply事件处理逻辑main.zeek的直接映射ssl_reply把backend_arg设为服务端字节success (b S)。测试目录中还提供了psql-aws-ssl-disable.pcap、psql-aws-ssl-require.pcap及其 15432 端口变体testing/btest/Traces/postgresql覆盖disable拒绝升级继续明文解析与require强制升级两种典型配置。动态端口探测DPD 签名分析器并不只依赖静态端口号还内置了动态协议探测DPD签名位于 scripts/base/protocols/postgresql/dpd.sigdpd_postgresql_client_sslrequest匹配客户端 SSLRequest 魔数\x00\x00\x00\x08\x04\xd2\x16\x2f即长度 8 80877103dpd_postgresql_server_ssl_confirm要求对端匹配上述客户端签名且服务端首字节为[SN]命中后启用PostgreSQL分析器dpd_postgresql_client_startup_3_x匹配 4 字节长度 版本\x00\x03\x00 256 字节内的user\x00参数用于识别 3.x 协议 StartupMessagedpd_postgresql_server_any_response要求对端匹配客户端 startup 签名服务端首字节为可打印消息类型且长度字段以\x00\x00开头命中后启用分析器。这意味着即使 PostgreSQL 跑在非标准端口上Zeek 也能通过内容特征将其识别出来。btest 中的 http-on-port-5432.zeek 与 mysql-on-port-5432.zeek 则验证了反向场景HTTP/MySQL 流量即使出现在 5432 端口也不会被误判为 PostgreSQL对应抓包位于 testing/btest/Traces/postgresql。错误与异常处理解析层对畸形输入有明确的防御与拒绝策略全部体现在 postgresql_zeek.spicyStartupMessage解析出错如主版本号非 3、长度过小→zeek::reject_protocol(error while parsing PostgreSQL StartupMessage: ...)FrontendMessage/BackendMessage出错 →zeek::reject_protocol(...)。Spicy 单元还做了多道前置校验StartupMessage.length 9、FrontendMessage.length 4、AuthenticationOK长度必须为 4否则抛 “AuthenticationOK with wrong length”见 postgresql.spicy、ReadyForQuery的事务状态必须是I/T/E之一等。对应的测试 bad-startup-message.zeek、bad-backend-message.zeek 与抓包 bad-startup-message-1.pcap、bad-backend-message-1.pcap 一起覆盖了这些异常路径确保分析器拒绝而非误报。使用与定制建议加载与启用分析器随默认脚本集init-default.zeek会加载base/protocols/postgresql自动启用如需显式加载可load base/protocols/postgresql。端口集合可通过重定义PostgreSQL::ports扩展例如redef PostgreSQL::ports { 15432/tcp };测试中的 15432 变体即演示了非标准端口场景。调整输出PostgreSQL::Info是标准日志记录所有字段带log标记可在脚本中用redef或事件处理器增删字段log_postgresql事件main.zeek是接入自定义后处理的默认钩子。行数统计语义rows仅在发生 DataRow 计数时输出data_row事件main.zeek对于CREATE TABLE这类无数据行的语句即使成功也显示rows0。如需区分“未统计”与“0 行”注意该字段是optional未出现时为-。排错路径若线上抓包无法识别优先检查是否启用了 Spicybtest 测试带TEST-REQUIRES: ${SCRIPTS}/have-spicy前置条件再对照 DPD 签名确认流量形态TLS 场景可结合conn.log的service列与ssl.log交叉验证。总结postgresql.log让 Zeek 从“看到连接”进化到“看懂会话”登录上下文、SQL 语句、错误细节、行数与 TLS 升级状态全部结构化落盘且基于 Spicy 的解析器在协议校验、乱序缓冲、加密交接和畸形输入防御上都有完整实现。本文涉及的源码与测试路径可直接在仓库中进一步研读Spicy 解析器、事件映射、日志与状态机、错误码映射、DPD 签名以及 btest 测试脚本 与对应的 基线输出。赞分享网络安全网络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 LDAP 协议日志深度解析ldap.log 与 ldap_search.log 的字段、配置与底层原理Zeek LDAP 协议日志深度解析ldap.log 与 ldap_search.log 的字段、配置与底层原理 轻量目录访问协议Lightweight D网络安全网络IDSnhost 背后的 PostgreSQL 线协议pgproto3 v3 协议编解码器深度解析nhost 背后的 PostgreSQL 线协议pgproto3 v3 协议编解码器深度解析 pgproto3 是 Go 生态中广泛使用的 PostgreSQ后端认证鉴权数据库无服务开发工具云原生Zeek协议分析器终极指南从TCP/UDP到应用层协议的深度解析Zeek是一款强大的 网络分析框架 它通过深度协议分析能力让您能够全面掌握网络流量中的每一个细节。无论您是网络安全新手还是资深工程师掌握Zeek的协议分析网络安全网络IDS上一篇librsync常见问题解答解决开发与使用中的痛点难题下一篇PowerShell-Docs社区指南如何有效获取帮助和分享经验创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考