LEEF格式:键值对与自定义属性
说实话,刚开始接触DLP日志的时候,我总觉得格式是个小问题。
能看懂不就行了?后来被坑过几次才明白——格式不对,解析全废。
今天咱就聊聊LEEF,这个在日志领域里挺常见,但又容易被忽视的格式。
LEEF到底是什么?
LEEF,全称是Log Event Extended Format。
翻译过来就是“日志事件扩展格式”。
它最早由IBM推出来,现在已经是很多安全产品的标配了。
我个人习惯把它理解为一种“有结构的K=V串”。
说白了,就是把日志里的关键信息,用键值对的方式组织起来。
这样做的好处很明显:机器好解析,人也看得懂。
举个例子,一条原始的DLP告警可能是这样的:
Sep 27 10:23:45 mailserver dlp_agent[12345]: 用户张三 发送了 一份包含信用卡号的文档 到 外部邮箱
这种日志,你让机器去提取“用户名”和“操作类型”,得写一堆正则。
换成LEEF格式以后呢?
LEEF:1.0|DLP_Agent|3.2.1|1001|DataLeakAlert|devTime=2024-09-27T10:23:45Z|srcUserName=张三|action=emailSend|object=信用卡号文档|target=external@example.com
看到没?每个字段都清清楚楚。
解析起来只需要按竖线切分,然后读键值对就行了。
我在项目中遇到过不少团队,一开始嫌麻烦不用LEEF,结果后期写解析器写到崩溃。
键值对结构:最核心的部分
LEEF格式的主体,就是键值对。
它的基本规则非常直白:
- 键和值用等号
=连接 - 多个键值对之间用制表符
\t分隔 - 键名不能包含空格和等号
- 值如果包含空格,不需要加引号——制表符就是天然的边界
嗯,这里要注意一点。
我曾经踩过一个坑:值里面如果包含等号,解析器会傻掉。
比如你记录了一个URL:url=https://example.com?key=value
解析器会把第二个等号也当成键值分隔符。
解决方案也很简单:把等号做一下URL编码,或者用其他分隔符代替。
%20,等号变成%3D。
虽然麻烦一点,但解析的时候不会出幺蛾子。
LEEF的固定结构
一条完整的LEEF日志,其实分两个部分:
第一部分:管道符分隔的头部
这部分是固定的,包含7个字段:
| 位置 | 字段 | 说明 |
|---|---|---|
| 1 | LEEF:1.0 |
版本号,目前主流是1.0 |
| 2 | 设备厂商 | 比如 DLP_Agent |
| 3 | 产品版本 | 比如 3.2.1 |
| 4 | 事件ID | 设备内部唯一编号 |
| 5 | 事件名称 | 比如 DataLeakAlert |
| 6 | 严重级别 | 可选,一般是1-10 |
| 7 | 时间戳 | 可选,Unix时间或ISO格式 |
第二部分:键值对主体
头部之后,跟着的就是一串键值对。
这部分完全由设备自己定义,灵活性很高。
你想想看,这就是LEEF最强大的地方——标准化头部保证通用性,自定义键值对保证灵活性。
LEEF:1.0|DLP_Inc|2.5.0|8080|PolicyViolation|5|devTime=2024-09-27T10:23:45Z srcUserName=张三 policyName=PCI-DSS matchKeyword=信用卡 riskScore=85注意!键值对之间用的是制表符,不是空格。
自定义属性:LEEF的精髓
自定义属性这部分,说实话,是LEEF最灵活也最容易翻车的地方。
我记得有一次帮客户排查日志丢失问题,发现他们自定义了一个叫“user@department”的属性。
解析器看到@符号直接报错,整条日志就丢掉了。
那自定义属性到底该怎么起名字?
我个人建议遵循几个原则:
- 无特殊符号:只用字母、数字和下划线。别整什么横杠、点号、@符号。
- 长度适中:别用
user_department_and_role_info这么长的键名,本身日志行就有长度限制。 - 命名一致:要么全小写,要么驼峰,别混着来。
- 签名备注:如果你有几十个自定义属性,建议做个文档记录每个键的含义。我见过最惨的情况——离职同事写了几百个自定义属性,没留文档,新来的人完全不知道怎么解析。
devTime、src、dst)误读成头部字段。
所以建议:自定义属性统一加个前缀,比如my_、ctx_。
这样永远不会跟标准属性撞车。
通用属性vs自定义属性
LEEF里有一组通用属性,算是“行业约定”。
比如devTime、srcUserName、dstUserName、fileName、filePath等等。
但注意——这些只是约定,不是强制要求。
我自己做DLP解析器的时候,处理策略是这样的:
- 先匹配通用属性,按标准逻辑解析
- 剩下的全都归为自定义属性,按字符串原样存储
- 最后给运维人员留一个“自定义属性映射表”,让他们自己去配
这样做的好处是:不管设备厂商怎么加新属性,解析器核心代码不用改。
只改配置文件就行。
数据流全景
用一张图来总结LEEF格式的核心结构:
实战中的踩坑与建议
用LEEF这么多年,我总结了几条血泪教训:
- 字符串长度:有的设备限制单条LEEF日志不超过4096字节。自定义属性太多太长,很容易截断。
- 中文编码:我用过的设备里,有的用UTF-8,有的用GBK。解析之前一定要确认编码,不然中文全变乱码。
- 时间格式:虽然LEEF不强制时间戳格式,但我强烈建议统一用ISO8601,别用Unix毫秒时间戳。人看着难受,解析也容易出精度问题。
- 属性顺序:LEEF本身不关心键值对的顺序,但很多日志平台会按出现顺序渲染。所以核心属性放在前面,辅助属性放后面,查日志的时候一眼就能看到关键信息。
最后多说一句。
LEEF最大的价值不是“格式有多强”,而是“大家都认”。
你只要按规范输出LEEF,市面上主流的SIEM、日志平台基本都能直接解析。
比你自己定义一套私有格式,省事太多了。