ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Linux日志体系实战:从故障排查到安全审计与事件复盘

Linux日志体系实战:从故障排查到安全审计与事件复盘 日志这东西平时没人惦记真到出事儿的时候——服务器宕了、被人入侵了、业务半夜报警了——你才会发现它比命都重要。我干了这么多年运维和安全见过太多同事一上来就 tail -f /var/log/messages 瞎翻翻半天找不着重点最后只能重装系统。说白了不是日志没用是你不会用。这篇东西我不讲虚的就把 Linux 下日志体系那点事儿掰开揉碎了讲清楚从故障排查到安全审计再到安全事件复盘一条线全串起来全是实际干活儿用得上的东西。1. 日志体系全景先弄清楚日志都藏在哪很多新手上来就盯着 /var/log/messages 看这没错但那只是冰山一角。Linux 日志体系的完整程度远超你的想象关键在于你知不知道去哪找、怎么看。我用一台标准的 CentOS 7.9 和一台 Ubuntu 22.04 混着讲因为两台机器的日志目录结构有细微差异但核心逻辑完全一致。1.1 核心日志文件逐一拆解先列一张我平时排查问题必看的日志清单这张表我建议你直接截图存下来日志文件记录内容主要用途/var/log/messages系统级通用日志涵盖内核、服务启动、硬件状态等故障排查首选几乎所有异常都能在这看到影子/var/log/secure安全验证日志记录登录、sudo、ssh 认证等安全审计必查看有没有人爆破你的服务器/var/log/boot.log系统启动日志开机异常、内核 panic 排查/var/log/dmesg内核环形缓冲区日志硬件识别、驱动加载、磁盘故障定位/var/log/croncron 定时任务日志排查定时任务为什么不执行/var/log/maillog邮件服务日志postfix、sendmail 相关排查/var/log/httpd/ 或 /var/log/nginx/Web 服务访问日志和错误日志Web 故障排查、渗透测试痕迹分析/var/log/journal/systemd-journald 持久化日志所有服务的标准输出和错误输出现代排查核心/var/log/audit/audit.logLinux 审计框架日志安全追踪文件访问、系统调用级别的审计这些文件的命名在不同发行版上略有差异比如 Ubuntu 上 /var/log/messages 被合并进了 /var/log/syslogauth.log 对应 CentOS 的 secure。但看日志的核心思路是一样的先判断你遇到的问题属于哪一类然后直奔对应的日志文件。1.2 systemd-journald 和 rsyslog 的分工现代 Linux 发行版基本都跑着两套日志系统systemd-journald 和 rsyslog。很多人搞不清她俩啥关系其实很好理解journald 是亲儿子rsyslog 是干儿子但俩人都得用。systemd-journald 负责把所有服务的标准输出、标准错误、内核日志统统收进二进制格式的 journal 文件里。好处是结构化了带时间戳、带优先级、带 unit 名查起来飞快。坏处是它默认存在 /run/log/journal/ 下这是个内存文件系统重启就没了。想要持久化必须手动建目录mkdir -p /var/log/journal systemd-kill -s USR1 $(pidof systemd-journald)而 rsyslog 则是传统文本日志的制造商它从 journald 里接收数据再按照配置规则写成 /var/log/messages、/var/log/secure 这些纯文本文件。这样做的意义在于纯文本文件可以用 grep、awk、tail 这些经典工具随意处理而且可以轻松配置远程日志转发。我个人建议生产环境两套都开journald 做快速检索和结构化查询rsyslog 做文本归档和关键词分析两手抓两手都要硬。2. 故障排查journalctl 与经典日志的分析套路真正做故障排查绝大多数人第一步就是打开终端然后犯愁日志文件这么大从哪看起这里我给你一套我自己用的排查套路按照这套思路走大部分问题都能在十分钟内锁定根因。2.1 journalctl 高效检索技法如果服务器是 CentOS 7 之后或者 Ubuntu 16.04 之后的系统journalctl 是你最趁手的兵器。这工具最强大的地方在于时间过滤和 unit 过滤。举个例子假设你的 nginx 服务在凌晨 3 点崩了千万别直接翻 /var/log/nginx/error.log先看一眼系统日志怎么说# 查看 nginx 服务最近 50 条日志 journalctl -u nginx -n 50 # 查看某个时间段内的所有系统日志时间格式非常灵活 journalctl --since 2024-01-15 02:50 --until 2024-01-15 03:10 # 查看内核级别的报错 journalctl -k -p err # 实时滚动查看和 tail -f 效果类似但信息更丰富 journalctl -f这里我最常用的是 -p 参数它按日志优先级过滤。Linux 日志优先级从 0 到 70 是 emergency7 是 debug。排查问题我只关心 0 到 4 级别的也就是 emerg 到 warning这就足够筛掉大量无用的信息。2.2 磁盘写满与误删恢复的场景复盘说个我实际处理过的案例。某天客户的数据库服务器突然报只读文件系统错误所有写操作全部失败。我登上机器第一件事就是 df -h果然根分区 100%。这时候重点来了怎么快速定位是哪个文件把磁盘塞满的# 查看哪些大文件在占用空间 du -sh /* 2/dev/null | sort -rh | head -10 # 重点排查被删除但还被进程占用的文件 lsof L1lsof L1 这个命令特别关键它列出所有被标记为删除但仍然被进程打开的文件。遇到磁盘满的情况经常是运维删了 /var/log/messages 但 rsyslog 进程还攥着文件句柄不放空间根本没释放。这种情况你就算把磁盘翻个底朝天也找不到那个文件了因为目录项已经没了但 inode 还被进程引用着。解决方案就是重启那个进程或者直接清空而非删除文件。另外插一句很多日志文件删不掉是因为权限或文件锁问题此时用 truncate 清空比 rm 删除更适合日志场景# 安全清空日志无需删除文件不影响正在写的进程 truncate -s 0 /var/log/messages2.3 服务起不来先查 Permission denied服务启动失败是故障排查里占比最高的一类问题而 Permission denied 又是其中的王者。很多人在 systemctl start xxx 失败后用 systemctl status xxx 看一眼红色文字就蒙了其实真正有用的是 journalctl 里那一大段堆栈。前阵子帮人排查一个 MySQL 起不来的问题systemctl status 只显示 failed我执行了journalctl -u mysqld -n 100结果最后一行豁然写着 Cant create/write to file /var/run/mysqld/mysqld.pid (Errcode: 13 - Permission denied)。原因就是 /var/run/mysqld 目录的所有者被误改成了 rootMySQL 进程用 mysql 用户跑没权限创建 PID 文件。解决方案一句话chown mysql:mysql /var/run/mysqld这类问题靠猜很难猜对但只要你养成了「服务起不来先查 journalctl」的习惯基本五分钟就能把根因挖出来。别老在配置文件里翻来覆去地改方向错了改一百遍也白搭。3. 安全审计登录日志、sudo记录与审计框架的实战组合故障排查是日志的常规用途但日志真正的黄金价值在安全领域。被入侵了怎么发现攻击者是怎么进来的进来了干了什么这些问题全靠日志来回答。我常说一句话没有日志的安全系统等于没有监控的银行金库丢了东西你连怎么丢的都不知道。3.1 登录日志里的蛛丝马迹先看最基础的登录日志。CentOS 上它在 /var/log/secureUbuntu 上在 /var/log/auth.logDebian 系也是 auth.log。别小看这个文件它能告诉你所有登录尝试的成败记录。# 查看所有失败的登录尝试 grep Failed password /var/log/secure | tail -50 # 查看成功的登录记录重点关注来源 IP grep Accepted /var/log/secure | tail -20 # 统计哪些 IP 爆破次数最多 grep Failed password /var/log/secure | awk {print $(NF-3)} | sort | uniq -c | sort -nr | head -20这里我解释一下 awk 取 IP 的小技巧。secure 日志里常见的格式是 Failed password for root from 192.168.1.100 port 22 ssh2倒数第四个字段也就是 $(NF-3)恰好就是来源 IP。这段命令是我每次安全审计的保留节目跑一遍就知道哪些 IP 在持续爆破。正常生产服务器一天失败的 ssh 尝试可能上万次这非常正常互联网上扫描器太多了。你要关注的不只是失败次数而是有没有成功记录。一旦在 Accepted 列表里看到你完全不认识的 IP那就是已经被人拿下了赶紧查后渗透痕迹别等。3.2 sudo 操作审计的进阶玩法/var/log/secure 里同样记录了所有 sudo 提权操作。很多人提到安全审计就只盯着 SSH 登录却忽略了 sudo 记录这是个大漏子。攻击者拿到一个低权限用户后最想干的事情就是 sudo 提权而 sudo 的每条指令都会在这里留下痕迹# 查看所有 sudo 执行记录 grep sudo /var/log/secure | tail -100看这条命令的输出你能清楚地看到某个用户在什么时间用 sudo 执行了什么命令。正常运维人员每天执行的 sudo 命令就那么几条如果某天突然出现大量 sudo 操作比如有人不停尝试 sudo -l 查看当前权限或者尝试 sudo bash 切换 root这就是典型的入侵信号。我自己做安全审计喜欢用一个组合查询把用户行为和时间段关联起来分析# 查看某个小时内的所有安全事件按时间排序 grep 2024-01-18T0[1-3] /var/log/secure | sort这样能在最短时间内对攻击者的整个攻击窗口有一个全局把握。另外提醒一句实在担心 sudo 日志不够详细的话可以考虑用 auditd 针对 sudo 命令做系统调用级别的审计后面我会详细讲。3.3 auditd 审计框架的实战配置如果说 secure 日志是宏观层面的安全记录那 auditd 就是显微镜级别的安全审计。它能精确到某个文件被谁读写了、某个系统调用是谁触发的这在追踪攻击者行为时特别有用。安装和启用 auditdyum install audit audit-libs -y # CentOS systemctl start auditd systemctl enable auditdauditd 的灵魂是规则。看两个我常用的规则场景。第一个场景监控 /etc/passwd防止攻击者创建新用户auditctl -w /etc/passwd -p wa -k user-passwd-monitor-w 指定监控的文件-p 指定监控的权限类型wa 是 write 和 attribute change-k 加一个自定义的 key 方便搜索。设置完之后任何对 /etc/passwd 的修改都会被记录到 /var/log/audit/audit.log 里。这条规则对应急响应来说就是救命的稻草攻击者拿到权限后最喜欢干的就是新建一个用户作为后门而监控 /etc/passwd 就是看死这道门。第二个场景监控 /root/.bash_history防止攻击者篡改操作痕迹auditctl -w /root/.bash_history -p wa -k root-history-monitor查询审计日志ausearch -k user-passwd-monitorausearch 是 auditd 配套的查询工具按 key 检索非常方便。输出的结果里最关键的信息包含时间戳、用户 UID、操作类型和结果success 或 fail这些在安全事件复盘时都是实打实的证据。还有一个非常有用的配置就是开启 auditd 对 sudo 命令的同步审计可以通过在 /etc/audit/rules.d/audit.rules 中追加-w /usr/bin/sudo -p x -k sudo_cmd_monitor这样每次有人执行 sudo都会在 audit.log 里留下记录连参数都清清楚楚。这个粒度比 secure 日志要深得多而且 audit.log 是二进制格式攻击者想篡改也比较困难。3.4 保证日志只能追加防篡改配置安全审计里最常见的一个需求就是保证日志只能追加不能删除和修改。攻击者得手之后第一件事往往就是清理日志把 /var/log/secure 里的记录删干净。怎么防利用 Linux 的 immutable 属性。chattr 命令可以给文件加上不可修改的属性chattr a /var/log/secure chattr i /etc/passwda 表示只能追加不能覆盖和删除日志文件非常适合这个属性。i 权限更严格文件完全不可变连追加都不行适合保护配置文件。加了 immutable 属性之后就算你是 root想删除安全日志也会得到 Operation not permitted 的报错。实际操作中要注意chattr a 操作会影响 rsyslog 正常写入吗答案是不会。rsyslog 写日志是打开文件后从文件末尾追加写入这属于 append 操作被 a 属性允许。但如果你要用 truncate 清空日志那就会被拒绝这正好达到防篡改的目的。一条命令查询已设置 immutable 属性的文件lsattr /var/log/secure输出有个 a 标记就证明属性生效了。这么做的意义在于即使攻击者拿到了 root他也没法轻易篡改关键日志这给你争取了宝贵的溯源时间。4. 安全事件复盘从日志痕迹还原攻击路径接下来这部分是安全圈最看重的活儿。什么叫复盘就是攻击已经发生了你要靠日志把攻击者的完整行为链条还原出来他是怎么进来的、进来之后干了什么、用什么方式维持了权限、有没有数据被带走。这个过程说白了就是和时间赛跑抢在日志过期前把证据固定下来。4.1 确定入侵时间点是复盘第一步一切复盘的起点是定位攻击者首次入侵的时间。我的做法是先从成功登录记录入手。# 找出所有成功登录按时间正序排列 grep Accepted /var/log/secure | sort | head -50重点看时间轴里有没有异常的跳变比如某天凌晨 2 点的登录记录或者来自你从未见过的地理位置 IP。确定时间点之后以这个时间为起点往后查所有安全相关的日志变更。同时别忘了一个细节/var/log/wtmp 和 /var/log/btmp。wtmp 记录所有成功登录的历史btmp 记录所有失败登录的尝试这俩都是二进制文件要用 last 和 lastb 去读last # 查看历史登录记录 lastb # 查看失败登录记录lastb 对判断暴力破解的规模特别有参考价值。如果失败尝试次数高达数万次那攻击者大概率走了暴力破解路线如果失败只有几次但随后就有成功登录那可能是撞库或者弱口令直接命中。4.2 复盘攻击路径的关键命令组合拳入侵时间点锁定后接下来的核心工作是还原攻击者拿到权限后做了什么。我的复盘三板斧是这样的第一板斧查历史命令。cat /root/.bash_history如果攻击者已经切换成了 root那 .bash_history 会记录他后续的每一步操作。当然有经验的黑客会先清除这个文件但清除了也没关系下面还有别的证据。第二板斧查进程和网络连接。攻击者必然会留下后门进程或者外连通信通过 ps 和 netstat 找到异常项ps aux --sort-%cpu | head -20 netstat -antlp | grep ESTABLISHED重点关注建立起外部连接的可疑进程。我之前复盘过一台被植入挖矿木马的服务器就是通过 netstat 看到一个进程不停向一个境外 IP 发起连接然后顺藤摸瓜找到 /tmp 下的恶意二进制文件。第三板斧查系统的计划任务和后门文件。攻击者最常用的持久化手段就是 cron、systemd service、以及放一个 setuid 后门文件。crontab -l ls -al /etc/cron.* find / -perm -4000 -type f 2/dev/null4.3 应急响应时的止损与证据固定复盘还没完紧急动作和证据保全必须同步推进。这里分享一套我实践过的标准应急响应流程第一步立即切外网或者调整防火墙策略限制所有外部访问只保留你当前的安全 SSH 连接。注意别直接断开所有网络你要留着通道下载工具、执行命令。第二步立即复制关键日志到安全位置防止攻击者后续清除mkdir /security_backup cp -a /var/log/secure /var/log/messages /var/log/wtmp /security_backup/ chattr i /security_backup/*第三步抓取当前进程快照和网络连接快照保留现场ps aux /security_backup/ps_snapshot.txt netstat -antlp /security_backup/netstat_snapshot.txt last /security_backup/last_snapshot.txt第四步对可疑的二进制文件不要直接执行先用 file 命令确认文件格式用 strings 提取可疑字符串谨慎情况下先拷贝一份再分析。这套流程走下来既保住了攻击现场又能堵住攻击者可能用于提权的入口。等复盘分析做完再根据结论决定是重装系统还是彻底清理后门。5. 系统日志规范配置轮转、持久化与远程集中管理前面讲的全是怎么用日志这一节聊聊怎么管日志。很多人日志用的溜但管理一团糟日志文件无限增长最终把磁盘塞爆或者日志留存时间太短出事时关键记录早被轮转覆盖了。这些坑我都踩过现在把我的最佳实践整理清楚。5.1 logrotate 日志轮转配置指南日志轮转最怕什么最怕该转的时候没转不该转的时候瞎转。logrotate 是解决这个问题的标准工具它由 cron 驱动按天或按大小自动切分、压缩、删除旧日志。看一个我为 nginx 配置的 logrotate 示例放在 /etc/logrotate.d/nginx/var/log/nginx/*.log { daily rotate 30 compress delaycompress missingok notifempty create 0640 nginx adm sharedscripts postrotate if [ -f /var/run/nginx.pid ]; then kill -USR1 cat /var/run/nginx.pid fi endscript }daily每天轮转一次。rotate 30保留 30 份。compress压缩旧日志delaycompress 表示延迟一天压缩这样让 nginx 顺利写完再压缩。postrotate轮转后给 nginx 发送 USR1 信号让它重新打开新的日志文件。生产环境里我的建议是重要的安全日志secure、audit.log保留至少 90 天普通消息日志保留 30 天就够。存储成本真的不高但要是关键日志提前被覆盖那代价就大了这个账必须算清楚。5.2 journald 持久化与容量限制journald 默认在内存里转重启丢数据所以我前面说了必须先建 /var/log/journal 目录。除此之外你还需要限制 journald 的磁盘占用不然它也会膨胀得离谱。配置文件在 /etc/systemd/journald.conf关键参数[Journal] Storagepersistent SystemMaxUse1G SystemMaxFileSize128M MaxRetentionSec90dayStoragepersistent持久化存储。SystemMaxUse1G整个 journal 目录最多占用 1G 磁盘。MaxRetentionSec90day最多保留 90 天日志。改完配置之后 systemctl restart systemd-journald 生效。设完这四行journald 就变成「有上限有期限」的持久化日志系统了。万一你的合规要求需要日志存一年就把 SystemMaxUse 改大到 10G 甚至 50G根据实际磁盘规划来。5.3 远程日志集中管理rsyslog 转发配置最后说说远程日志。我一直认为真正常用的日志系统必须有一个远程集中端。原因很简单本地日志防得了菜鸟黑客防不了老手。攻击者拿到 root 之后 chattr a 也能解、/var/log 也能清唯一清不掉的是不在本机的远程日志。配置 rsyslog 远程日志转发只需要在客户端上创建 /etc/rsyslog.d/remote.conf*.* 192.168.100.10:514这行配置把本机所有日志转发到 192.168.100.10 的 UDP 514 端口。如果担心丢日志把单 改成双 走 TCP 协议*.* 192.168.100.10:514服务端日志收集服务器在 /etc/rsyslog.conf 里放开接收配置# 在全局配置里添加 module(loadimudp) input(typeimudp port514) # 如果走 TCP module(loadimtcp) input(typeimtcp port514)收下来的日志按来源主机分目录存放避免所有机器日志混在一起可以在 /etc/rsyslog.conf 里加个模板$template RemoteLogs,/var/log/remote/%fromhost-ip%/%programname%.log *.* ?RemoteLogs这样一来即便某台服务器被入侵攻击者把本地日志删得干干净净远程日志中心照样记录着他的一举一动。这项工作在运维和安全体系里叫日志集中管理属于最基础但最有效的安全防护措施之一。6. 常见问题速查与实战心得到最后了把前面这些年踩过的坑整理一下做成速查表方便真到了紧急情况时对照使用。遇到问题别慌按图索骥。6.1 日志排查高频问题速查表症状首选查看位置关键排查命令磁盘爆满df -h然后定位大文件lsof L1 找被删但占用的文件服务启动失败journalctl -u 服务名journalctl -u mysqld -n 100SSH 登录慢/var/log/secure查有没有大量失败尝试占带宽系统过一会儿就卡死/var/log/messagesgrep OOM 查内存溢出定时任务不执行/var/log/cron检查是否有 No such file or directoryWeb 访问异常Nginx/Apache 的 error.logtail -f error.log疑似被入侵/var/log/secure audit.loggrep Accepted ausearch内核模块加载失败dmesgdmesg | grep -i errorRTC 时间异常/var/log/messagesgrep -i rtc6.2 日志时间的时区陷阱与排序坑日志排查有个常年坑人的点——时间戳。/var/log/messages 和 secure 默认用的系统本地时间而 journald 默认显示的是 UTC 或者本地时间取决于配置。我之前排查一个问题翻 messages 和 journald 的日志发现时间线对不上后来一查是 journald 的时区配置不一致导致。建议所有服务器统一时区为 Asia/Shanghaitimedatectl set-timezone Asia/Shanghai并在 /etc/rsyslog.conf 里加上时间戳格式模板确保所有日志时间基准一致。还有一个排序的问题日志文件是记录了就往后面追加但如果你用 grep 过滤出来的内容是按磁盘顺序输出的不是严格按时间排序。我在复盘安全事件时就吃过这个亏看到的时间顺序和实际发生的顺序有偏差差点判断错了攻击者行为链。现在我处理这类问题都会刻意地用 sort 或者管道加重排序逻辑保证基于时间的分析万无一失。6.3 遗留小技巧给日志分析加点效率最后分享几个我日常分析日志时的习惯操作。第一给 tail 加别名随时带行号看最新日志alias lttail -f /var/log/messages | nl第二用 grep 加上下文来获取报错前后的完整上下文grep -A 20 -B 10 OutOfMemory /var/log/messages-A 和 -B 分别表示显示匹配行后的 20 行和前 10 行这个对于分析一出错误报错前后的状态非常重要。第三写个简单脚本来统计关键词出现次数快速评估危害程度for word in OutOfMemory Segfault Permission denied FAILED; do echo $word: $(grep -ci $word /var/log/messages) done每次应急响应先跑一遍这段脚本能快速判断一下服务器上最严重的几个问题分布。这套方法我已经用了很多年效率非常高希望你也能用上。说到底日志就是一台服务器的黑匣子飞机失事要靠黑匣子还原现场服务器出问题也一样。从故障排查时快速定位根因到安全审计时发现攻击痕迹再到安全事件复盘时还原完整攻击链全部依赖这套日志体系。平时多花半小时了解日志配置到关键时刻就能少熬几个通宵。这些都是我最真实的经验总结希望对你有用。
返回列表