第4章 Linux日志采集基础(rsyslog、journald)

说实话,搞审计日志采集,Linux这块要是没搞明白,后面全是白搭。我见过太多团队在Windows日志上花了大力气,结果Linux这边随便搭个syslog就觉得万事大吉了——后来被攻击溯源时才发现,关键日志要么丢了,要么格式乱得没法看。

你想想看,现在的Linux服务器,主流日志系统就两套:传统的rsyslog和systemd带来的journald。它们不是取代关系,而是互补关系。今天我们就好好聊聊怎么用好它们。

4.1 rsyslog:老牌稳健,但配置是个技术活

rsyslog是Linux日志采集的老兵了。我记得我刚入行那会儿,公司还在用syslogd,连TLS加密都不支持。后来全面升级到rsyslog,我才意识到原来日志传输可以这么灵活。

rsyslog的核心功能

说白了,rsyslog就是一个日志路由器。它从各种源收日志,然后按规则转发出去。它的核心能力有这几个:

  • 支持多种输入源:本地文件、网络socket、内核日志等
  • 灵活的过滤条件:根据设施、等级、程序名等做精细控制
  • 多种输出方式:本地文件、远程服务器、数据库、甚至Elasticsearch
  • 高可靠性:支持队列、磁盘缓冲、TLS加密传输

为什么说它可靠?我在项目中遇到过极端情况——网络抖动导致日志发送失败。rsyslog会启用自己的磁盘队列,等网络恢复后再重新发送,消息一条都不会丢。

配置语法核心

rsyslog的配置语法其实不难,但一开始容易搞混。它的规则格式是:

facility.priority    action

facility表示日志来源(比如auth、cron、kern),priority表示等级(比如info、warn、err)。两者组合起来就是过滤条件。action则是把这部分日志送到哪里去。

这里有个坑——优先级是包含关系的。比如你写了kern.err,它会把kern的err、crit、alert、emerg级别的日志都匹配上。为什么会这样?因为rsyslog用的是'最低优先级包含更高优先级'的设计思路。

优先级 数值 常见场景
emerg 0 系统不可用,通常需要立即通知管理员
alert 1 必须立即处理的问题,比如数据库损坏
crit 2 临界条件,比如硬盘空间不足
err 3 一般错误,功能受影响但系统仍在运行
warning 4 警告信息,不会影响正常使用
notice 5 正常但重要的事件,比如服务启动
info 6 普通信息,日常运行状态
debug 7 调试信息,只在排查问题时才开启
我个人的小习惯:在生产环境,我只把err及以上级别发到远程审计服务器。info和debug级别的日志留在本地,避免网络带宽浪费。但如果做安全审计,auth设施的notice及以上级别我都会保留——因为非法登录尝试的日志等级通常是notice。

实战:配置rsyslog转发审计日志

假设我们要把认证相关的日志发送到远程日志服务器(192.168.1.100),配置很简单:

# /etc/rsyslog.d/audit-forward.conf
# 认证相关的日志,发到远程审计服务器
auth,authpriv.*    @@192.168.1.100:514

# 内核日志也发一份
kern.*             @@192.168.1.100:514

# 本地保留一份(默认配置已有,这里显式声明)
auth,authpriv.*    /var/log/secure
kern.*             /var/log/kern.log

这里@@表示使用TCP协议,单个@是UDP。我个人强烈建议用TCP——UDP在网络上丢包了rsyslog没法重传,审计日志丢不起。

配置完成后重启服务:

systemctl restart rsyslog

# 检查配置有没有写错
rsyslogd -N1
我曾经踩过的坑:配置里写错了远程IP,导致日志一直发不出去,本地磁盘塞满了才发现。后来我养成了一个习惯——每次配完后用rsyslogd -N1做语法检查,再用tcpdump抓包确认日志确实发出去了。你想想看,审计日志都丢了,光配好看有什么用?

4.2 journald:新贵登场,把日志记录得更细致

从CentOS 7、Ubuntu 16.04开始,systemd统一了江湖,journald也就成了标配。它跟rsyslog是完全不同的思路——rsyslog是纯文本日志,journald是二进制结构化日志。

为什么需要journald?

传统syslog有个致命的问题:日志丢了上下文。比如你看到一行sshd[12345]: Failed password for root,但你不知道这个用户之前登录失败了多少次,也不知道系统当时的资源使用情况。journald把所有这些元数据都记录在案。

我举个例子:我在排查一次SSH暴力破解事件时,用journalctl查询某个服务的日志,不仅看到了失败记录,还看到了每条日志对应的PID、UID、GID、内核模块、cgroup信息。这些数据对于溯源来说,价值不可估量。

journald的操作

它最厉害的武器就是journalctl命令。说实话,用好了这个命令,你基本不用再去翻/var/log目录下的文本文件了。

命令 用途
journalctl -u sshd.service 只查看sshd服务的日志
journalctl -p err --since "2024-01-01" 查看某个时间点之后的错误级别日志
journalctl -k 只查看内核日志
journalctl -o verbose 展示所有元数据字段,审计必备
journalctl -f 实时跟踪日志,类似tail -f
我强烈建议:在安全事件响应时,先用journalctl -o verbose导出完整元数据,再结合--since和--until缩小时间范围。这样你拿到的日志信息会比纯文本丰富至少3倍。我曾经靠journalctl里的_SYSTEMD_CGROUP字段快速定位到被入侵的容器,比传统方法快了一整个下午。

journald的持久化配置

journald默认把日志存在内存里(/run/log/journal),重启后就没了。做审计日志采集,必须改成持久化存储。

# /etc/systemd/journald.conf
[Journal]
Storage=persistent
Compress=yes
SystemMaxUse=5G
RuntimeMaxUse=1G
ForwardToSyslog=yes
MaxRetentionSec=30day

这里Storage=persistent让日志写入/var/log/journal。我建议加上ForwardToSyslog=yes,把journald的日志再转发给rsyslog,双方都保留一份。为什么要这样做?

  • 冗余存储:万一某个组件出问题,另一个还能查到日志
  • 统一转发:rsyslog负责把日志发到远程,journald只负责本地记录,职责分离
  • 格式互补:需要结构化元数据时用journalctl,需要文本流转发时用rsyslog

4.3 实战组合:journald + rsyslog协同工作

这套组合是我在多个生产环境验证过的。简单来说,就是journald负责本地精细记录,rsyslog负责远程转发和日志格式转换。

这样做的好处很明显:

  1. 审计日志服务器的格式统一,不会因为不同Linux发行版的差异导致解析困难
  2. 本地还保留了完整的元数据,供未来深入分析使用
  3. rsyslog的网络传输功能非常成熟,有断点续传、TLS加密等能力

配置上只需要在journald.conf里开启ForwardToSyslog=yes,然后让rsyslog按规则转发即可。我自己的生产环境用了5年多,几乎没出过问题。

小结一下:别把rsyslog和journald看成对手。rsyslog擅长网络传输和格式转换,journald擅长本地记录和元数据存储。把它们组合起来,才是Linux日志采集的最优解。

我们用一个图来展示这套体系的整体结构:

Linux日志采集体系结构 日志来源 应用程序日志 内核日志 / kmsg 系统服务日志 journald 接收 二进制结构化日志(/var/log/journal) rsyslog 接收 纯文本日志(/var/log/secure 等) 日志过滤 / 匹配规则 日志格式转换 / 路由 本地文件存储 用于本地排查 / 审计溯源 远程日志服务器 集中存储 / 统一分析 建议同时启用两条通道 实现冗余存储 + 格式互补

说实话,把这两套系统捋清楚后,Linux日志采集对你来说就没秘密了。rsyslog的稳定可靠加上journald的精细元数据,这套组合能让你的审计日志采集既有广度又有深度。我在多个项目里都是这么配的,从来没有因为日志采集问题被追责过——嗯,这就是专业配置的价值。