ARTICLE DETAIL

资讯详情

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

Linux登录审计核心命令last:读懂wtmp日志与常用参数实战

Linux登录审计核心命令last:读懂wtmp日志与常用参数实战 1. 先搞清楚last命令到底在翻阅哪本“流水账”——wtmp与登录审计原理1.1 为什么last能知道“谁来过、什么时候走的”很多刚接触Linux的朋友第一次敲下last命令时屏幕里哗啦啦滚出几十行记录心里想的都是同一个问题它凭什么知道这些答案其实不复杂——系统里一直有一本持续追加的“登录流水账”这本账就是/var/log/wtmp文件。用户在终端里输入用户名密码、通过SSH远程登录、在图形界面打开会话系统都会在登录成功、会话退出、系统重启等关键时刻把一条记录追加进wtmp文件里。last命令本身并不“发明”历史它只是这本账簿的“翻译官”——把里面一条条二进制记录翻译成人能看懂的文本。你可以这样理解wtmp类似于饭店门口的签到簿谁来了、几点来、坐几号桌、几点走服务员都会记一笔。last干的事情就是拿起这本签到簿按顾客名字、到店时间给你规整地背出来。过度引申一下这就是Linux日志审计体系的起点。一个人什么时候登录过、登录了多久、从哪里登录只要没有被人为清理wtmp里都会留下痕迹。1.2 三兄弟utmp、wtmp、btmp各管一段很多教程一上来就让你记住三个文件路径但不说它们之间的区别结果就是死记硬背。这里我用最直白的话一次讲清文件名所在路径记录内容utmp/var/run/utmp当前登录会话的即时快照也就是“此刻谁在线”wtmp/var/log/wtmp登录、登出、重启等历史流水也就是“以前都有谁来过”btmp/var/log/btmp登录失败的记录也就是“谁在门外试过钥匙”三者之间不是包含关系而是分工关系。who和w命令读的是utmp回答的是“现在”last读的是wtmp回答的是“过去”lastb读的是btmp回答的是“谁在尝试但没成功”。也正是因为wtmp是持续追加的这本“流水账”会越滚越大所以发行版通常会用logrotate对它做轮转。轮转之后的老文件就成了/var/log/wtmp.1、wtmp.2.gz这种带序号的文件。这一点在后面第5章我会展开讲这是一个很容易被忽略、但排查老记录时特别关键的知识点。1.3 千万别用cat去读wtmp说句实话我见过不少新手第一次探索系统时想直接cat /var/log/wtmp看内容结果屏幕里全是乱码和特殊符号以为日志文件坏了。这不是文件损坏而是wtmp是二进制格式它用一套内部结构记录时间戳、用户名、终端名、来源IP这些信息普通文本工具读不懂。要读它就必须交给last这个专门的解释器。这也是last比直接看日志文件更高效的根本原因它把解析隐藏到了幕后你只要关注结果就行了。类似的道理utmpdump也可以把utmp/wtmp里的原始二进制结构导出来但日常使用里last的默认输出已经足够友好完全够用。2. 命令输出的每一列都暗藏玄机——last输出字段与特殊标记全解读2.1 一列一列拆开看先看一段典型的last输出$ last -n 5 root pts/0 192.168.1.108 Fri Dec 6 10:22 still logged in user01 pts/1 10.0.0.15 Thu Dec 5 22:10 - 23:45 (01:35) reboot system boot 5.15.0-91-generic Thu Dec 5 09:00 still running gong pts/2 :0 Thu Dec 5 08:30 - 08:32 (00:02) demo :0 :0 Wed Dec 4 18:44 - down (00:05)逐列翻译其实信息量非常大位置内容含义第1列用户名或系统事件名发起会话的用户或者reboot等特殊事件第2列终端设备pts/0是SSH或本地终端模拟器tty1是物理控制台:0是图形界面第3列来源地址或内核信息远程登录会显示来源IP或主机名本地登录常显示为:0第4列登入时间这条会话是什么时候开始建立的第5列登出时间会话是什么时候结束的如果还没结束显示特殊状态词第6列持续时长用小括号括起来的登录总时长比如(01:35)表示登录了1小时35分如果你愿意还可以加上-F参数时间立刻变成更完整的格式年月日、时分秒甚至秒级都给你列出来。默认的四列时间格式只精确到分钟在审计场景下往往不够用所以我会在后面反复强调能上-F就上。2.2 那几个必须认识的状态词新手最容易困惑的其实不是数值列而是文字状态。比如still logged in、still running、down、crash第一次见都会懵。这里统一解释清楚still logged in这条会话到现在还没结束用户仍然在线。你敲last的时候所有登录中的会话都会以这个状态出现在最新几行。down系统从某个时间点开始进入关机状态。通常是正常关机留下的收官记录。reboot系统发生了重启第二列的system boot和第三列的内核版本号能帮你确认具体是哪一次启动。crash系统没有正常走完关机流程大概率是断电、内核崩溃或者被人强制重启。审计时出现crash要特别留个心眼。still running当前系统从某次启动后一直运行到现在还没关机或重启过。还有一个提示信息叫wtmp begins ...它表示这个wtmp文件从什么时间点开始记录内容。比如wtmp begins Fri Dec 1 08:00:00 2024意味着你只能看到这个时间之后的记录更早的历史要么被轮转走了要么一开始就没记。把这些状态词和业务场景一结合能做的事情就很清晰了。比如你想确认“这台机器最近有没有被人重启过”直接执行last reboot结果一目了然想确认“服务器是不是意外断电过”就看输出里有没有非正常数量的crash条目。3. 让last按你的要求干活——常用参数组合与真实运维场景实战3.1 先背下来这几个高频参数last默认会从最新的记录往旧的方向返回一直列到wtmp文件头碰到大日志会刷屏到怀疑人生。所以日常使用基本都是先选参数再执行。我把最高频的几个参数做成了表格你直接照着用就行参数作用示例-n NUM只显示最近NUM条记录last -n 20-F显示完整时间格式精确到秒last -F -n 10-f FILE指定日志文件默认是/var/log/wtmplast -f /var/log/wtmp.1-i来源地址显示为纯IP不做反向DNS解析last -i -n 15-a把来源主机名显示在最后一列方便对齐阅读last -a -n 10-x显示系统关机、重启等特殊记录last -x -n 20-R不显示来源主机名输出更干净last -R -n 10这里特别说明一下-i和-a的价值。默认情况下last拿到来源IP后会尝试做反向DNS解析把IP解析成主机名。解析过程需要网络请求在DNS不通或者反向解析超时的时候命令会卡住好几秒才出结果。生产环境里排查问题本来就紧张等这几秒钟非常难受。我个人的习惯是几乎永远加-i直接看IP需要主机名的时候再单独处理。-a则纯粹是美观对齐用的它把来源地址放到最后一列日志多的时候扫起来视觉压力小很多。3.2 几个我常用的命令组合直接抄作业场景一某台服务器今天到底有没有人进来过last -i -F -n 30这条命令适合每天例行巡检时开个头。用-F看到秒级时间用-i看真实IP最近30条记录里当天的情况基本都覆盖了。如果登录行为特别频繁可以把-n 30换成-s 2024-12-01 08:00:00这类时间范围过滤不过要注意-s和-t的写法在不同发行版上存在差异最好先last --help确认一下。场景二排查某个账号是否被异地登录last username -i -F把命令后面的位置替换成用户名就把某一个人的登录历史单独筛出来了。审计账号时非常常用。比如有一个运维账号平时固定从公司IP登录某天突然出现一个外地IP那你大概率要把它当成安全事件来看待。我个人比较激进一点一旦看到异常IP第一反应是sudo lastb -i -n 50看看这个账号有没有同时段失败登录记录再决定要不要立刻改密码、踢掉已有会话。场景三统计服务器重启频率last reboot | head -20重启记录也是wtmp的一部分。服务器莫名重启又找不到原因时先用这条命令看看重启时间点是否和业务异常时间对得上能快速缩小排查范围。如果重启记录里有crash状态基本可以判断不是正常流程触发的关机再开机大概率要往硬件、内核错误、机房断电这些方向查。场景四统计谁的登录次数最多last -F | awk {print $1} | sort | uniq -c | sort -nr这条命令把第一列用户名全部提取出来排序后统计出现次数再做降序排列。输出的第一行就是这台机器上登录最频繁的用户。配合head -1使用能快速回答“谁的登录次数最多”这种问题。注意关键字不要漏掉reboot它也会被统计进来需要手动在awk时过滤掉。场景五查看登录失败记录sudo lastb -i -n 20lastb读的是btmp文件记录的是认证失败的尝试。默认情况下lastb需要root权限因为btmp文件的权限比较严格。这条命令在做暴力破解排查时非常有用如果btmp里有同一个IP反复尝试不同用户名说明这台机器正在被字典尝试轰炸。别问我怎么知道的经历过一次就懂了。3.3 一个完整排查思路串一遍把上面的参数组合到一条实操链路里你会有更直观的感受。假设某天早上业务监控报警说服务在凌晨3点被重启过而值班的人说没有人动过它。你登上服务器后可以按这个顺序查先执行last -x -F -i | head -20看最近的重启和关机记录锁定确认到底有没有重启、发生在几点几分。然后用last -F -i -n 50回头看重启前后有没有可疑账号登录尤其是从没见过的来源IP。如果发现异常IP立刻sudo lastb -i -n 50看这个IP有没有同时段暴力尝试。再配合who看当前有没有异常在线会话有的话直接pkill -u 用户名或者更保守一点先把会话踢掉再改密码。这套组合拳打完绝大多数“半夜被重启”的谜团都能定位到七七八八。倒不是说last能直接告诉你谁执行了shutdown而是它能帮你圈定时间窗口和目标账号接下来再去翻/var/log/syslog或者journalctl效率会高很多。4. 登录审计的完整拼图——last、lastb、lastlog的分工与配合4.1 三兄弟到底有什么不同写运维方案的时候经常看到有人把last、lastb、lastlog混为一谈其实它们各自盯着一本完全不同的账本。前面已经说过last读wtmp、lastb读btmplastlog则单独维护一份文件路径通常是/var/log/lastlog记录的是“每个用户最后一次登录的时间、终端和IP”。它们之间的差异可以这样归纳last回答历史上有哪些登录成功事件。lastb回答历史上有哪些登录失败事件。lastlog回答每个账号最后一次成功登录是什么时候。值得注意的是lastlog在某些发行版上默认并不开启记录。如果你的机器上执行lastlog得到“未找到命令”或者输出全为空先不要慌检查一下软件包是否安装比如Debian系可以安装login包里的lastlog工具也可以用aulastlog代替后者是auditd套件里的实现。4.2 把三兄弟组合成一条审计流水线单一命令看多了容易形成“局部视角”真正实用的是把它们组合起来形成一条巡检链路。我自己的做法是这样的每天早晨连上服务器后固定执行下面三组命令大约花费不到一分钟last -F -i -n 5 # 看最近5条成功登录 sudo lastb -F -i -n 10 # 看最近10条失败登录 lastlog | grep -v Never logged in # 看哪些账号最近登录过如果三者产生关联就值得进一步追究。比如last里出现一个陌生来源IP的成功登录同时lastb里这个IP又有一大串失败尝试那基本可以断定是撞库成功后进来的。此时再看lastlog如果受影响账号的最后登录时间正好落在那个时间窗附近几乎就能还原整套攻击路径了。这还没完我更推荐把巡检做成定时任务。比如把last的输出追加到一个审计文件里last -F -i /var/log/login-history-$(date \%Y\%m\%d).log这样即便系统的wtmp被人为清空或者轮转覆盖你手里仍然有一份按天归档的历史记录。虽然last不能像专业审计工具那样给出完整的四方报告但作为轻量级的第一手证据它够快、够直观、够用了。如果你对审计有更高要求再上auditd或者把日志实时转发到远程日志服务器last仍然可以当作快速侦察工具保留在手边。4.3 和who、w命令配合使用who和w是和last互补性很强的工具。who输出当前登录用户列表w则在who的基础上额外显示每个会话在执行什么命令。当你用last查到某用户“still logged in”时下一步就是执行w 用户名看看这个在线会话现在正在跑什么操作。如果发现一个明明不认识的人在线并且正在执行rm、curl这类命令那就不是分析历史的问题了而是要先断会话。这三条命令配合起来才能从“过去”延伸到“现在”把审计闭环走完。5. 那些年我踩过的last命令的坑——边界情况与处理经验5.1 日志轮转之后老记录去哪了默认情况下/var/log/wtmp会跟着logrotate的周期轮转。以常见的Debian/Ubuntu配置为例wtmp通常按周或按月轮转轮转后的文件变成wtmp.1、wtmp.2.gz等。last默认只读当前这个wtmp所以你想查一个月前的记录直接敲last是看不到的必须指定老文件last -f /var/log/wtmp.1如果是压缩过的wtmp.2.gz需要先解压再交给lastzcat /var/log/wtmp.2.gz /tmp/wtmp.2 last -f /tmp/wtmp.2一个更省事的做法是把多个wtmp文件按顺序合并后再查询。不过注意wtmp每条记录里都带有时间戳直接拼接虽然能查但可能出现时间倒序需要自己再用sort处理。我个人很少做合并更多是按需指定单一文件够用就行。这里要小心一个认知误区有些新手看到last输出第一行写着wtmp begins ...就以为日志文件坏了或者被清空过。其实这行只是说明当前这个文件的起始时间区间不代表所有记录都没了。真正要警惕的是last一行记录都没有、只显示wtmp begins并且时间戳离现在很近那才说明日志在某个时间点之后被重置过收入时就要多留个心眼了。5.2 时间显示不对先检查时区和系统时间排查登录时长时如果发现last输出的时间明显不对比如来源于IP显示的登入时间与业务日志对不上第一时间要检查系统时区。Linux服务器的/etc/localtime配置如果被改过wtmp里记录的时间戳本身是UTC存储的显示出来会根据当前系统时区换算。所以不是last算错是系统时区变过。遇到这种情况可以用date -R看看系统和UTC的偏移量再核对last -F的输出就能判断是换算问题还是原始记录本身错误。另外时间错乱的另一个常见原因是虚拟化环境里做了时间漂移校正可能导致记录瞬间“跳到未来”不过这种情况属于少见异常真遇到了优先检查NTP同步即可。5.3 权限问题与日志可信度wtmp文件默认权限通常是664属主是root、属组是utmp。普通用户能读wtmp但btmp由于记录了失败尝试的信息权限一般收得更紧只有root用户能读。所以在非特权用户下执行lastb大概率会提示Permission denied这属于正常现象不是命令有问题。在安全视角下一个更重要的提醒是last完全依赖于wtmp文件而wtmp文件一旦被root权限入侵者拿到修改甚至清空都是可能的。所以它只能作为“常规审计”的入口不能当作绝对可信的证据链。如果你负责的服务器合规性要求比较高一定要配合远程日志、集中采集这类手段把日志实时同步到其他机器上。这也是很多运维老手即使有了auditd仍然习惯先看last的原因——它足够轻量适合做第一轮筛查真正要追责的时候靠的是系统外保存的日志副本。5.4 长期运行的主机账号名可能重复出现如果服务器常年不关机wtmp里的记录量会非常大一个问题就是同一个账号的登录会话可能被拆分成多条记录从A终端登录记了一条后来从B终端登录又记了一条。单纯按用户名统计登录次数可能会把同一个人在不同终端上的会话重复计入。统计的时候想精确一点就同时把终端字段纳入统计维度last -F | awk {print $1, $2} | sort | uniq -c | sort -nr这种统计方式能区分“同一用户在不同终端上的登录”在审计多人共用的机器时会更准确。不过也不要过度较真在没有明确规范要求时按用户名统计已经能反映大部分登录行为趋势够用就好。5.5 一条实测小技巧长时间无人操作的会话如果你发现某用户的状态是still logged in但持续时间已经好几个小时可以考虑进一步确认这个会话是否已经僵死。执行w 用户名如果对应的JCPU和PCPU时间几乎没变化大概率是一个挂起的SSH连接一直占着会话没退出。这种会话多了会拖累服务器资源影响其他用户的连接数。处理办法通常是通过pkill -u 用户名强制结束该用户所有会话或者在业务允许的情况下直接重启SSH服务。当然操作前最好和用户确认一下毕竟把人家正在跑的编译任务断掉可是会挨骂的。说了这么多其实last命令的底层逻辑一点不深奥它有本事让系统里最原始的那些登录痕迹重新开口说话。我之前排查过一台服务器的异常重启最后就是靠last -x -F -i把时间窗口精确到秒、再顺藤摸瓜找到对应用户整个过程不到五分钟。平时花几十秒敲一行last养成的习惯关键时刻能帮你省下几个小时。所以我的建议很直接——把last -F -i写进你的肌肉记忆里当你不确定服务器发生了什么先让它告诉你谁来过、谁还在。
返回列表