日志格式详解:Syslog、JSON、CEF、W3C扩展格式
日志格式这东西,说白了就是不同设备“说话”的方式。你想想看,一台思科路由器、一台Windows服务器、一个Web应用,它们吐出来的日志字段长得完全不一样。我在刚开始做CA对接时,就被这些格式搞晕过。后来发现,只要搞懂四种主流格式——Syslog、JSON、CEF、W3C扩展格式,基本就能覆盖90%的场景。
嗯,这节我们就挨个拆开看看,每个格式的字段到底什么意思,怎么解析,以及——最容易踩的坑在哪儿。
1. Syslog格式
Syslog是老牌日志协议了,网络设备、Unix/Linux服务器基本都在用。它的格式有两个版本:RFC 3164(老版)和RFC 5424(新版)。我在项目中遇到最多的还是老版3164。
一个典型的Syslog消息长这样:
<34>Oct 11 22:14:15 mymachine.example.com su: 'su root' failed for lonvick on /dev/pts/8
字段拆开看:
- PRI(优先级):尖括号里的数字,34。它由Facility×8 + Severity计算得出。Facility表示来源,比如0是内核,1是用户级;Severity是紧急程度,从0(紧急)到7(调试)。我个人习惯是直接算:34÷8=4余2,Facility=4(auth),Severity=2(critical)。
- TIMESTAMP:时间戳,格式是“Mmm dd hh:mm:ss”。注意没有年份!这是老Syslog的头号坑。
- HOSTNAME:主机名。我记得有一次排查问题时,发现主机名被截断了——设备配置的hostname超过64字节,结果后面的字符全丢了。嗯,采集时得小心。
- MESSAGE:消息体,包含TAG(进程名/ID)和内容。比如这里的“su: 'su root' failed...”
新版RFC 5424增加了STRUCTURED-DATA字段,用键值对存储结构信息。但说实话,真正支持完整5424的设备还是少。我一般会优先检测5424格式,不行再回退到3164。
2. JSON格式
JSON嘛,现在最流行的结构,Web应用、API网关、微服务基本都用它。一句话:键值对、可嵌套、人类和机器都读得懂。
看个例子:
{
"timestamp": "2025-10-11T22:14:15Z",
"host": "api-gateway-01",
"severity": "ERROR",
"service": "auth-service",
"message": " validation failed",
"context": {
"user_id": "u12345",
"ip": "192.168.1.1",
"attempts": 3
}
}
字段含义:
- timestamp:ISO 8601格式,带时区。比Syslog靠谱多了。
- severity:日志级别。常见的有DEBUG、INFO、WARN、ERROR、FATAL。
- context:嵌套对象。这是JSON格式最爽的地方——可以把关联信息打包在一起,解析时直接取用。
我建议这样处理:采集JSON日志时,尽量保持完整的嵌套结构。别急着摊平!保留context字段可以方便后续关联分析。比如上面的例子,看到ERROR级别,直接就能拿到user_id和IP,省得再查一次。
JSON格式的坑在哪?主要是字段名不统一。有的用“timestamp”,有的用“@timestamp”或“time”。我在对接一个第三方系统时,发现它的时间字段叫“event_time”——没标准。所以,你得在采集层做字段映射。
3. CEF格式(Common Event Format)
CEF,全称Common Event Format,是ArcSight搞出来的,安全设备特别喜欢用。为什么?因为它能同时保留结构化字段和自定义扩展字段。说起来,我最早接触CEF是在做SIEM对接时,一看到这个格式就觉得——嗯,这才是为安全事件量身定做的。
一个CEF消息长这样:
CEF:0|Security|threatmanager|1.0|100|Detected a port scan|5|src=10.0.0.1 dst=10.0.0.2 dpt=80
字段拆解:
| 字段位置 | 字段名 | 示例值 | 解释 |
|---|---|---|---|
| 1 | Version | 0 | CEF版本号,通常是0 |
| 2 | Device Vendor | Security | 设备厂商,比如Cisco、Palo Alto |
| 3 | Device Product | threatmanager | 产品名称 |
| 4 | Device Version | 1.0 | 产品版本 |
| 5 | Signature ID | 100 | 事件标识符,每个事件类型对应一个ID |
| 6 | Name | Detected a port scan | 事件名称,人类可读 |
| 7 | Severity | 5 | 严重程度,0-10,10最严重 |
最后面的就是扩展字段(Extension),用空格分隔键值对。key可以自定义,但CEF有一组标准key,比如src、dst、dpt、spt、proto、cs1、cs2等(cs表示custom string)。
4. W3C扩展格式
W3C扩展格式主要出现在Web服务器日志里,IIS、Azure Application Gateway都在用。它本质上是一种制表符或空格分隔的文本,但有两个特点:字段可自定义、前缀带标记。
典型例子:
#Fields: date time cs-uri-stem cs-uri-query sc-status
2025-10-11 14:15:16 /api/login user=admin 200
注意看:第一行是#Fields:声明,告诉解析器后面的字段名分别是什么。每行日志按顺序对应这些字段。我建议别跳过#Fields头!有些设备会在不同的日志里混用不同的字段集合,不看声明就可能对不上。
常见字段前缀:
- cs:Client-to-Server,比如cs-uri-stem(请求路径)、cs-method(GET/POST)
- sc:Server-to-Client,比如sc-status(响应码)、sc-bytes(响应大小)
- time-taken:请求耗时,单位毫秒
- c-ip:客户端IP
格式的灵活性是优点也是缺点。不同Web服务器声明的字段名差异很大。你拿到一份W3C日志,最好先读一下#Fields头,动态构建解析规则。我有个项目就是靠这个技巧一次性兼容了三个版本的IIS日志。
四种格式的核心差异
| 格式 | 结构化程度 | 可读性 | 扩展性 | 解析复杂度 |
|---|---|---|---|---|
| Syslog (RFC 3164) | 低,消息体无固定结构 | 中 | 差,全靠自定义 | 高,需正则+启发式 |
| JSON | 高,嵌套支持好 | 高 | 强,字段可随意添加 | 中,需字段映射 |
| CEF | 高,头部7字段固定+扩展 | 中 | 强,扩展字段丰富 | 中,注意转义 |
| W3C扩展格式 | 中,字段由#Fields声明 | 中 | 强,可自定义字段集 | 中,需动态解析声明头 |
下面这张图展示了四种日志格式在CA采集场景下的定位关系。你一看就明白,在不同场景下该优先考虑哪种格式。
CA采集中的格式选择建议
说了这么多,该选哪种格式来对接CA?我个人的经验是:看数据源,看解析复杂度,看字段覆盖率。
- 如果是网络设备或老系统:大概率是Syslog。优先尝试5424格式解析,不行就回退3164。重点处理时间戳和消息体。
- 如果是Web应用或微服务:JSON是首选。解析方便,扩展灵活。记得处理好嵌套对象和字段映射。
- 如果是安全设备(防火墙、IDS/IPS、DLP):大部分用CEF。直接按标准解析头部7个字段,扩展字段按位置处理。
- 如果是IIS或Azure网关:W3C扩展格式。一定要读#Fields头,动态生成解析器。
一个小技巧:遇到不确定的格式,可以写一个格式嗅探器。先看首字符是不是"<",再看有没有"CEF:0|",接着检查是不是"#Fields:"开头的声明,最后尝试解析成JSON。我在一个项目中靠这个嗅探器,一天内接入了5种不同设备,效率翻番。
最后提醒一点:不管哪种格式,都要注意字段值的转义和长度限制。我见过Syslog消息体里包含换行符导致解析中断的,也见过JSON里包含特殊字符导致序列化失败的。嗯,采集层一定要做好异常处理。