syslog 协议简介
一 、syslog 协议简介
Syslog[1]常被称为系统日志或系统记录,系统日志通过Syslog进程记录系统的有关事件,也可以记录应用程序运作事件。通过适当配置,还可以实现运行Syslog协议的机器之间的通信。
架构定义
l 生成消息的设备被称作“device”。 l 可以接收消息的设备又将消息转发给了其他设备,称作“relay”。 l 接收消息但不进行转发的设备称作“collector”。通常称作syslog服务器。 l 发出消息或转发消息的设备被称作“sender”。 l 任何接收消息的设备,包括转发或收集都称作“receiver”。
以下架构是有效的 ,在下图中,所有的 relay 都可以透传一些或所有他们接收到的消息。:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
+------+ +---------+
|Device|---->----|Collector|
+------+ +---------+
+------+ +-----+ +---------+
|Device|---->----|Relay|---->----|Collector|
+------+ +-----+ +---------+
+------+ +-----+ +-----+ +---------+
|Device|-->--|Relay|-->--..-->--|Relay|-->--|Collector|
+------+ +-----+ +-----+ +---------+
+------+ +-----+ +---------+
|Device|---->----|Relay|---->----|Collector|
+------+-\ +-----+ +---------+
\ +-----+ +---------+
\-->--|Relay|---->----|Collector|
+-----+ +---------+
+------+ +---------+
|Device|---->----|Collector|
+------+-\ +---------+
\ +-----+ +---------+
\-->--|Relay|---->----|Collector|
+-----+ +---------+
+------+ +-----+ +---------+
|Device|---->----|Relay|---->-------|Collector|
+------+ \ +-----+ / +---------+
\ +-----+ /
\-->--|Relay|-->--/
+-----+
1. syslog协议标准
目前业界存在常见两种syslog日志协议,一个是2009年起草协议RFC5424
,另外一个是2001年的RFC3164
协议。RFC3164 相对来说格式较为简单,能适应大部分使用场景,但是已废弃,RFC5424
已作为Syslog的业界规范。
RFC5424
取代了RFC3164
。RFC5424
是对较早的 syslog 协议的急需的改进。协议的最大变化之一是遵循RFC3339
的时间戳规范。在较旧的协议在时间戳方面没有指定太多。但是在RFC5424收到的日志消息中至少包含年份,月份,日期,小时和秒。
2. RFC5424 协议
RFC 5424 规定消息最大长度为2048个字节,如果收到Syslog报文,超过这个长度,需要注意截断或者丢弃;
截断:如果对消息做截断处理,必须注意消息内容的有消息,很好理解,UTF-8编码,一个中文字符对应3个字节,截断后的字符可能就是非法的;
丢弃:如果该syslog应用的场景下,认为超出长度的就是非法的,则可做丢弃处理;
RFC5424
协议包含以下字段信息,SP表示空格(space)。具体信息可以参考官方协议(https://tools.ietf.org/html/rfc5424)
1
2
# 优先级 版本 空格 时间戳 空格 主机名 空格 应用名 空格 进程id 空格 信息id
PRI VERSION SP TIMESTAMP SP HOSTNAME SP APP-NAME SP PROCID SP MSGID
以下通过几个示例来解释以上字段代表信息:
1
2
3
4
5
6
7
8
9
10
11
12
# Example1:
<34>1 2019-07-11T22:14:15.003Z aliyun.example.com ali - ID47 - BOM'su root' failed for lonvick on /dev/pts/8
"""
PRI: 34
VERSION: 1
TIMESTAMP: 2019-07-11T22:14:15.003Z
HOSTNAME: aliyun.example.com
APP-NAME: ali
PROCID: 无
MSGID: ID47
MESSAGE: 'su root' failed for lonvick on /dev/pts/8
"""
1
2
3
4
5
6
7
8
9
10
11
12
13
# Example-2:
<165>1 2019-07-11T22:14:15.000003-07:00 192.0.2.1 myproc 8710 - - %% It's time to make the do-nuts.
"""
PRI: 165
VERSION: 1
TIMESTAMP: 2019-07-11T05:14:15.000003-07:00
HOSTNAME: 192.0.2.1
APP-NAME: myproc
PROCID: 8710
STRUCTURED-DATA: “-”
MSGID: “-”
MESSAGE: "%% It's time to make the do-nuts."
"""
(1) PRI
PRI为消息优先级,用”<”和”>”括起来,和 RFC3164 中的定义一样。PRI由两部分组成:
Facility (特性):用来表示硬件设备、协议或系统软件的型号。
Severity (严重性):范围为0~7的数字编码,表示了事件的严重程度。
计算方式为:PRI = Facility * 8 + severity; Facility = PRI / 8;Level = PRI % 8;(例如 165表示一条级别为Notice的local4消息)
Facility取值范围及含义如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
Code值 Facility(设施)
-------------------------------------
0 kernel messages 内核消息
1 user-level messages 用户级消息
2 mail system 邮件系统
3 system daemons 系统守护进程
4 security/authorization messages 安全/授权消息
5 messages generated internally by syslogd 由 syslogd 内部生成的消息
6 line printer subsystem
7 network news subsystem
8 UUCP subsystem
9 clock daemon
10 security/authorization messages 安全/授权消息
11 FTP daemon
12 NTP subsystem
13 log audit 日志审计
14 log alert 日志警报
15 clock daemon (note 2)
16 local use 0 (local0)
17 local use 1 (local1)
18 local use 2 (local2)
19 local use 3 (local3)
20 local use 4 (local4)
21 local use 5 (local5)
22 local use 6 (local6)
23 local use 7 (local7)
Level / Severity 取值范围含义:
1
2
3
4
5
6
7
8
9
10
Code值 Level / Severity(严重性)
-----------------------------------------------
0 Emergency: system is unusable 紧急:系统无法使用
1 Alert: action must be taken immediately 警报:必须立即采取行动
2 Critical: critical conditions 严重:严重情况
3 Error: error conditions 错误:错误情况
4 Warning: warning conditions 警告:警告情况
5 Notice: normal but significant condition 注意:正常但重要的情况
6 Informational: informational messages 信息:信息性消息
7 Debug: debug-level messages 调试:调试级别消息
(2) Version
版本用来表示Syslog协议的版本,RFC5424 的版本号为“1”;
(3) TIMESTAMP
TIMESTAMP字段是源自[RFC3339]
的形式化时间戳 ,格式为:yyyy-mm-ddTHH:MM:SS.xxxxxx+/-HH:MM
有以下几个要求:
- “T” “Z”必须大写
- “T”是必须的
- 不能使用闰秒
- 如果无法获取时间戳,必须使用”-“代替
举例如下:
1
2
3
4
5
1985-04-12T23:20:50.52Z # 有效
1985-04-12T19:20:50.52-04:00 # 有效
2003-10-11T22:14:15.003Z # 有效
2003-08-24T05:14:15.000003-07:00 # 有效
2003-08-24T05:14:15.000000003-07:00 # 非法,小数点后超过6位
(4) Hostname
hostname标识发送syslog消息的源主机;优先选用如下几种写法:
- (1) FQDN , 完全全限定域名:同时带有主机名和域名的名称。如:server.mycompany.com
- (2) Static IP address
- (3) Hostname
- (4) Dynamic IP address
- (5) The NILVALUE , 找不到的话用字符 “-“ 表示
(5) App-Name
用于识别产生消息的设备或应用,找不到用”-“代替;
(6) ProcID
进程名称或进程ID,得不到用”-“代替;ProcId常用于分析日志生成进程的连续性,但不做可靠性保证,比如进程重启还是可能会分到一样的进程ID;
(7) MsgID
标识消息类型。例如TCPIN、TCPOUT分别代表TCP数据的流入或流出;如果无法获取数据类型,用”-“代替。 MSGID可根据数据类型用于数据过滤;
(8) Structured-Data
结构化数据;提供了一种记录被良好定义易于被解析的数据的数据格式;可用于记录系统的元信息或应用相关的信息;
可以包含多条结构化数据——”SD-ELEMENT”,如果没有则用”-“代替;
(9) SD-Element
一条结构化数据SD-ELEMENT包含名字(SD-ID)以及多条键值对(SD-PARAM)
(10) SD-ID
一条消息中必须唯一,用于识别SD-Element 的类型和目的; 有两种格式:
IANA定义的 SD-ID
IANA定义,标准规范的SD-ID;不包含@;
自定义的 SD-ID:
支持自定义SD-ID,格式为 name@
;例如 example1@32473;name同样不能包含@ = ] ” 空格 控制符
值得一提的是,32473 在IANA上已被注册作为文档中的举例数字,无法被使用;
(11) SD-Param
键值对;除了自定义的SD-ID外,所有的SD-PARAM也是受限的,在IANA上定义了所有的PARAM-NAME;PARAM-NAME有效范围为一个指定的SD-ID;
- 在不同的SD-ID种两个同名的PARAM-NAME是不同的;
- 一个SD-ELEMENT可能包含多个同样的SD-PARAM;
- 一旦SD-ID以及PARAM-NAME被定义,是不允许修改的,只能通过新增的方式去实现你的需求;
举例如下:
一条自定义的数据类型:exampleSDID@32473
,对应三个参数:
1
[exampleSDID@32473 iut="3" eventSource="Application" eventID="1011"]
两条数据:
1
[exampleSDID@32473 iut="3" eventSource="Application" eventID="1011"][examplePriority@32473 class="high"]
非法数据,两条结构化数据中间有空格 ( 两个 [ ]
之间有空格 );
1
[exampleSDID@32473 iut="3" eventSource="Application" eventID="1011"] [examplePriority@32473 class="high"]
非法数据,SD-ID与 “[” 中间有空格
1
[ exampleSDID@32473 iut="3" eventSource="Application" eventID="1011"][examplePriority@32473 class="high"]
(12) MSG
消息体,无格式要求;如果Syslog应用用UTF-8编码,必须以BOM开头;
3. RFC3164 协议
RFC3164 消息 格式包含以下3个字段信息:<PRI> HEADER MESSAGE
,消息最大长度为 1024 个字节。具体信息可以参考官方协议(https://tools.ietf.org/html/rfc3164)
1
2
# 优先级 空格 信息头 空格 消息内容
PRI HEADER[TIME HOSTNAME] MSG
格式举例:
1
2
3
4
5
6
7
8
9
10
"""
<30>Oct 9 22:33:20 hlfedora auditd[1787]: The audit daemon is exiting.
"""
PRI: 30
HEADER
- TIME: Oct 9 22:33:20
- HOSTNAME: hlfedora
MSG
- TAG: auditd[1787]
- Content: The audit daemon is exiting.
syslog消息主要分为Priority
、Header
以及Message
三个部分,其中Priority是由两个部分组成的——Facility
、Level
。
其中“<30>
”是PRI部分,“Oct 9 22:33:20 hlfedora
”是HEADER部分,“auditd[1787]: The audit daemon is exiting.
”是MSG部分。
(1) PRI
PRI
即Priority(优先级)
和 RFC 5424 中的定义一样,有效值范围为0 - 191。不能有空格、数字前也不能补0。 合法的形式如:<15>
。
PRI值包含两部分信息:Facility
和Level/Severity
。
Facility
值用于判断哪个程序产生了日志信息。Level/Severity
值用于判断严重等级。
计算方法: PRI = Facility * 8 + Level。 Facility = PRI / 8; Level = PRI % 8;
这个数字如果换成2进制的话,低位的3个bit表示 Severity
,剩下的高位的部分右移3位,就是表示Facility
的值。
1
2
3
十进制30 = 二进制0001 1110
0001 1... = Facility: DAEMON – system daemons (3)
.... .110 = Severity: INFO – informational (6)
Facility 字段
Facility 表明该日志消息是由谁产生的,是内核kern?还是用户user?
Facility 的定义如下,可以看出来syslog的Facility是早期为Unix操作系统定义的,不过它预留了User(1),Local0~7 (16~23)给其他程序使用:
设施和严重性值并不规范,但经常使用。下表中对它们的描述仅供参考。
Facility(设施)值必须在 0 到 23 内:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
Code值 Facility(设施)
-------------------------------------
0 kernel messages 内核消息
1 user-level messages 用户级消息
2 mail system 邮件系统
3 system daemons 系统守护进程
4 security/authorization messages 安全/授权消息
5 messages generated internally by syslogd 由 syslogd 内部生成的消息
6 line printer subsystem
7 network news subsystem
8 UUCP subsystem
9 clock daemon
10 security/authorization messages 安全/授权消息
11 FTP daemon
12 NTP subsystem
13 log audit 日志审计
14 log alert 日志警报
15 clock daemon (note 2)
16 local use 0 (local0)
17 local use 1 (local1)
18 local use 2 (local2)
19 local use 3 (local3)
20 local use 4 (local4)
21 local use 5 (local5)
22 local use 6 (local6)
23 local use 7 (local7)
Level / Severity 字段
每条消息的 PRI 还有一个十进制 Level / Severity(严重性) 指示符。表明该日志消息的重要程度
下表描述了这些及其数值。 Level / Severity 在 0 到 7 的范围内(包括 0 和 7)
字符<
后面唯一出现“0”值的情况是“优先级”值“0”。其他情况,不能以0开头。
1
2
3
4
5
6
7
8
9
10
Code值 Level / Severity(严重性)
-----------------------------------------------
0 Emergency: system is unusable 紧急:系统无法使用
1 Alert: action must be taken immediately 警报:必须立即采取行动
2 Critical: critical conditions 严重:严重情况
3 Error: error conditions 错误:错误情况
4 Warning: warning conditions 警告:警告情况
5 Notice: normal but significant condition 注意:正常但重要的情况
6 Informational: informational messages 信息:信息性消息
7 Debug: debug-level messages 调试:调试级别消息
Level表明该日志消息的重要程度,是导致系统不能正常使用了的紧急级别emerg?还是需要被及时处理的警告级别alert?又或仅仅是需要调试的debug级别的信息?同样可通过man 3 syslog查看:
Facility和level分别定义了不同的代号,其各自的宏定义可见/usr/include/sys/syslog.h头文件,它们两者的组合构成了Priority头的值。而该priority的值也恰恰是syslog函数的第一个参数的值。
(2) HEADER
HEADER 包含2个字段:TIMESTAMP
和HOSTNAME
的字段 ( 时间 、主机名/IP )
- 1)TIMESTAMP
TIMESTAMP 字段是源自[RFC3339]
的形式化时间戳,紧跟着PRI中的“>”。中间没有空格,格式必须是“Mmm dd hh:mm:ss”,不包括年份。“日”的数字如果是1~9,前面会补一个空格(也就是月份后面有两个空格),例如8月的第七天表示成为“Aug 7”,其中g和7之间有两个空格。而“小时”、“分”、“秒”则在前面补 “0”。
月份取值包括: Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec
==因为有些系统需要将日志长期归档,而时间字段又不包括年份,所以一些不标准的syslog格式中包含了年份==,例如:
1
<165>Aug 24 05:34:00 CST 1987 mymachine myproc[10]: %% It’s time to make the do-nuts. %% Ingredients: Mix=OK, Jelly=OK....
这样会导致解析程序将 “CST” 当作主机名,而 “1987” 开始的部分作为 MSG 部分。解析程序面对这种问题,可能要做很多容错处理,或者定制能解析多种 syslog格式,而不仅仅是只能解析标准格式。
- 2)HOSTNAME
TIMESTAMP和HOSTNAME之间用一个空格分隔,
HOSTNAME包含主机名,主机名不得包括域名部分。如果没有主机名,将会包含主机的IP地址。
HOSTNAME字段包含发送者的主机名或IP地址。如果使用主机名,HOSTNAME字段必须包含STD 13中描述的主机名。其中不能包含任何空格主机名不能包含在HOSTNAME字段中。如果使用IPv4地址,必须是点分十进制。如果是IPv6格式,使用RFC 2373中的格式。HOSTNAME字段之后也必须有一个空格。
(3) MESSAGE
MSG部分是syslog报文的剩余部分。又分为两个部分,TAG和Content。其中TAG部分是可选的。
- TAG字段的值是产生消息的程序或进程名称。TAG是32个字符之内的ABNF数字字母字符集。任何非数字字母的字符会被当作TAG字段的结束标记,并且这个字符会当作CONTENT字段的开始。
- Content 部分包含消息的详细信息。通常是开放格式的消息,包含事件的一些详细信息。CONTENT字段的第一个字符表示TAG字段的结束,通常是方括号 “[”,冒号 “:” 或者空格。
通常它包含生成这个消息进程的其他信息以及消息的文本内容。这部分没有结束分隔符。
报文的MSG部分必须包含可见的(可打印)的字符。通常使用和 PRI 以及 HEADER 部分一样的ASCII字符集。在这个字符集中,允许的字符是ABNF VCHAR(%d33-126)以及空格(SP value %d32)。然而,不需要在MSG中使用的代码集的指示,也不期望这样做。可以使用其他的字符集,只要MSG中使用的字符是与上述类似的可见的字符和空格。包含不可见字符集的消息不能被展示,也不能被接收者理解,不会给操作员或管理员任何信息。
举例:
1
<30>Oct 9 22:33:20 hlfedora auditd[1787]: The audit daemon is exiting.
“auditd[1787]”是TAG部分,包含了进程名称和进程PID。PID可以没有,这个时候中括号[ ]
也是没有的。
进程PID有时甚至不是一个数字,例如“root-1787”,解析程序要做好容错准备。
TAG后面用一个 “冒号 :
” 隔开Content部分,这部分的内容是应用程序自定义的。
日志格式RFC5424
4. 报文分析
测试命令
1
2
3
4
5
logger -t hello -p "local7.info" "cwr test"
#参数说明:
-t TAG Log using the specified tag (defaults to user name)
-p PRIO Priority (numeric or facility.level pair)
1
2
3
4
5
6
7
红色 PRI
黄色 版本号
绿色 时间戳(注意必须是rfc3339时间标准,rsyslog可以使用%TIMESTAMP:::date-rfc3339%)
蓝色 主机名
紫色 应用名(简单通过logger来模拟一个应用名进行测试)
棕色 进程ID,消息ID和结构化数据(没有在实际进程中调用syslog接口发送,因此进程号字段缺省为空,用-填充,其他几个字段也一样。logger默认调用syslog接口发送,因为syslog使用的是旧的协议3164,因此只填充MSG字段。)
灰色 MSG