文章

syslog 协议简介

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取代了RFC3164RFC5424是对较早的 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消息主要分为PriorityHeader以及Message三个部分,其中Priority是由两个部分组成的——FacilityLevel

其中“<30>”是PRI部分,“Oct 9 22:33:20 hlfedora”是HEADER部分,“auditd[1787]: The audit daemon is exiting.”是MSG部分。

(1) PRI

PRIPriority(优先级) 和 RFC 5424 中的定义一样,有效值范围为0 - 191。不能有空格、数字前也不能补0。 合法的形式如:<15>

PRI值包含两部分信息:FacilityLevel/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个字段:TIMESTAMPHOSTNAME的字段 ( 时间 、主机名/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)

image-20230717161523073

1
2
3
4
5
6
7
红色    PRI
黄色    版本号
绿色    时间戳(注意必须是rfc3339时间标准,rsyslog可以使用%TIMESTAMP:::date-rfc3339%)
蓝色    主机名
紫色    应用名(简单通过logger来模拟一个应用名进行测试)
棕色    进程ID,消息ID和结构化数据(没有在实际进程中调用syslog接口发送,因此进程号字段缺省为空,用-填充,其他几个字段也一样。logger默认调用syslog接口发送,因为syslog使用的是旧的协议3164,因此只填充MSG字段。)
灰色    MSG

本文由作者按照 CC BY 4.0 进行授权