利用 libvirt 和 Linux 审计子系统跟踪 KVM 客户机

概述

Libvirt 被广泛应用于管理 Linux® 上的虚拟化环境。它提供了各种丰富的功能,包括客户机生命周期管理、资源分配、资源管理(使用 cgroups),以及通过 SELinux 实现安全强制 (security enforcement) 等。所有这些操作均是由 libvirt 执行,主要处理被分配给客户机或从客户机释放的主机资源。

从 0.9.0 版本开始,libvirt 就能够与主机上的 Linux 审计子系统通信,发出有关若干操作的记录。这是一项重要特性,允许系统管理员、审计员,甚至其他应用程序访问虚拟化环境中详细的变更历史,包括客户机生命周期操作,以及主机资源到客户机的分配变化。

Linux 审计子系统能够处理来自不同来源的许多种操作,而不仅仅是 libvirt 发出的与虚拟化有关的事件。审计系统常用于跟踪文件变更、来自 SELinux 或 AppAmor 的安全拒绝 (security denial),以及系统调用。这些不同的事件包含对虚拟机审计有用的信息。

例如,SELinux 策略可能禁止访问某个分配给客户机的资源,这将生成一个 AVC (Access Vector Cache) 拒绝记录。尽管该事件不是由 libvirt 发出,但是它与一个客户机关联。类似地,许多事件都可以与客户机关联,其中包含由内核或用户空间内的程序生成的异常事件。

在下一节中,我们将快速了解审计系统如何工作,libvirt 如何与之交互,以及如何从审计日志获取与客户机相关的信息。

审计基础知识

Linux 内核负责生成大部分审计事件,例如系统调用事件、文件监视事件和安全事件。但是用户应用程序也可以生成事件。

Linux 审计系统的核心组件就是内核。由其他组件生成的所有事件首先将被发送给内核。在内核中,将应用一系列规则来决定是否应当丢弃某个事件。图 1 展示了构成 Linux 审计系统的组件。


图 1. 审计系统组件
利用 libvirt 和 Linux 审计子系统跟踪 KVM 客户机_第1张图片

内核中的审计规则可以通过 auditctl 命令修改。一些具有特殊功能的应用程序,如 libvirt daemon,被认为是可信任的应用程序,能够向内核发送审计事件。在应用了规则后,内核向 audit daemon 发送审计事件。然后 audit daemon 将记录写入到磁盘,并使用 auditspd daemon 分配定制操作。

其他组件(ausearch、aureport、aulast 和 auvirt)均为用户空间工具,用于解析审计日志并以更简单的形式呈现信息。auvirt 工具专门用于呈现与虚拟化有关的事件和关联事件。

需要注意审计事件和审计记录之间的区别。审计事件是由受审计的用户或应用程序所发起的一个操作,例如:文件打开事件就是一个可以受审计的事件。此外,审计记录包含仅与事件的某个方面有关的信息。因此,一个事件可能跨越审计日志中的一个或多个记录。以文件打开为例,该事件可以生成两条记录,一条记录包含与被调用的开放 syscall 有关的信息,另一条记录包含与所访问的文件有关的记录。(参见 清单 1 获得示例)。


清单 1. 打开文件事件的审计记录(使用独立区域显示以清晰呈现)
				
type=SYSCALL msg=audit(1328292445.908:40194): arch=c000003e syscall=2 
 success=yes exit=3 a0=7fffe3d2e85c a1=941 a2=1b6 a3=7fffe3d2c570 items=3
 ppid=26377 pid=26677 auid=500 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0
 fsgid=0 tty=pts8 ses=1 comm="touch" exe="/bin/touch"
 subj=unconfined_u:unconfined_r:unconfined_t:s0 key=(null) 

type=CWD msg=audit(1328292445.908:40194):  cwd="/home/mhcerri" 

type=PATH msg=audit(1328292445.908:40194): item=0 name="/tmp/file" 
 inode=1196 dev=fd:01 mode=0100775 ouid=500 ogid=501 rdev=00:00 
 obj=unconfined_u:object_r:user_tmp_t:s0

注意,每条记录都有一个不同的类型,所有三条记录都包含 "1328292445.908:40194" 字符串。这是事件标识符。冒号前的头两个数字为事件时间戳,第一个为 UNIX® 事件(单位为秒),第二个为毫秒值。第三个数字是生成的序列号。还需注意,审计记录中使用的格式有些复杂,因此审计系统提供了一些工具帮助您显示审计日志。

Libvirt 和 Audit

Libvirt 实际上生成三种类型的记录。它们都包含一条通用记录,“uuid” 字段。这是一个 Universal Unique Identifier,标识所有记录中 libvirt 发出的客户机。libvirt 使用的记录类型为:

  • VIRT_CONTROL:在虚拟机生命周期的每个阶段生成。它将在客户机启动或停止时生成,并且包含运行原因和客户机名称等字段。
  • VIRT_MACHINE_ID:它是在 libvirt 尝试向客户机分配安全标签时生成的。在对 QEMU 使用 sVirt 时,该记录将包含 QEMU 流程的安全标签和分配给客户机的磁盘安全标签。
  • VIRT_RESOURCE:该类型的记录在客户机的资源分配出现变化时生成,例如,当从客户机中移除磁盘,或向客户机连接一个新的网络设备。

Auvirt

auvirt 工具将搜索审计日志,查找由 libvirt 生成的记录,展示虚拟机会话列表。它还查找其他一些事件,如主机宕机、与客户机有关的 AVC 拒绝事件,以及与 QEMU 有关的异常事件。清单 2 展示了一个 auvirt 输出例子。第一个字段为客户机名称。第二个为启动客户机的用户。第三个为客户机运行的时间范围。注意,示例中 “Arch” 的执行已失败,而另一个仍然保持运行。


清单 2. Auvirt 输出
				
# auvirt
Fedora                 	root       	Tue Jan 24 16:28 - 16:28  (00:00)
Fedora                 	root       	Wed Jan 25 10:31 - 10:34  (00:02)
CentOS                 	root       	Wed Jan 25 10:34 - 13:50  (03:16)
Fedora                 	root       	Wed Jan 25 13:51 - 13:54  (00:03)
Fedora                 	root       	Wed Jan 25 13:54 - 13:55  (00:00)
Arch                   	root       	Wed Jan 25 13:55 - failed
Arch                   	root       	Wed Jan 25 13:56

可以通过下面的选项将输出限制到一个特定的时间范围:

  • --start <date> [<time>]:为将要使用的时间期限确定一个开始时间
  • --end <date> [<time>]:为将要使用的时间期限确定一个结束时间

如果忽略 <time>,工具将把开始和结束时间默认设置为 “00:00:00” 和 “23:59:59”。


清单 3. 按时间过滤 auvirt 输出
				
# auvirt --start 01/25/2012 12:00:00 --end  01/25/2012
Fedora                  root        Wed Jan 25 13:51 - 13:54  (00:03)
Fedora                  root        Wed Jan 25 13:54 - 13:55  (00:00)
Arch                    root        Wed Jan 25 13:55 - failed
Arch                    root        Wed Jan 25 13:56

也可以将结果限制到一个客户机。该客户机可以通过客户机名称或客户机的 UUID 指定。默认情况下,为了保持输出简单,工具不会显示 UUID,但是您可以通过 --show-uuid 选项在输出中包含它。


清单 4. 按客户机名称和 UUID 过滤 auvirt 输出(使用独立区域显示以清晰呈现)
				
# auvirt --vm Fedora
Fedora                  root        Tue Jan 24 16:28 - 16:28  (00:00)
Fedora                  root        Wed Jan 25 10:31 - 10:34  (00:02)
Fedora                  root        Wed Jan 25 13:51 - 13:54  (00:03)
Fedora                  root        Wed Jan 25 13:54 - 13:55  (00:00)

# auvirt --show-uuid --uuid cabf9532-99f1-3756-930f-59e8f19d4144 
Arch                    cabf9532-99f1-3756-930f-59e8f19d4144    root
 Wed Jan 25 13:55 - failed
Arch                    cabf9532-99f1-3756-930f-59e8f19d4144    root 
 Wed Jan 25 13:56

默认情况下,auvirt 将显示一个简化的输出。要展示所有与虚拟化有关的事件,可以使用 --all-events 选项。使用该选项后,auvirt 将展示每个起始和结束事件、资源分配和相关事件的记录。清单 5 展示了使用 --all-events 选项的例子。


清单 5. 详细的 auvirt 输出(为了清晰显示进行了编辑,参见下载部分获得完整的输出)
				
# auvirt --vm CentOS --all-events
down                            root            Wed Jan 25 08:34
res   CentOS                    root            Wed Jan 25 10:34 - 13:50  (03:16)
 cgroup          allow           major   rw      pty

[...]

avc   CentOS                    root            Wed Jan 25 10:34
 relabelto       denied          libvirtd        CentOS.img
 system_u:object_r:svirt_image_t:s0:c6,c883

[...]

res   CentOS                    root            Wed Jan 25 10:34 - 13:50  (03:16)
 disk            start           /var/lib/libvirt/images/CentOS.img
res   CentOS                    root            Wed Jan 25 10:34 - 13:50  (03:16)
 net             start           52:54:00:DB:AE:B4
res   CentOS                    root            Wed Jan 25 10:34 - 13:50  (03:16)
 mem             start           1048576
res   CentOS                    root            Wed Jan 25 10:34 - 13:50  (03:16)
 vcpu            start           1
start CentOS                    root            Wed Jan 25 10:34 - 13:50  (03:16)

[...]

stop  CentOS                    root            Wed Jan 25 13:50

第一个字段表示事件类型,包含以下值:start、stop、res、avc、anom 和 down(表示主机宕机)。

资源分配和 AVC 记录包含额外的字段,提供相关的信息。资源分配中的额外字段包括:

  • 资源类型:描述可分配给客户机的不同的资源类型,如磁盘、虚拟 CPU、内存和网络设备等。此外,libvirt 可以通过 Cgroups 设置为限制每个客户机使用的资源,这也被记录为一个资源事件。该字段的可能值包括:vcpu、mem、disk、net 和 cgroup。
  • 原因:表示哪个操作引起资源分配事件。例如,当客户机启动或运行时,可以将一个磁盘分配给客户机,对于这些情况,原因值可以为 “start” 或 “attach”。对于 Cgroups 事件,原因字段表示是否允许或拒绝某个资源,它的值可以为 “allow” 或 “deny”。
  • 资源:指分配给客户机的资源。路径用于磁盘资源,兆字节用于内存,MAC 地址用于网络设备,VCPU 数量用于虚拟 CPU。对于 Cgroups 事件,该值由三个部分组成:类型、ACL 和资源。

auvirt 报告的 AVC 事件表示客户机执行的访问没有被拒绝,而主机中另一个进程对客户机资源进行的访问被拒绝。AVC 事件包含的额外字段包括:

  • 操作:指流程执行的操作被拒绝。例子包括:read、write、open、relabelto 和 relabelfrom。
  • 操作结果:通常为拒绝。
  • 程序:尝试执行拒绝操作的流程的程序名。
  • 目标:拒绝操作的目标。例如,如果主机内部的一个流程试图访问客户机的磁盘映像文件,并且访问被 SELinux 拒绝,那么该字段将包含磁盘映像文件名。
  • 上下文:对于 relabeltorelabelfrom 操作,额外又包含了字段,表示相关的安全上下文:relabelto 的目标上下文和 relabelfrom 的源上下文。

访问原始数据

Auvirt 提供了用户友好的输出,不必包含审计日志中的所有事件信息。有时,这些额外的信息可能有用,需要访问原始数据来获得更详细的信息。Auvirt 包含 --proof 选项,可用于显示审计事件标识符(用于生成输出中的每条记录)。


清单 6. Auvirt --proof 选项
				
# auvirt --vm Fedora -ts 01/23/2012 00:00 -te 01/23/2012 17:30 --proof 
Fedora                      root        Mon Jan 23 17:02 - 17:27  (00:24)
    Proof: 1327345338.087:41631, 1327346831.548:41702 

清单 6 显示了 auvirt 示例,显示了用于创建记录的开始和停止事件标识符。通过这些信息,您可以使用 ausearch 工具从审计日志中提取原始记录(参见 清单 7)。


清单 7. 使用 ausearch 获得原始记录(使用独立区域显示以清晰呈现)
				
# ausearch -a 41631 --start 01/23/2012 17:02:00 --end 01/23/2012 17:27:59 
---- 
time->Mon Jan 23 17:02:18 2012 
type=VIRT_CONTROL msg=audit(1327345338.087:41631): user pid=2433 uid=0
 auid=4294967295 ses=4294967295 subj=system_u:system_r:initrc_t:s0 msg='virt=kvm 
 op=start reason=booted vm="Fedora" uuid=7bcae45c-c179-6cea-a185-c7abe50520c7: 
 exe="/usr/sbin/libvirtd" hostname=? addr=? terminal=? res=success'

该示例使用了 -a 选项,将输出限制到带有给定序列号的记录,还使用了 --start--end 选项,它们与 auvirt 选项的工作方式相同。注意,原始记录包含了额外的信息,如原因、可执行文件名称和 pid。

结束语

云计算正在变得越来越普及,虚拟化开始成为一项主流技术。清晰地理解虚拟化环境中发生的变化变得愈加重要。此外,对于某些特定的行业,如政府和金融,审计也成为一项必须满足的要求。本文介绍了可用于过滤与虚拟化相关的主机审计事件的审计工具。通过使用这些事件,您可以了解到主机和客户机上发生的客户机事件,从而获得更加全面的客户机审计跟踪

你可能感兴趣的:(利用 libvirt 和 Linux 审计子系统跟踪 KVM 客户机)