网络协议 — syslog 协议与 rsyslog 日志服务

目录

syslog 协议

Syslog(系统日志)是一种在 IP 网络中传输操作系统和应用程序的日志信息的标准网络协议,常被应用于安全管理系统、日志审计系统等场景。

Syslog 协议的关键概念有以下 3 个:

  1. Facility(设施):是一个产生日志的程序模块。
  2. Severity(严重级别):标识日志级别。
  3. Action(动作):标识存储日志的位置。

通过 Facility、Priority 和 Action 的组合使用可以描述清楚 “存储什么日志、存储在哪里” 的问题。

Facility

下列是 Linux Kernel 中实现的 Syslog Facilities(syslog.h),Applicant 通过调用这些服务类型来记录它们的软件日志信息。

在这里插入图片描述

Severity

下列是 Linux Kernel 中实现的 7 个 Syslog Severities。

在这里插入图片描述

Action

1)记录到普通文件或设备文件
*.*     /var/log/file.log   # 绝对路径
*.*     /dev/pts/0          # 设备文件

2)”|”,表示将日志送给其他命令处理

3)”@HOST”,表示将日志发送到特定的主机

*.emerg                     @192.168.10.1

4)”用户”,表示将日志发送到特定的用户

5)”*”,表示将日志发送所有登录到系统上的用户

示例:摘取 $msg 变量内容,判断如果 keyboard 关键字就进行远程传送,没有此关键字的就不传送;

if $msg contains "keyboard"  then
action(type="omfwd" Target="172.18.20.60"\
       Port="8594"\
       Protocol="udp"\
       queue.type="LinkedList"\
       queue.spoolDirectory="/var/spool/rsyslog"\
       queue.filename="test2"\
       queue.size="100000"\
       queue.maxdiskspace="2g"\
       queue.highwatermark="60000"\
       queue.lowwatermark="2000"\
       queue.discardmark="80000"\
       queue.timeoutenqueue="3000"\
       queue.maxfilesize="200m"\
       queue.dequeuebatchsize="1000"\
       )

rsyslog

在这里插入图片描述

rsyslog(rocket-fast system for log)是 CentOS6 以后引入的一个日志服务,是 Syslog 协议的软件实现。rsyslog 能够接受从各种各样的来源,将其输入,输出的结果到不同的目的地。此外还具有以下特性:

  • 支持多线程;
  • 支持 UDP、TCP、TLS 等协议;
  • 支持 MySQL、PGSQL、Oracle 等存储;
  • 支持自定义输出格式;
  • 具有强大的过滤器,可实现过滤记录日志信息中任意部分;
  • 可以提供超过每秒一百万条消息给目标文件。

软件架构

在这里插入图片描述

Rsyslog 架构如上图所示,消息流是:输入模块 => 预处理模块 => 主队列 => 过滤模块 => 执行队列 => 输出模块。

  • Input 模块:是消息来源,包括:imklg、imsock、imfile;
  • Output 模块:是消息的目的地,包括:omudp、omtcp、omfile、omprog、ommysql、omruleset;
  • Filter 模块:处理消息的分析和过滤,rsyslog 可以根据消息的任何部分进行过滤,包括:mmnormalize。
  • 预处理模块:解决各种 Syslog 协议实现间的差异,例如:假设日志系统 client 使用 rsyslog,而 server 使用 syslog-ng,如果自己不做特殊处理的话 syslog-ng 是无法识别的。但是反过来,rsyslog 的 server 就可以识别 syslog-ng 发过来的消息。
  • Queue 模块:负责消息的存储,从 Input 传入的未经过滤的消息放在主队列中,过滤后的消息放入到不同 action queue 中,再由 action queue 送到各个输出模块。

rsyslogd 服务

  • 程序包名:rsyslog
  • 主程序文件:/usr/sbin/rsyslogd
  • 配置文件:/etc/rsyslog.conf、/etc/rsyslog.d/*.conf
  • 库文件:/lib64/rsyslog/*.so

Systemd 启动方式:

/lib/systemd/system/rsyslog.service

CLI 启动方式:

rsyslogd -f /root/rsyslog_worker_dir/rsyslog.conf -i /root/rsyslog_worker_dir/rsyslog.pid
rsyslogd -f /root/rsyslog_worker_dir/rsyslog.conf -i /root/rsyslog_worker_dir/rsyslog.pid -dn >debuglog

# 检测配置文件是否正确
rsyslogd -N1 -f file

rsyslog.conf

rsyslog.conf 配置文件由 3 个部分组成:

  1. MODULES:模块配置,作为 rsyslog 启动时需要加载的一些额外模块,是 rsyslog 支持多种设施类型的关键。
  2. GLOBAL DIRECTIVES:全局配置,定义通用的属性。
  3. RULES:规则配置,定义记录日志的来源、格式和位置。

MODULES

#################
#### MODULES ####
#################
​
module(load="imuxsock") # provides support for local system logging
#module(load="immark")  # provides --MARK-- message capability

# provides UDP syslog reception
module(load="imudp")
input(type="imudp" port="514")# provides TCP syslog reception
module(load="imtcp")
input(type="imtcp" port="514")# provides kernel logging support and enable non-kernel klog messages
module(load="imklog" permitnonkernelfacility="on")

GLOBAL DIRECTIVES

###########################
#### GLOBAL DIRECTIVES ####
###########################
#
# Use traditional timestamp format.
# To enable high precision timestamps, comment out the following line.
#
$ActionFileDefaultTemplate RSYSLOG_TraditionalFileFormat

# Filter duplicated messages
$RepeatedMsgReduction on

#
# Set the default permissions for all log files.
#
$FileOwner syslog
$FileGroup adm
$FileCreateMode 0640
$DirCreateMode 0755
$Umask 0022
$PrivDropToUser syslog
$PrivDropToGroup syslog

#
# Where to place spool and state files
#
$WorkDirectory /var/spool/rsyslog

#
# Include all config files in /etc/rsyslog.d/
#
$IncludeConfig /etc/rsyslog.d/*.conf

RULS

#################
####  RULES  ####
#################
# 服务名称[.=!]信息等级	 信息记录的文件名或设备或主机
# .   表示大于等于 xxx 级别的信息;
# .=  表示等于 xxx 级别的信息;
# .!  表示在 xxx 之外的等级的信息;
mail.info			     /var/log/maillog_info  # mail 服务产生的大于等于 info 级别的日志信息,都记录到后面指定的位置中。

# Log all kernel messages to the console.
# Logging much else clutters up the screen.
#kern.*                                                 /dev/console

# Log anything (except mail) of level info or higher.
# Don't log private authentication messages!
*.info;mail.none;authpriv.none;cron.none                /var/log/messages

# The authpriv file has restricted access.
authpriv.*                                              /var/log/secure

# Log all the mail messages in one place.
mail.*                                                  -/var/log/maillog

# Log cron stuff
cron.*                                                  /var/log/cron

# Everybody gets emergency messages
*.emerg                                                 :omusrmsg:*

# Save news errors of level crit and higher in a special file.
uucp,news.crit                                          /var/log/spooler

# Save boot messages also to boot.log
local7.*                                                /var/log/boot.log

属性替代

Rsyslog 预定义了一些内置的属性,我们可以在配置文件中定义日志输出格式、或定义动态文件名的时候使用到这些属性。以 $ 开头的是从本地系统获得的变量、不带 $ 就是从消息中获得变量。例如:

  1. pri(Priority,级别)
  2. msg(消息体)
  3. time(时间)
  4. hostname(主机名)
  5. 进程名
  6. 进程 ID

属性替代的语法格式:

%propname:fromChar:toChar:options:fieldname%

属性替换的功能很强大,你可以使用起始字符获取自己所需的字段,也可以使用正则表达式,也可以使用分隔符。例如:为了兼容一个 RFC 协议,rsyslog 规定如果用户输入的 msg 不是以空格开头,rsyslog 会自动补充一个空格,因此如果你希望输出的时候去掉这个空格,就可以使用:

%msg:2:$%     # 选取 msg 变量中,起始位置为 2,终止位置为结尾。

我们经常需要根据空格来分析字符串,F 表示使用字符分割,32 是空格的 ASCII 码,例如:

%msg:F,32:3%  # 按照空格分隔,取第三个子串。

模板渲染

模板渲染结合属性替代功能,常用于定义日志的输出格式,或者定义 omfile 模块的动态路径、动态文件等。例如:

$template  t_msg, "%msg\n%"
$template  f_debug, "/data0/logs/%$year%-%$month%-%$day%/debug.log"

过滤规则

通过过滤规则(Ruleset)可以针对不同的 Syslog 来源应用不同的过滤规则。需要在配置文件中预先定义才可以使用。例如针对不同的端口使用不同的过滤规则:

$Ruleset tcp1999
$RulesetCreateMainQueue on
Local3.*      @@10.0.0.44:1999

$Ruleset tcp2000
$RulesetCreateMainQueue on
Local4.*      @@10.0.0.44:2000

Filter 模块

在配置文件中导入了 Filter 模块之后就可以应用过滤规则了。例如:

Local3.*    -/data0/logs/local3.log;t_msg   # 在这个输出中使用 t_msg 的模板。
Local4.*    -?f_local3_test;t_msg           # 问号表示要使用模板定义的动态路径。

队列

Rsyslog 的队列具有主队列和工作队列这 2 种类型。从输入模块接收的消息会进入主队列,主队列中的消息,经过过滤模块,会进入到相应的工作队列。

队列j具有 4 种工作模式:

  1. direct mode
  2. disk mode
  3. FixedArray mode
  4. LinkedList mode

前两种是磁盘队列,更可靠,但是性能也较差;而后两种是内存队列。FixedArray 会预分配队列长度,而 LinkedList 是动态分配,如果你的系统日志流量比较平稳,可以使用预分配队列,如果日志属于突发型,可以使用动态队列。

此外,内存队列还可以通过指定一个 queuename 来添加 DA 模式,DA 模式主要是为了防止意外情况(进程关闭、Server 宕机)下,内存队列可以不丢失。

通过查看 rsyslog 的系统命令,可以看见 rsyslog 对队列提供了大量的可配参数,可以根据需要来进行优化。

远端日志文件服务器部署示例

  • 客户端:192.168.157.60
  • 服务器:192.168.157.61

客户端

$ vim /etc/rsyslog.conf

$ModLoad imudp  
$UDPServerRun 514 
$ModLoad imtcp  
$InputTCPServerRun 514


$template myFormat,"%timestamp% %fromhost-ip% %msg%\n"
$ActionFileDefaultTemplate myFormat

# 服务端 IP 地址,一个 @ 表示 TCP 传输,两个 @ 表示 UDP 传输
*.info;mail.none;authpriv.none;cron.none              @@192.168.157.61:514


$ systemctl start rsyslog

服务器

$ vim /etc/rsyslog.conf

$ModLoad imudp
$UDPServerRun 514
$ModLoad imtcp
$InputTCPServerRun 514
*.info;mail.none;authpriv.none;cron.none                /data/log/messages

# 允许 157.0 网段内的主机以 TCP 协议来传输
$AllowedSender tcp, 192.168.157.0/24

# 定义模板,接受日志文件路径,这里区分了不同主机的日志
$template Remote,"/data/log/%fromhost-ip%/%fromhost-ip%_%$YEAR%-%$MONTH%-%$DAY%.log"

# 过滤服务器本机的日志。
:fromhost-ip, !isequal, "127.0.0.1" ?Remote


$ systemctl start rsyslog
$ mkdir -pv /data/log
$ touch messages

$ systemctl restart rsyslog


$ tree /data/log/
/data/log/
├── 192.168.157.60
│   └── 192.168.157.60_2019-05-10.log
└── messages

验证

client $ logger "I'm very happy"

server $ tail -f /data/log/192.168.157.60/192.168.157.60_2019-05-10.log 

将日志存储至 MySQL 部署示例

服务器

$ yum install mariadb-server rsyslog-mysql -y
$ systemctl start mariadb.service

$ rpm -ql rsyslog-mysql
/usr/lib64/rsyslog/ommysql.so   # 客户端通信模块
/usr/share/doc/rsyslog-8.24.0/mysql-createDB.sql  # 创建 rsyslog 日志表结构的 SQL 语句

$ mysql < /usr/share/doc/rsyslog-8.24.0/mysql-createDB.sql

mysql> show databases;
mysql> use Syslog;
mysql> show tables;
+------------------------+
| Tables_in_Syslog       |
+------------------------+
| SystemEvents           |
| SystemEventsProperties |
+------------------------+

mysql> grant all on Syslog.* to 'rsysloguser'@'127.0.0.1' identified by 'rsyslogpass';
mysql> flush privileges;

修改服务器配置文件:

$ vim /etc/rsyslog.conf
......
$ModLoad ommysql    # 打开连接 MySQL 的模块
*.*                      :ommysql:127.0.0.1,Syslog,rsysloguser,rsyslogpass

$ systemctl restart rsyslog.service

验证

client $ logger 'THIS IS A TEST'

mysql> use Syslog;
mysql> select * from SystemEvents\G;
*************************** 17. row ***************************
            ID: 17
    CustomerID: NULL
    ReceivedAt: 2019-05-10 23:15:07
DeviceReportedTime: 2019-05-10 23:15:06
          Facility: 1
          Priority: 5
          FromHost: send
           Message:  THIS IS A TEST
        NTSeverity: NULL
        Importance: NULL
       EventSource: NULL
         EventUser: NULL
     EventCategory: NULL
           EventID: NULL
   EventBinaryData: NULL
      MaxAvailable: NULL
         CurrUsage: NULL
          MinUsage: NULL
          MaxUsage: NULL
        InfoUnitID: 1
         SysLogTag: root:
      EventLogType: NULL
   GenericFileName: NULL
          SystemID: NULL

监听 Apache 日志发送到远程服务器

客户端

在 /etc/rsyslog.d/ 目录下新建一个 apache_log.conf 配置文件:

# 加载 imfile 模块
$ModLoad imfile 
$InputFilePollInterval 10

## Apache 访问日志文件路径
$InputFileName /var/log/apache2/access.log
# tag 标签,可以作为过滤或分类用
$InputFileTag apache-access
# 状态文件,只需要指定文件名,程序会在工作目录 $WorkDirectory 下创建指定文件
$InputFileStateFile stat-apache-access
# 日志类型,user 代表应用日志
$InputFileFacility user
# 日志级别
$InputFileSeverity info
# 写入状态文件时间间隔
$InputFilePersistStateInterval 25000
## 以上属性可等效写为:
##  input(type="imfile" File="/path" Tag="tag1" StateFile="filename" Severity="info" Facility="user" PersistStateInterval="25000")

## Apache 错误日志文件路径
$InputFileName /var/log/apache2/error.log
$InputFileTag apache-error
$InputFileStateFile stat-apache-error
$InputFileSeverity error
$InputFilePersistStateInterval 25000

## 日志格式模板:msg 代表默认产生的消息
$template apache_temp,"%msg%\n"

## 按照 tag 分类指定 rsyslog 日志服务器地址,
if $syslogtag == 'apache-access' then @your_server:port;apache_temp
if $syslogtag == 'apache-access' then ~
if $syslogtag == 'apache-error' then @your_server:port;apache_temp
if $syslogtag == 'apache-error' then ~

服务器

# The imjournal module bellow is now used as a message source instead of imuxsock.
$ModLoad imuxsock # provides support for local system logging (e.g. via logger command)
$ModLoad imjournal # provides access to the systemd journal
 
# 启用 udp 模块,默认端口为 514 
module(load="imudp")
input(type="imudp" port="514")

# 启用 tcp 模块
module(load="imtcp")
input(type="imtcp" port="514")

# 将收到的日志模板化,比如在前面添加 IP 进行区分
$template access_log, "%FROMHOST-IP% %msg%\n"
$template error_log, "%msg%\n"
$template eophp_log, "%msg%\n"

# 指定保存到服务器的路径
# access-log
$template access_log_path, "/data/apache/logs/%$NOW%/access-log/web1-access_log"
# error-log 
$template error_log_path, "/data/apache/logs/%$NOW%/error-log/web1-error_log"
# eophp log
$template eophp_log_path, "/data/eophp_logs/%$NOW%/%FROMHOST-IP%.log"

# if 进行条件匹配比如多台客户端的 IP 在同一个网络,可以用 startwith 匹配 IP 的前缀
# $syslogtag 为日志的 tag 标签
if $fromhost-ip startswith '119.123.' and $syslogtag == 'apache-access' then ?access_log_path;access_log
& ~
# web1-error-log 
if $fromhost-ip startswith '119.123.' and $syslogtag == 'apache-error' then ?error_log_path;error_log
& ~
# eophp
if $fromhost-ip startswith '119.123.' and $syslogtag == 'eplog' then ?eophp_log_path;eophp_log
&~

# omit...

猜你喜欢

转载自blog.csdn.net/Jmilk/article/details/131963041