4. 日志标准化与格式化:从混乱到有序的第一步

说实话,我刚进安全审计这个领域时,面对的第一道坎就是日志格式。那时候各厂商的设备凑在一起,日志长得五花八门——有的用竖线分隔,有的用逗号,有的干脆是自由文本。你想想看,如果连格式都不统一,告警规则怎么写?分析工具怎么识别?

所以这一章,咱们就聊聊日志标准化。说白了,就是把各路“方言”翻译成统一的“普通话”。

4.1 常见日志格式解析

目前业界主流的标准化日志格式有三种:JSON、CEF 和 LEEF。我建议你至少掌握前两种,第三种了解即可。

4.1.1 JSON 格式

JSON 是目前最通用的格式。它的好处是结构清晰,解析简单,几乎所有现代编程语言都原生支持。

{
  "timestamp": "2024-03-15T10:30:00Z",
  "src_ip": "192.168.1.100",
  "dst_ip": "10.0.0.5",
  "action": "BLOCK",
  "rule_name": "SQL注入防护",
  "severity": 7
}

我个人习惯把 JSON 作为首选输出格式。为什么呢?因为它扩展性好。需要加字段?直接往里塞一个 key-value 就行,不会破坏已有结构。

小提示:JSON 虽然好,但注意控制嵌套深度。超过 4 层的嵌套会显著降低解析性能,尤其是在高吞吐场景下。

4.1.2 CEF 格式(Common Event Format)

CEF 是 ArcSight 推广的格式,在传统 SIEM 系统里非常常见。它的样子是这样的:

CEF:0|安全公司|产品名|版本号|事件ID|事件名|严重程度|
src=192.168.1.100 dst=10.0.0.5 act=BLOCK

CEF 的核心是“管道符+键值对”组合。我在项目中遇到过一家银行,他们的旧系统只认 CEF,硬是把 JSON 转成 CEF 才接进去。

4.1.3 LEEF 格式(Log Event Extended Format)

LEEF 是 IBM QRadar 的格式,和 CEF 类似,但语法略有不同:

LEEF:2.0|IBM|QRadar|7.2.0|事件名|严重程度|
src=192.168.1.100	dst=10.0.0.5	act=BLOCK

LEEF 我见得少,主要是在 QRadar 集群里必须用它。如果你不用 QRadar,这个格式可以忽略。

4.1.4 三种格式对比

特性 JSON CEF LEEF
可读性 高 中 中
解析性能 中 高 高
扩展性 强 一般 一般
主流 SIEM 支持 全部 ArcSight、Splunk QRadar
推荐场景 新系统、微服务 传统安全设备 IBM 体系

我的建议:新建系统优先用 JSON。如果是和旧设备对接,看看对方支持 CEF 还是 LEEF,尽量往 JSON 转。

4.2 字段映射

格式统一之后,下一步就是字段映射。什么叫字段映射?就是让不同设备里意思一样的字段用同一个名字。

举个例子:

  • 防火墙 A 里叫 source_ip
  • 防火墙 B 里叫 src
  • 漏扫设备里叫 client_addr

这三个字段实际上都表示“源IP”。不做映射的话,你写规则就要写三遍。做了映射,统一叫 src_ip,一条规则搞定。

我以前在一个 SOC 项目里遇到过一个坑:某厂商的日志里,severity 字段的值范围是 1-5,另一家是 0-100。不映射的话,直接就告警混乱了。

4.2.1 通用字段映射表(建议版本)

标准化字段名 含义 常见别名 数据类型
timestamp 事件时间 time、date、@timestamp ISO8601 字符串
src_ip 源 IP 地址 source_ip、src、client_addr IPv4/IPv6 字符串
dst_ip 目标 IP 地址 dest_ip、dst、target_addr IPv4/IPv6 字符串
src_port 源端口 source_port、sport 整数 (0-65535)
dst_port 目标端口 dest_port、dport 整数 (0-65535)
action 处理动作 act、result、verdict 枚举 (ALLOW/BLOCK/LOG)
severity 严重程度 priority、level、event_severity 整数 (0-10)
event_name 事件名称 name、event_type、signature 字符串
log_source 日志来源设备 device_name、hostname、source 字符串
raw_message 原始日志内容 message、raw_log 字符串
注意:字段映射表不是一成不变的。每接入一种新设备,可能就要更新一次。我建议把映射表放在配置中心,不要硬编码在代码里。

4.3 标准化规范设计

有了格式和字段映射,还得有一整套规范来约束。不然每人按自己的理解来,最后又是一团乱麻。

我总结了一套“四层规范”的设计方法:

层级 规范内容 示例
L1 格式层 日志必须使用 JSON 严禁使用 CSV、自定义分隔符
L2 字段层 必选字段必须存在 timestamp、src_ip、action 不能为空
L3 取值层 枚举字段必须用指定值 action 只能是 ALLOW/BLOCK/LOG
L4 命名层 字段名采用 snake_case 用 user_name 不用 userName

4.3.1 规范设计原则

  • 最小完备原则:字段数量够用就行,别什么都往里塞。我记得有个项目,一个日志里塞了 50 多个字段,解析和存储都炸了。
  • 向前兼容:新增字段不能改变已有字段的含义。你想想看,如果某天把 severity 从“数字越大越严重”改成“数字越小越严重”,那之前的规则全得重写。
  • 统一时间格式:时间戳必须用 ISO8601,带时区。我以前见过用 Unix 时间戳、用 yyyyMMdd 格式的,解析时头都大了。
  • 避免特殊字符:字段名和值里不要出现换行符、制表符、双引号。JSON 里虽然能转义,但你手动查日志时会疯掉。

4.3.2 避坑指南

我曾经接手过一个项目,日志标准化规范都写好了,但落地时发现有些老设备根本改不了格式。后来想了个折中方案:在采集端加一层“日志转换器”,用 Logstash 或 Fluentd 把老格式转成标准 JSON。这个思路你也可以参考。

实操建议:新设备必须按规范输出。旧设备靠转换器兼容。不要幻想所有设备都能改,不现实。

4.4 本章知识体系

下面这张图梳理了日志标准化与格式化的核心逻辑:从原始日志输入,经过格式识别和字段映射,最终输出标准化的日志对象,供后续告警流程使用。

日志标准化与格式化知识体系 JSON 格式 CEF 格式 LEEF 格式 格式对比与选择决策 字段映射机制 四层标准化规范设计 格式层 | 字段层 | 取值层 | 命名层 统一标准化日志 防坑提醒 • 旧设备用转换器兼容 • 字段映射放配置中心 • 避免硬编码字段名

标准化这件事,做好了不容易察觉,做不好处处是坑。但它又是整个告警流程优化的地基——地基不牢,上层的规则再精巧也白搭。我自己踩过的坑,希望你能绕着走。