三亩地 三亩地SAN MU DI · CODE DIARY
ARTICLE DETAIL

日记详情

真实记录编程学习的某一天,欢迎挑你感兴趣的翻一翻。

Ubuntu用户登录与操作历史全解析:从基础命令到auditd审计实战

Ubuntu用户登录与操作历史全解析:从基础命令到auditd审计实战

1. 从一次线上故障排查说起:为什么我们需要追溯用户操作?

去年,我负责维护的一个线上服务突然出现性能雪崩,CPU使用率飙升到90%以上,导致部分业务接口响应超时。登录服务器一看,几个核心进程的负载高得吓人。第一反应是代码有内存泄漏或者死循环?但最近并没有发布新版本。正当团队焦头烂额准备重启服务时,我多问了一句:“最近有谁在这台机器上操作过吗?” 一位同事小声说,他半小时前登录上去,想手动清理一下日志文件。

问题瞬间清晰了。他使用了类似find /var/log -name “*.log” -exec rm {} \;的命令,但路径写得不精确,加上通配符使用不当,意外地递归删除了大量正在被进程写入的日志文件,导致某些进程陷入异常状态,进而引发连锁反应。如果当时能快速、清晰地看到“谁、在什么时候、执行了什么命令”,我们至少能节省一个多小时的无效排查时间,直接定位到操作者并询问其操作细节。

这个经历让我深刻体会到,在一个多用户、多角色的Linux服务器环境(尤其是像Ubuntu这样的生产或开发服务器)中,清晰地掌握用户登录及操作历史,不是系统管理员的“选修课”,而是保障系统安全、进行故障排查、落实责任审计的“生命线”。无论是追踪恶意行为、复盘误操作,还是简单地了解服务器负载变化前有哪些人为动作,这些历史记录都是最直接、最可靠的证据链。

今天,我们就以Ubuntu系统为例,抛开那些华而不实的理论,直接上干货,系统地梳理一下如何查看用户登录及操作历史。我会从最基础的命令讲起,深入到各种日志文件的关联分析,并分享一些我在实践中总结的增强监控与审计的心得技巧。无论你是刚接触Linux的开发者,还是需要管理服务器集群的运维工程师,这些内容都能帮你构建起一套有效的用户行为追踪能力。

2. 用户登录记录:谁在什么时候进来了?

用户登录是用户与系统交互的起点。在Ubuntu中,记录登录行为的信息分散在几个关键的文件和命令里,它们各有侧重,结合起来才能拼出完整的画面。

2.1 实时与近期登录:who,w,last,lastlog

这几个命令是快速了解当前和近期登录情况的瑞士军刀,无需深入日志文件,结果直观。

whow命令:看看现在谁在线上

who命令列出当前所有登录到系统的用户会话信息,非常轻量快捷。

who

典型的输出如下:

ubuntu pts/0 2024-05-10 14:30 (192.168.1.100) jenkins pts/1 2024-05-10 13:15 (10.0.0.5)
  • 第一列(ubuntu, jenkins):登录用户名。
  • 第二列(pts/0, pts/1):用户使用的终端标识。pts(伪终端)通常代表通过SSH等远程方式登录,tty代表直接连接的控制台。
  • 第三列(2024-05-10 14:30):登录时间。
  • 第四列((192.168.1.100)):登录来源的主机名或IP地址。这对于判断登录是否来自可信网络至关重要。

w命令可以看作是who的增强版,它除了显示登录用户,还会额外显示用户当前正在执行的命令(WHAT)以及系统负载(LOAD AVERAGE)。

w

输出示例:

14:35:10 up 15 days, 2:30, 2 users, load average: 0.08, 0.03, 0.01 USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT ubuntu pts/0 192.168.1.100 14:30 5.00s 0.05s 0.00s w jenkins pts/1 10.0.0.5 13:15 1:20m 0.02s 0.00s tail -f /var/log/syslog
  • WHAT列非常有用,它能直接告诉你用户正在做什么。比如上面可以看到jenkins用户正在跟踪系统日志。
  • IDLE列显示用户空闲时间,对于清理长期不活动的会话有参考价值。
  • JCPUPCPU反映了该终端关联进程和当前进程的CPU时间消耗。

实操心得:在应急响应时,我第一个敲的命令往往是w。因为它不仅能快速确认入侵者是否还在线(看FROM的IP是否陌生),还能看到他正在执行什么破坏性命令(WHAT列),为立即中断其会话提供依据。

last命令:翻阅系统的“登录日记”

last命令用于查询系统自创建以来所有的登录、注销、重启记录。它读取的是/var/log/wtmp二进制日志文件。

# 查看所有历史登录记录 last # 查看特定用户(如ubuntu)的登录历史 last ubuntu # 查看最近10条记录 last -n 10

输出示例:

ubuntu pts/0 192.168.1.100 Fri May 10 14:30 still logged in jenkins pts/1 10.0.0.5 Fri May 10 13:15 still logged in reboot system boot 5.4.0-42-generic Fri May 10 13:00 - 14:36 (01:36) ubuntu pts/0 192.168.1.100 Thu May 9 09:20 - crash (1+03:40)
  • 每一行代表一次登录会话或系统事件。
  • still logged in表示该会话目前仍处于活动状态。
  • reboot行记录了系统重启事件,这对于排查因重启导致的服务中断非常关键。
  • 末尾的(01:36)表示会话持续时长或系统运行时长。

lastlog命令:检查所有用户的“最后登录”时间

lastlog命令格式化输出/var/log/lastlog文件,显示系统中所有用户最近一次登录的时间。

lastlog

输出示例:

Username Port From Latest root **Never logged in** ubuntu pts/0 192.168.1.100 Fri May 10 14:30:30 +0800 2024 jenkins pts/1 10.0.0.5 Fri May 10 13:15:15 +0800 2024 mysql **Never logged in**
  • 这个命令对于账户审计特别有用。你可以快速发现哪些系统账户(如mysql,www-data)从未登录过(这通常是正常现象),以及哪些用户账户长期未登录(可能已成僵尸账户,存在安全隐患)。
  • 如果发现一个本该活跃的用户账户显示“从未登录”,或者一个普通用户从异常地点登录,那就需要警惕了。

2.2 深入日志文件:/var/log/auth.logsecure(syslog)

命令行工具虽然方便,但其背后的数据源才是根本。对于登录、认证、授权等安全相关事件,Ubuntu 系统主要将其记录在/var/log/auth.log文件中(在某些其他发行版中可能是/var/log/secure)。

这个文件是纯文本格式,由rsyslogsyslog服务管理,内容非常详尽。我们使用grep,tail,less等工具来查看。

# 实时跟踪认证日志(在另一个终端窗口执行,用于监控) sudo tail -f /var/log/auth.log # 查看包含“Accepted password”或“Accepted publickey”的行,即成功的登录 sudo grep “Accepted” /var/log/auth.log # 查看包含“Failed password”的行,即失败的登录尝试(暴力破解迹象) sudo grep “Failed password” /var/log/auth.log # 查看特定用户(如ubuntu)的所有认证日志 sudo grep “ubuntu” /var/log/auth.log

auth.log中的一条成功SSH登录记录通常如下:

May 10 14:30:30 ubuntu-server sshd[12345]: Accepted password for ubuntu from 192.168.1.100 port 54322 ssh2 May 10 14:30:30 ubuntu-server sshd[12345]: pam_unix(sshd:session): session opened for user ubuntu by (uid=0)
  • 第一段(May 10 14:30:30 ubuntu-server):时间戳和主机名。
  • 第二段(sshd[12345]):产生日志的进程(sshd守护进程)及其PID。
  • 第三段:具体事件描述。“Accepted password”表示密码认证成功;“Accepted publickey”表示密钥认证成功。后面紧跟用户名和来源IP。
  • 第四段(session opened):表示系统为该用户创建了一个新的会话。

一条失败的登录尝试记录如下:

May 10 14:29:15 ubuntu-server sshd[12344]: Failed password for invalid user hacker from 203.0.113.5 port 6667 ssh2
  • invalid user hacker表明攻击者尝试了一个不存在的用户名hacker
  • 如果短时间内出现大量来自同一IP的“Failed password”记录,这是非常明显的暴力破解攻击信号。

避坑指南/var/log/auth.log文件默认会轮转(logrotate),旧日志会被压缩成auth.log.1.gz,auth.log.2.gz等。当你需要调查几天甚至几周前的登录事件时,别忘了去检查这些压缩文件。可以使用zcatzgrep命令直接查看压缩内容,例如:zgrep “Accepted” /var/log/auth.log.2.gz

3. 用户操作历史:进来之后做了什么?

知道谁登录了还不够,更重要的是知道他做了什么。这里主要依赖两个机制:Shell历史记录和进程审计日志。

3.1 Shell命令历史:.bash_historyhistory命令

这是最直接、最常用的用户操作记录。当用户在Bash Shell(Ubuntu默认Shell)中执行命令时,这些命令会被记录在内存的历史列表中,并在退出Shell时(或达到HISTSIZE限制时)写入到用户家目录下的.bash_history隐藏文件中。

查看当前用户的命令历史

# 查看当前会话中执行过的所有命令(包括序号) history # 查看最近20条命令 history 20 # 执行历史记录中的第101条命令 !101 # 搜索包含“grep”的历史命令 history | grep grep

查看其他用户的命令历史文件每个用户的命令历史独立保存在其家目录~/.bash_history中。需要具有相应权限(通常是root)才能查看。

# 查看用户‘ubuntu’的命令历史 sudo cat /home/ubuntu/.bash_history # 或 sudo less /home/ubuntu/.bash_history

Shell历史记录的局限性及增强配置默认的.bash_history机制有几个明显的缺陷,在安全审计场景下需要特别注意:

  1. 会话隔离性:默认配置下,命令只在Shell正常退出时才写入文件。如果用户通过kill -9强制结束终端,或者系统突然崩溃,那么该会话中的所有命令历史都会丢失。
  2. 时间戳缺失:默认的.bash_history文件只记录命令,不记录命令执行的时间。这在追溯“某个命令是何时执行的”时非常无力。
  3. 易被篡改或清除:用户有权清空自己的.bash_history文件(history -chistory -w),或者直接删除该文件,从而抹去操作痕迹。

为了强化审计,我强烈建议在全局或特定用户的 Bash 配置中(/etc/bash.bashrc或用户家目录的~/.bashrc)添加以下配置:

# 将以下行添加到 ~/.bashrc 或 /etc/bash.bashrc 的末尾 # 设置历史记录格式,包含时间戳 export HISTTIMEFORMAT=“%F %T ” # 强制每条命令执行后立即写入历史文件,而不是等退出时 shopt -s histappend export PROMPT_COMMAND=“history -a;$PROMPT_COMMAND” # 设置历史记录文件大小和条数(可调整) export HISTSIZE=10000 export HISTFILESIZE=20000 # 忽略重复命令和空格开头的命令(以空格开头的命令不会被记录) export HISTCONTROL=ignoreboth
  • HISTTIMEFORMAT:这是关键。设置后,使用history命令会显示每条命令的执行时间。
  • PROMPT_COMMAND:这个技巧让Bash在每次显示命令提示符前,都执行history -a命令,将当前内存中的历史记录追加到历史文件中,实现了“实时写入”,解决了会话隔离问题。
  • HISTCONTROL=ignoreboth:忽略重复的连续命令和以空格开头的命令。后者是一个小技巧,如果用户不想让某条敏感命令被记录,可以在输入命令前加一个空格。

配置生效后(source ~/.bashrc),history的输出会变成:

1001 2024-05-10 14:35:10 ls -la 1002 2024-05-10 14:35:15 cd /var/log 1003 2024-05-10 14:35:20 sudo tail -f auth.log

时间和命令一一对应,审计价值大大提升。

经验之谈:在调查安全事件时,如果发现用户的.bash_history文件异常干净或只有几条无关紧要的命令,这本身就是一个巨大的红色警报。攻击者入侵后,往往会第一时间清空历史记录。此时,你需要转向下一节更底层的审计工具。

3.2 系统级进程审计:auditd框架

.bash_history不可信或被绕过时(比如用户使用其他Shell,或通过非交互式脚本执行命令),我们就需要更底层的监控手段。Linux Audit Daemon (auditd) 是内核级别的审计框架,它可以记录系统调用和文件访问,功能极其强大,是专业安全审计的基石。

安装与启动 auditd在Ubuntu上,auditd通常不是默认安装的。

sudo apt update sudo apt install auditd audispd-plugins -y sudo systemctl enable --now auditd

配置审计规则:监控关键命令的执行auditd的威力在于其灵活的规则系统。规则可以通过命令行临时添加,或永久写入配置文件/etc/audit/rules.d/audit.rules

假设我们要监控所有用户对rm,mv,cp命令的执行,以及对/etc/passwd,/etc/shadow等关键文件的访问。

  1. 使用auditctl命令添加临时规则

    # 监控‘rm’命令的执行(监控execve系统调用,且路径匹配*/bin/rm) sudo auditctl -a always,exit -F arch=b64 -S execve -F path=/bin/rm -k “delete_cmd” # 监控‘passwd’文件的任何写属性更改 sudo auditctl -w /etc/passwd -p wa -k “passwd_change”
    • -a always,exit:在系统调用退出时总是记录。
    • -F arch=b64:针对64位系统。
    • -S execve:监控执行程序的系统调用。
    • -F path=...:指定要监控的程序路径。
    • -w ...:监控文件路径。
    • -p wa:监控文件的写(w)和属性更改(a)操作。
    • -k:为这条规则打上一个“关键词”标签,方便后续搜索。
  2. 永久规则配置: 将上述规则(去掉auditctl)写入/etc/audit/rules.d/audit.rules文件,然后重启auditd服务 (sudo systemctl restart auditd) 即可永久生效。

查询审计日志审计日志默认存储在/var/log/audit/audit.log,是二进制格式,需要使用专用工具ausearchaureport来查看。

# 查看所有日志(内容非常详细) sudo ausearch -i # 查看带有特定关键词的日志(如我们上面设置的‘delete_cmd’) sudo ausearch -k delete_cmd -i # 查看今天的所有审计事件 sudo ausearch -ts today -i # 使用aureport生成汇总报告,更友好 sudo aureport --summary # 事件摘要 sudo aureport -x --summary # 可执行文件调用报告 sudo aureport -f --summary # 文件操作报告

一条典型的ausearch输出(经过-i解释后)如下:

type=SYSCALL msg=audit(2024-05-10 14:40:00.123:456) : arch=x86_64 syscall=execve success=yes exit=0 a0=0x7ffc12345678 a1=0x7ffc12345690 items=2 ppid=5678 pid=9012 auid=ubuntu uid=ubuntu gid=ubuntu euid=ubuntu suid=ubuntu fsuid=ubuntu egid=ubuntu sgid=ubuntu fsgid=ubuntu tty=pts0 comm=rm exe=/usr/bin/rm key=delete_cmd

这条记录告诉我们:在指定时间,用户ubuntu(auid是审计用户ID,通常等于登录uid)在终端pts0上成功执行了/usr/bin/rm命令,进程PID是9012,父进程PPID是5678,并且这条记录关联着我们定义的delete_cmd关键词。

高级技巧与避坑auditd功能强大但配置复杂,日志量也可能非常庞大。在生产环境中,务必:

  1. 规则要精确:避免使用过于宽泛的规则(如监控所有execve),否则日志会瞬间爆炸,影响性能且难以分析。应该针对关键命令、关键文件和关键用户进行监控。
  2. 关注auidauditd记录的auid(审计用户ID)是用户登录时的原始ID,即使用户后续通过susudo切换了身份,auid也不会变。这为追踪操作的最终责任人提供了可靠依据,而uid可能只是当前进程的有效用户ID。
  3. 日志轮转与归档:配置好/etc/audit/auditd.conf中的max_log_filenum_logs参数,并考虑将重要的审计日志实时同步到远程的日志服务器(SIEM)上,防止攻击者本地擦除。

4. 关联分析与进阶排查:拼凑完整的证据链

在实际的故障排查或安全事件响应中,我们很少只依赖单一来源的信息。通常需要将登录记录、操作历史和系统其他日志(如应用日志、系统消息日志)关联起来,形成一条完整的时间线。

4.1 时间线重建:一个模拟案例

假设我们在auth.log中发现一条可疑的深夜成功登录记录:

May 10 02:15:10 server sshd[22222]: Accepted publickey for deploy from 198.51.100.77 port 12345 ssh2

用户deploy从IP198.51.100.77登录。我们需要知道这个用户登录后做了什么。

第一步:检查该用户的命令历史

sudo cat /home/deploy/.bash_history

如果历史记录被清空或内容可疑,进行下一步。

第二步:使用last确认登录会话

last deploy

确认在May 10 02:15左右确实有一个来自该IP的登录会话,并记下其终端号(例如pts/3)。

第三步:搜索系统日志 (/var/log/syslog) 中该时间点附近、与该终端或用户相关的活动

sudo grep “May 10 02:1[5-9]” /var/log/syslog | grep -E “(deploy|pts/3)”

可能会发现该用户启动了某个服务,或者修改了某个配置文件。

第四步:如果配置了auditd,搜索该时间段的审计日志

sudo ausearch -ts 05/10/2024 02:15:00 -te 05/10/2024 02:30:00 -ua deploy -i

这能列出该用户在该时间段内所有的系统调用事件,可能包括执行了哪些二进制文件、访问了哪些敏感路径。

第五步:检查进程记账(如果启用)Ubuntu 还可以通过acct包启用进程记账功能,它会记录所有进程的详细信息(谁、何时、执行了何命令、消耗多少资源)。

# 安装进程记账 sudo apt install acct sudo systemctl enable --now psacct # 使用 `lastcomm` 查看所有执行过的命令记录 sudo lastcomm # 查看特定用户执行过的命令 sudo lastcomm deploy # 查看特定命令(如find)的执行历史 sudo lastcomm find

lastcomm的输出包含用户、终端、命令、执行时间、退出状态等,是.bash_history的强力补充。

通过这样多维度、交叉验证的分析,我们就能相对清晰地还原出用户deploy在登录后的一系列操作,判断其行为是正常的运维操作,还是恶意的入侵行为。

4.2 可视化与集中式日志管理

对于服务器数量众多的环境,逐台登录去查日志是不现实的。成熟的运维体系会建立集中式的日志管理平台,例如使用ELK Stack (Elasticsearch, Logstash, Kibana)Grafana Loki

其基本工作流是:

  1. 在每台服务器上部署一个日志收集器(如Filebeat,Fluentd,Promtail)。
  2. 收集器实时读取本地的auth.logaudit.log、应用日志等。
  3. 将日志发送到中央的索引和存储系统(如 Elasticsearch 或 Loki)。
  4. 通过可视化界面(Kibana 或 Grafana)进行统一的搜索、分析和仪表盘展示。

在这种架构下,你可以:

  • 在一个界面中,全局搜索某个IP地址在所有服务器上的登录尝试。
  • 设置告警规则,当某台服务器出现多次“Failed password”日志时,自动发送告警通知。
  • 绘制用户登录热力图,直观展示异常时间的登录活动。

个人体会:搭建集中日志系统初期有一定成本,但一旦建成,对于安全监控和运维效率的提升是颠覆性的。它让“追溯用户行为”从一个被动的、手动的、基于单机的排查动作,变成了一个主动的、自动的、全局的可观测性能力。即使资源有限,我也建议至少将关键服务器的auth.log通过rsyslog转发到一台专用的日志服务器上,实现简单的集中存储和防篡改。

5. 安全加固与最佳实践:让历史记录更可靠

了解了查看方法,我们更要思考如何让这些记录本身变得更可靠、更难以被篡改。以下是一些关键的最佳实践:

  1. 配置安全的 Bash History:如前文所述,强制在/etc/profile/etc/bash.bashrc中为所有用户设置HISTTIMEFORMAT和实时写入 (PROMPT_COMMAND),并设置足够大的HISTSIZE

  2. 设置日志文件的不可更改属性(Immutable Flag):对于 root 用户,可以通过chattr命令为关键日志文件添加i(immutable)属性,防止被意外或恶意修改、删除。(注意:这可能会影响正常的日志轮转,需谨慎操作或配合脚本临时解除属性)

    sudo chattr +i /var/log/auth.log sudo chattr +i /var/log/audit/audit.log # 解除属性使用 `chattr -i`
  3. 启用并合理配置auditd:对于重要的生产服务器,务必安装和配置auditd。规则应聚焦于:

    • 监控特权命令(/bin/su,/usr/bin/sudo,/usr/bin/passwd)。
    • 监控敏感文件(/etc/passwd,/etc/shadow,/etc/sudoers, 网站根目录等)。
    • 监控管理用户(如root,ubuntu, 以及所有具有sudo权限的用户)的所有执行操作。
  4. 远程日志记录(Syslog Forwarding):配置rsyslogauth.logaudit.log实时发送到一台受保护的、独立的日志服务器。这样即使攻击者攻陷了业务服务器并清除了本地日志,在远程服务器上依然留有证据。在/etc/rsyslog.conf中添加如*.* @remote-log-server-ip:514的配置即可实现。

  5. 使用sudo并记录详细日志:强制所有管理操作通过sudo进行。在/etc/sudoers文件中,确保存在Defaults logfile=”/var/log/sudo.log”Defaults log_input, log_output这样的配置。log_inputlog_output会记录sudo会话中所有的输入和输出,提供了极其详细的审计追踪,但会占用大量磁盘空间,请根据需求启用。

  6. 定期审计与审查:建立制度,定期(如每周)审查关键日志,关注异常登录时间、异常来源IP、失败登录暴增、特权命令的使用等情况。可以将审查工作自动化,通过脚本扫描日志并生成报告。

用户行为的历史记录是Linux系统安全与运维的“黑匣子”。从简单的lasthistory,到强大的auditd框架,再到集中式的日志分析平台,工具链的深度决定了你审计能力的强度。对于个人开发者或小型团队,掌握前两节的基础命令足以应对日常绝大部分需求。而对于负责关键基础设施的工程师,深入理解auditd和构建集中日志体系,则是迈向专业运维和安全管理的必经之路。记住,这些日志不仅是出问题后的“调查工具”,更是震慑潜在不当行为、提升整体系统安全水位的“预防性措施”。花时间配置好它们,在真正需要的时候,你会感谢自己当初做的这些工作。

← 返回列表