第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
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负责远程转发和日志格式转换。
这样做的好处很明显:
- 审计日志服务器的格式统一,不会因为不同Linux发行版的差异导致解析困难
- 本地还保留了完整的元数据,供未来深入分析使用
- rsyslog的网络传输功能非常成熟,有断点续传、TLS加密等能力
配置上只需要在journald.conf里开启ForwardToSyslog=yes,然后让rsyslog按规则转发即可。我自己的生产环境用了5年多,几乎没出过问题。
我们用一个图来展示这套体系的整体结构:
说实话,把这两套系统捋清楚后,Linux日志采集对你来说就没秘密了。rsyslog的稳定可靠加上journald的精细元数据,这套组合能让你的审计日志采集既有广度又有深度。我在多个项目里都是这么配的,从来没有因为日志采集问题被追责过——嗯,这就是专业配置的价值。