简介
Rsyslog is a rocket-fast system for log processing.
官方有 8.2208.0 文档可以查阅,虽然有人说挺乱,但是还是可以解决大部分问题的。
前言
需求是多台设备的 syslog 在集群、堆叠、链路聚合模式下实现某些日志的同步功能,并在单机模式停止同步,web 平台页面中可查询历史记录。按理说应该有一台日志服务器去做这一些功能,但是由于一些原因不能安装 EFK 之类的日志分析系统,且这种日志量比较大,在命中防火墙某条或多条告警策略的前提下,持续命中 3~4 个小时就产生几百万条日志,当然正常情况下不会让这种情况持续进行,系统早已告警,管理员进行处理。最终方案使用系统自带 Rsyslog 将本设备日志进行过滤、转发、存储,web 服务平台读取本设备日志文件。
整理教程时的系统环境
Linux Kylin 4.4.131-20200704.kylin.server-generic
rsyslogd 8.16.0
配置 Rsyslog
默认配置
配置文件 /etc/rsyslog.conf
大概分为三个部分:MODULES
、GLOBAL DIRECTIVES
、RULES
,下面贴出来仅供参考,但是不做修改。
# /etc/rsyslog.conf Configuration file for rsyslog.
#
# For more information see
# /usr/share/doc/rsyslog-doc/html/rsyslog_conf.html
#
# Default logging rules can be found in /etc/rsyslog.d/50-default.conf
#################
#### MODULES ####
#################
module(load="imuxsock") # provides support for local system logging
module(load="imklog") # provides kernel logging support
#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")
# Enable non-kernel facility klog messages
$KLogPermitNonKernelFacility on
###########################
#### 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
自定义配置
本机日志配置
将自定义配置放入 /etc/rsyslog.d/
文件夹下,好处是可以方便的对配置进行维护,且对其他人的配置无影响。
编辑 99-fw-policy.conf
配置,为本机开启端口,过滤、接收日志功能:
# 提供 UDP 模式日志服务
# provides UDP syslog reception
module(load="imudp")
input(type="imudp" port="516")
# 提供 TCP 模式日志服务
# provides TCP syslog reception
module(load="imtcp")
input(type="imtcp" port="516")
# 设定默认模板
$template myFormat,"%$NOW% %timestamp:8:15% %fromhost-ip% %syslogtag% %msg%\n"
$ActionFileDefaultTemplate myFormat
# 设定日志文件模板
$template RemoteLogs,"/opt/smipmp/syslog/%$YEAR%-%$MONTH%-%$DAY%.log"
# 设定过滤规则
:rawmsg, contains, "POLICY:" -?RemoteLogs
:rawmsg, contains, "POLICY:" ~
:fromhost-ip, !isequal, "162.219.225.3" ~
:rawmsg, contains, "FIREWALL" @127.0.0.1:514
这里使用 $ActionFileDefaultTemplate
配置日志格式的默认模板,下面列出 template
模板配置过程中使用的部分属性,其他额外的信息可以使用 man rsyslog.conf
命令去查看 rsyslog.conf 手册,也可以查看官方文档: Examples。
- $NOW:当前日期戳,格式为YYYY-MM-DD
- $YEAR:当前年份(4位数字)
- $MONTH:当前月份(2位数字)
- $DAY:月的当前日期(2位数)
- timestamp:timereported的别名
- fromhost-ip:接收到消息的系统的主机IP
- syslogtag:来自消息的标签,通常来说是消息源进程的用户名
- msg:即消息源进程调用syslog家族函数,所传递的文本信息
有了模板,接下来配置规则,可以查看官方文档:Filter Conditions。因为系统中 syslog 日志很多,不能让所有的日志全部存入日志文件中,那样 web 服务端筛选的时候比较麻烦,而且导致日志文件会很大。
# 消息中包含 “POLICY:” 这一关键词的日志,则使用 RemoteLogs 规则,存入文件中
:rawmsg, contains, "POLICY:" -?RemoteLogs
# 重定向规则
:rawmsg, contains, "POLICY:" ~
# 不是从此 IP 发过来的日志,进行重定向
:fromhost-ip, !isequal, "162.219.225.3" ~
# 消息中包含 “FIREWALL:” 这一关键词的日志,转发到本机 514 端口
:rawmsg, contains, "FIREWALL" @127.0.0.1:514
- RemoteLogs:注意
/etc/rsyslog.conf
配置文件中GLOBAL DIRECTIVES
部分对日志文件的默认权限,如果权限不正确是无法写入的。 - rawmsg:这里使用 rawmsg 而不是 msg,测试在大报文情况下 msg 匹配不上,不确定是不是上游防火墙的原因。
- 重定向规则:告知 rsyslog 守护进程停止对日志消息的进一步处理,符合上一条规则的将不再进行下面的规则匹配;如果没有使用该重定向规则,远程消息匹配完上一条规则后,还将进行后面的规则匹配。
- @:转发协议的参数 @@ 为 TCP协议,对应的接收端也需要配置接受 TCP 协议,@ 为 UDP 协议。
转发日志配置
官方文档:Forwarding to More than One Server,这里使用队列进行日志转发,当有多设备需要转发时
# start forwarding rule 1
$ActionQueueType LinkedList # use asynchronous processing
$ActionQueueFileName srvrfwd1 # set file name, also enables disk mode
$ActionResumeRetryCount -1 # infinite retries on insert failure
$ActionQueueSaveOnShutdown on # save in-memory data if rsyslog shuts down
:fromhost-ip, isequal, 162.219.225.3 @@server1:port
# end forwarding rule 1
# start forwarding rule 2
$ActionQueueType LinkedList # use asynchronous processing
$ActionQueueFileName srvrfwd2 # set file name, also enables disk mode
$ActionResumeRetryCount -1 # infinite retries on insert failure
$ActionQueueSaveOnShutdown on # save in-memory data if rsyslog shuts down
:fromhost-ip, isequal, 162.219.225.3 @@server2:port
# end forwarding rule 2
- ActionQueueType:指定将使用的队列类型。可能的选项是“FixedArray”,“LinkedList”,“Direct”或“Disk”
- ActionQueueFileName:创建消息队列文件名称
- ActionResumeRetryCount:操作恢复重新计数
- ActionQueueSaveOnShutdown:关闭队列时候
上述的配置除了能发送多设备,还解决在 Rsyslog 客户端无法通过网络访问目标服务器时,临时将客户端的日志信息存储在它的一个磁盘缓冲文件中,当网络或者服务器恢复时,再次进行发送。
日志转发工具类
import io.renren.AdminApplication;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
/**
* 包过滤日志服务工具类
*
* @author Stone
* @since 1.0.0 2022/8/30
*/
@Component
public class PolicyLogServerUtil {
private static final Logger logger = LoggerFactory.getLogger(PolicyLogServerUtil.class);
public static final String POLICY_FILE = "/etc/rsyslog.d/99-fw-policy.conf";
public static final String FORWARDING_POLICY_FILE = "/etc/rsyslog.d/98-fw-policy-f.conf";
public static final String ACTIVE = "Active: active";
public static final String POLICY_FILE_MD5 = "4a6040f70e8257c506fe016a6e2631a5";
/**
* 检测syslog日志服务
*/
public static void checkLogServer() {
logger.debug("策略日志服务检测工具类[开始]======>");
File policyConfFile = new File(POLICY_FILE);
String policyConfFileMd5 = Md5CalculateUtil.getMD5(policyConfFile);
if (policyConfFile.exists()) {
logger.debug("策略日志服务配置文件已存在! ");
if (POLICY_FILE_MD5.equals(policyConfFileMd5)) {
logger.debug("策略日志服务检测工具类[结束]<======");
return;
}
}
String commandShell = ScriptUtils.executeCommandShell("systemctl status rsyslog.service | grep 'Active'");
if (StringUtils.isNotBlank(commandShell) && !commandShell.contains(ACTIVE)) {
ScriptUtils.executeCommandShell("systemctl restart rsyslog.service");
}
InputStream inputStream = AdminApplication.class.getClassLoader().getResourceAsStream("tools/99-fw-policy.conf");
try {
if (inputStream != null) {
policyConfFile.createNewFile();
FileUtils.copyToFile(inputStream, policyConfFile);
ScriptUtils.executeCommandShell("systemctl restart rsyslog.service");
}
} catch (IOException e) {
logger.error("策略日志服务工具类检测失败:{}", e.getMessage());
} finally {
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
logger.error("策略日志服务工具类检测失败:{}", e.getMessage());
}
}
}
logger.debug("策略日志服务检测工具类[结束]<======");
}
/**
* 添加策略转发
*
* @param remoteAddresses 远端地址, 不包括本机
*/
public static void addPolicyForwarding(String remoteAddresses) {
if (StringUtils.isNotEmpty(remoteAddresses)) {
String[] address = remoteAddresses.split(",");
StringBuilder rule = new StringBuilder(128);
for (int i = 0; i < address.length; i++) {
rule.append("\n# start forwarding rule ").append(i + 1).append("\n")
.append("$ActionQueueType LinkedList\n")
.append("$ActionQueueFileName srvrfwd").append(i + 1).append("\n")
.append("$ActionResumeRetryCount -1\n")
.append("$ActionQueueSaveOnShutdown on\n")
.append(":fromhost-ip,isequal,\"162.219.225.3\" @@").append(address[i]).append(":516\n")
.append("# end forwarding rule ").append(i + 1).append("\n");
}
if (StringUtils.isNotBlank(rule)) {
FileUtils.writeToFile(FORWARDING_POLICY_FILE, String.valueOf(rule), true);
ScriptUtils.executeCommandShell("systemctl restart rsyslog.service");
}
}
}
/**
* 移除策略转发
*/
public static void removePolicyForwarding() {
ScriptUtils.executeCommandShell("rm -f " + FORWARDING_POLICY_FILE + " && systemctl restart rsyslog.service");
}
}
这里贴几篇感觉写的很好的博客,参考部分内容
rsyslog配置动态日志文件
手工配置rsyslog配置文件详解
Linux下Rsyslog日志远程集中式管理
Centos6.5部署Rsyslog-日志的存储方式及监测服务状态
cmd输出日志如何带时间戳_第15篇:Linux 日志管理–rsyslog模板详解
评论区