背景:在日志审计项目中收集各个设备的系统信息,利用syslog日志进行日志的采集、接收、转发,因在多网络段转发日志时需要获取 各个转发设备主机名/主机IP地址的,所以接入Syslog-ng日志。
Syslog 详解
Syslog常被称为系统日志或系统记录,是一种用来在互联网协议(TCP/IP)的网上中传递记录档消息的标准。这个词汇常用来指涉实际的syslog 协议,或者那些提交syslog消息的应用程序或数据库。
syslog协议提供传输功能,以允许机器通过IP网络将事件通知消息发送到事件消息collector(也称为系统日志服务器)。因为每一个进程、应用程序和操作系统是分开开发的,syslog的信息的内容大多都是不同的。因此,不会对消息的格式或内容做出任何假设。这个协议只是简单的传递这些信息。在任何情况下,有一个设备发出消息。那台机器上的Syslog进程可能将信息发送给collector。不需要任何应答。
Syslog协议和进程的基本原则是它的简单性。在发送者和接收者之间不需要协调。实际上,syslog信息的发送者可以在接收者没有配置好或根本不存在的情况下进行发送。相反,很多设备会在没有任何配置和定义的情况下收到消息。这种简单性让syslog更容易接受和部署。
Syslog使用用户数据报(UDP)作为底层传输层协议。Syslog的UDP端口为514。如果消息是由syslog进程发出,建议源端口也是514,不是514也是合法的。如果发送者使用比514大的端口号,那么建议接下来的其他消息也由这个端口发出。
Syslog常被用来日志等数据的传输协议,数据格式遵循规范主要有RFC3164,RFC5424;
RFC5424 相比 RFC3164 主要是数据格式的不同,RFC3164相对来说格式较为简单,能适应大部分使用场景,但是已废弃,RFC5424已作为Syslog的业界规范。
系统日志架构
相关定义的说明
- device:生成消息的设备
- relay:接收消息的设备又将消息转发给了其他设备
- collector:接收消息但不进行转发的设备,也称作syslog服务器
- sender:发出消息或转发消息的设备
- receiver:任何接收消息的设备,包括转发或收集
Syslog-ng 简介
syslog-ng就是syslog的升级版,功能也比syslog强大。比如:高性能、支持多平台、高可靠的传输、众多的用户群体、强大的日志过滤、排序。syslog-ng有两个版本,一个是收费的,一个是开源的。syslog ng是一个增强的日志守护进程,支持多种输入和输出方法:syslog、非结构化文本、消息队列、数据库(类似于SQL和NoSQL)等等。syslog-ng可以通过对日志信息执行正规表达式过滤,并且支持主机链方式等工作,都能更好的协助我们管理主机。syslog-ng官方网站:https://www.syslog-ng.com/
syslog-ng替代syslog是基于以下的设计原则的:
- 通过正规表达式协助,除支持原facitily/level方式,还支持内容过滤等以建立更好的消息过滤机制;
- 支持主机链,即使日志消息经过多重网络转发,仍可找到原发出主机的信息和整个消息链;
- 支持强大的自定义配置,并且清晰、明了。
syslog-ng的主配置文件存放在:/etc/syslog-ng/syslog-ng.conf
配置说明
格式:LOG STATEMENTS『SOURCES - FILTERS -DESTINATIONS』
消息路径 『消息源 - 过滤器 - 目的站』也就是说,通过定义多个消息源,把匹配上若干个过滤器的消息导向到指定的目的地,从而组成一个消息路径。
SOURCES
格式:
<sourcename>:一个消息源的标识
sourcedriver:消息源驱动器,可以支持若干参数,并使用分号“;”隔离多个消息源驱动器
消息源驱动器有:
消息源驱动器 | 说明 |
file (filename) | 从指定的文件读取日志信息 |
unix-dgram (filename) | 打开指定的SOCK_DGRAM模式的unix套接字,接收日志消息 |
unix-stream (filename) | 打开指定的SOCK_STREAM模式的unix套接字,接收日志消息 |
udp ( (ip),(port) ) | 在指定的UDP端口接收日志消息 |
tcp ( (ip),(port) ) | 在指定的TCP端口接收日志消息 |
sun-streams (filename) | 在solaris系统中,打开一个(多个)指定的STREAM设备,从其中读取日志消息 |
internal() | syslog-ng内部产生的消息 |
pipe(filename),fifo(filename) | 从指定的管道或者FIFO设备,读取日志 |
解释:定义了s_sys消息源 消息驱动器1:从/proc/kmsg 目录选择以kernel: 前缀的文件进行读取 消息驱动器2:syslog-ng内部产生的消息 消息驱动器3:从udp的514端口获取消息
过滤器:filters
格式为:filter <filtername> { expression; };
说明:
<filtername>:一个过滤器标识
expression:表达式,支持:逻辑操作符:and(和)、or(或)、not(非);函数:可使用正规表达式描述内容
过滤函数 | 说明 |
facility(,) | 根据facility(设备)选择日志消息,使用逗号分割多个facility |
level(,) | 根据level(优先级)选择日志消息,使用逗号分割多个level,或使用“..”表示一个范围 |
program(regexp) | 日志消息的程序名是否匹配一个正则表达式 |
host(regexp) | 日志消息的主机名是否和一个正则表达式匹配 |
match(regexp) | 对日志消息的内容进行正则匹配 |
filter() | 调用另一条过滤规则并判断它的 |
这里的level定义info,相当于syslog的.=info,并不包括更低的等级;
若需要包括更低的等级,请使用“..”表示一个等级范围;
另外,filter(DEFAULT),用于捕获所有没有匹配上的日志消息。filter(*)是无效的。
目的地:DESTINATIONS
格式为:
说明:<destname>:一个目的地的标识 destdriver :目的地驱动器
目的地驱动器有:
目的地驱动器 | 说明 |
file (filename) | 把日志消息写入指定的文件 |
unix-dgram (filename) | 把日志消息写入指定的SOCK_DGRAM模式的unix套接字 |
unix-stream (filename) | 把日志消息写入指定的SOCK_STREAM模式的unix套接字 |
udp (ip),(port) | 把日志消息发送到指定的UDP端口 |
tcp (ip),(port) | 把日志消息发送到指定的TCP端口 |
usertty(username) | 把日志消息发送到已经登陆的指定用户终端窗口 |
pipe(filename),fifo(filename) | 把日志消息发送到指定的管道或者FIFO设备 |
program(parm) | 启动指定的程序,并把日志消息发送到该进程的标准输入 |
消息路径LOG STATEMENTS
格式为:
把消息源、过滤器、消息目的组合起来就形成一条完整的指令。日志路径中的成员是顺序执行的。凡是来源于指定的消息源,匹配所有指定的过滤器,并送到指定的地址。
注意:每条日志消息都会经过所有的消息路径,并不是匹配后就不再往下执行的。
选项参数 options
格式:options { opt1; opt2; ... };
选项参数 | 说明 |
chain_hostnames(yes|no) | 是否打开主机名链功能,打开后可在多网络段转发日志时有效 |
long_hostnames(yes|no) | 是chain_hostnames的别名,已不建议使用 |
keep_hostname(yes|no) | 是否保留日志消息中保存的主机名称,否时,总是使用来源主机来作重写日志的主机名 |
use_dns(yes|no) | 是否打开DNS查询功能,应使用防火墙保护使用syslog-ng的节点安全,并确认所有主机都是可以通过dns解释的,否则请关闭该选项 |
use_fqdn(yes|no) | 是否使用完整的域名 |
check_hostname(yes|no) | 是否检查主机名有没有包含不合法的字符 |
bad_hostname(regexp) | 可通过正规表达式指定某主机的信息不被接受 |
dns_cache(yes|no) | 是否打开DNS缓存功能 |
dns_cache_expire(n) | DNS缓存功能打开时,一个成功缓存的过期时间 |
dns_cache_expire_failed(n) | DNS缓存功能打开时,一个失败缓存的过期时间 |
dns_cache_size(n) | DNS缓存保留的主机名数量 |
create_dirs(yes|no) | 当指定的目标目录不存在时,是否创建该目录 |
dir_owner(uid) | 目录的UID |
dir_group(gid) | 目录的GID |
dir_perm(perm) | 目录的权限,使用八进制方式标注,例如0644 |
owner(uid) | 文件的UID |
group(gid) | 文件的GID |
perm(perm) | 文件的权限,同样,使用八进制方式标注 |
gc_busy_threshold(n) | 当syslog-ng忙时,其进入垃圾信息收集状态的时间。一旦分派的对象达到这个数字,syslog-ng就启动垃圾信息收集状态。默认值是:3000 |
gc_idle_threshold(n) | 当syslog-ng空闲时,其进入垃圾信息收集状态的时间。一旦被分派的对象到达这个数字,syslog-ng就会启动垃圾信息收集状态,默认值是:100 |
log_fifo_size(n) | 输出队列的行数 |
log_msg_size(n) | 消息日志的最大值(bytes) |
stats(n) | 多少时间(秒)写入两行STATUS信息供,默认值是:600 |
sync(n) | 缓存多少行的信息再写入文件中,0为不缓存,局部参数可以覆盖该值 |
time_reap(n) | 在没有消息前,到达多少秒,即关闭该文件的连接 |
time_reopen(n) | 对于死连接,到达多少秒,会重新连接 |
use_time_recvd(yes|no) | 宏产生的时间是使用接受到的时间,还是日志中记录的时间;建议使用R_的宏代替接收时间,S_的宏代替日志记录的时间,而不要依靠 |
Syslog-ng配置实例
syslog-ng垃圾收集状态
一定条件下,syslog-ng即会进入垃圾收集状态,而暂时不再接受日志信息。这时,会造成非连接的传输协议的日志丢失(例如UDP)。
gc_idle_threshold(n):一旦被分派的对象到达这个数字,并且当syslog-ng空闲时(100微秒内没有日志消息到达)。此时,syslog-ng就会启动垃圾信息收集状态。已分配的对象可通过-v命令行参数指定其的最小值。而syslog-ng这个值应该比较小,但比已分配的对象要大即可。
gc_busy_threshold(n) :当syslog-ng忙时,一旦分派的对象达到这个数字,syslog-ng就进入垃圾信息收集状态的时间。该值应该比较高,以保证正常情况下不会打断日志消息的收取。
日志格式-RFC3164
syslog格式:<PRI>HEADER MESSAGE
syslog的消息长度:不超过1024。
RFC3164协议手册地址:https://tools.ietf.org/html/rfc3164
syslog格式举例:<15>Jul 10 12:00:00 192.168.1.1 SyslogGen MESSAGE
格式说明:
PRI:即Priority(优先级),有效值范围为0 - 191。不能有空格、数字前也不能补0。合法的形式如:<15>。PRI值包含两部分信息:Facility和Level。其中Facility值用于判断哪个程序产生了日志信息。Level值用于判断严重等级。计算方法:PRI = Facility * 8 + Level。只有一种情况,当0跟着<时,表示优先级为0。其他情况,不能以0开头
Facility可选值为
Level可选值为:
- HEADER:
HEADER包含两个称为TIMESTAMP和HOSTNAME的字段。TIMESTAMP紧跟着PRI中的“>”。TIMESTAMP和HOSTNAME之间用一个空格分隔。HOSTNAME包含主机名。如果没有主机名,将会包含主机的IP地址。如果设备有多个IP地址,将会使用发送数据的IP地址。两者可以选一个发送。在这种情况下,device可能被配置成使用一个源IP发送所有的消息,不管消息实际从哪个接口发出。这种方式为所有的消息的HOSTNAME字段提供了一致性。 TIMESTAMP是本地事件,格式是“Mmm dd hh:mm:ss”:Mmm是月份的英文缩写,以一个大写的M开始,两个小写的m结束。取值如下:Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec。dd是一个月中的天数。如果小于10,必须表示成空格然后是数字。例如8月的第七天表示成为“Aug 7”,其中g和7之间有两个空格。hh:mm:ss是本地时间。小时表示成为24小时的格式,合法值是00到23。分钟和秒是00到59。在TIMESTAMP之后需要有一个空格。HOSTNAME字段包含发送者的主机名或IP地址。最好的名称是主机名。如果使用主机名,HOSTNAME字段必须包含STD 13中描述的主机名。其中不能包含任何空格主机名不能包含在HOSTNAME字段中。如果使用IPv4地址,必须是点分十进制。如果是IPv6格式,使用RFC 2373中的格式。HOSTNAME字段之后也必须有一个空格。
- MESSAGE: MSG部分是syslog报文的剩余部分。通常它包含生成这个消息进程的其他信息以及消息的文本内容。这部分没有结束分隔符。Syslog报文的MSG部分必须包含可见的(可打印)的字符。通常使用和PRI以及HEADER部分一样的ASCII字符集。在这个字符集中,允许的字符是ABNF VCHAR(%d33-126)以及空格(SP value %d32)。然而,不需要在MSG中使用的代码集的指示,也不期望这样做。可以使用其他的字符集,只要MSG中使用的字符是与上述类似的可见的字符和空格。包含不可见字符集的消息不能被展示,也不能被接收者理解,不会给操作员或管理员任何信息。MSG部分有两个字段,分别是TAG和CONTENT。TAG字段的值是产生消息的程序或进程名称。CONTENT部分包含消息的详细信息。通常是开放格式的消息,包含事件的一些详细信息。TAG是32个字符之内的ABNF数字字母字符集。任何非数字字母的字符会被当作TAG字段的结束标记,并且这个字符会当作CONTENT字段的开始。CONTENT字段的第一个字符表示TAG字段的结束,通常是方括号“[”,冒号“:”或者空格。
日志格式RFC5424
syslog格式:<PRI>VERSION TIMESTAMP HOSTNAME APP-NAME PROCID MSGID
RFC5424协议手册地址:https://tools.ietf.org/html/rfc5424
- PRI:参见RFC3164中的PRI。
- VERSION :版本用来表示Syslog协议的版本,RFC5424的版本号为“1”
- TIMESTAMP :时间戳格式为:yyyy-mm-ddTHH:MM:SS.xxxxxx+/-HH:MM 有几个要求:1."T" "Z"必须大写。2.如果无法获取时间戳,必须使用"-"代替。3.不能使用闰秒。4."T"是必须的
- HOSTNAME :hostname标识发送syslog消息的源主机。优先选用几种写法:1.FQDN:全限定域名:同时带有主机名和域名的名称。(通过符号“.”)2.Static IP address:静态IP地址。3.Hostname:主机名。4.Dynamic IP address:动态Ip地址。4.the NILVALUE:"-"
- APP-NAME:用于识别产生消息的设备或应用,找不到用"-"代替
- PROCID :进程名称或进程ID,得不到用"-"代替;ProcId常用于分析日志生成进程的连续性,但不做可靠性保证,比如进程重启还是可能会分到一样的进程ID
- MSGID:标识消息类型。例如TCPIN、TCPOUT分别代表TCP数据的流入或流出;如果无法获取数据类型,用"-"代替。 MSGID可根据数据类型用于数据过滤
RFC 5424 简单示例
对于数据的提取 可采用正则表达式 及字符串的分割读取