在我的服务器上,我有一个名为“cards2”的 KVM 虚拟机。它是通过执行(以 root 身份)创建的:
# virt-install --connect qemu:///system --virt-type kvm --name cards2 --ram 2048 --disk /var/kvm/cards2.qcow,size=3 --vcpus=8 --cdrom /var/kvm/debian-8.5.0-amd64-netinst.iso --vnc --os-type linux --network network=default
该图像具有权限:
# ls -l /var/kvm/cards2.qcow
-rwxr-xr-x 1 libvirt-qemu libvirt-qemu 3221225472 Aug 17 18:49 /var/kvm/cards2.qcow
然而我注意到任何具有 SSH 访问权限的用户可以通过执行以下操作来访问虚拟机:
virt-viewer --connect qemu+ssh://[email protected]/system vmname
(注意,这个命令是执行远程,而不是在服务器上。这将通过 SSH 隧道使用连接 URI 连接到虚拟机管理程序)qemu+ssh://[email protected]
用户username
只是组的成员username
。使用 SSH 帐户登录时,username
虚拟机列表显示为空:
$ virsh list --all
Id Name State
----------------------------------------------------
而且,当我通过 SSH 执行以下操作时,我也无法使用套接字进行连接:
$ virsh --connect qemu:///system list --all
error: Failed to connect socket to '/var/run/libvirt/libvirt-sock': Permission denied
我还尝试删除/usr/bin/vir*
不属于该kvm
组的用户的所有文件的权限:
# chown root:kvm /usr/bin/vir*
# chmod o-rx /usr/bin/vir*
# ls /usr/bin/vir* -l
-rwxr-x--- 1 root kvm 321120 Jul 1 04:46 /usr/bin/virsh
-rwxr-x--- 1 root kvm 32184 Dec 7 2013 /usr/bin/virt-alignment-scan
-rwxr-x--- 1 root kvm 28128 Dec 7 2013 /usr/bin/virt-cat
-rwxr-x--- 1 root kvm 9774 Sep 29 2014 /usr/bin/virt-clone
-rwxr-x--- 1 root kvm 10277 Sep 29 2014 /usr/bin/virt-convert
-rwxr-x--- 1 root kvm 806 Dec 7 2013 /usr/bin/virt-copy-in
-rwxr-x--- 1 root kvm 808 Dec 7 2013 /usr/bin/virt-copy-out
-rwxr-x--- 1 root kvm 54584 Dec 7 2013 /usr/bin/virt-df
-rwxr-x--- 1 root kvm 33312 Dec 7 2013 /usr/bin/virt-edit
-rwxr-x--- 1 root kvm 54536 Dec 7 2013 /usr/bin/virt-filesystems
-rwxr-x--- 1 root kvm 30112 Dec 7 2013 /usr/bin/virt-format
-rwxr-x--- 1 root kvm 14656 Jul 1 04:46 /usr/bin/virt-host-validate
-rwxr-x--- 1 root kvm 7944 Sep 29 2014 /usr/bin/virt-image
-rwxr-x--- 1 root kvm 44696 Dec 7 2013 /usr/bin/virt-inspector
-rwxr-x--- 1 root kvm 36992 Sep 29 2014 /usr/bin/virt-install
-rwxr-x--- 1 root kvm 5338 Dec 7 2013 /usr/bin/virt-list-filesystems
-rwxr-x--- 1 root kvm 6686 Dec 7 2013 /usr/bin/virt-list-partitions
-rwxr-x--- 1 root kvm 53816 Dec 7 2013 /usr/bin/virt-ls
-rwxr-x--- 1 root kvm 18641 Dec 7 2013 /usr/bin/virt-make-fs
-rwxr-x--- 1 root kvm 9600 Jul 1 04:46 /usr/bin/virt-pki-validate
-rwxr-x--- 1 root kvm 36264 Dec 7 2013 /usr/bin/virt-rescue
-rwxr-x--- 1 root kvm 1322488 Dec 7 2013 /usr/bin/virt-resize
-rwxr-x--- 1 root kvm 1231256 Dec 7 2013 /usr/bin/virt-sparsify
-rwxr-x--- 1 root kvm 1289592 Dec 7 2013 /usr/bin/virt-sysprep
-rwxr-x--- 1 root kvm 8949 Dec 7 2013 /usr/bin/virt-tar
-rwxr-x--- 1 root kvm 804 Dec 7 2013 /usr/bin/virt-tar-in
-rwxr-x--- 1 root kvm 806 Dec 7 2013 /usr/bin/virt-tar-out
-rwxr-x--- 1 root kvm 55 Jul 12 2012 /usr/bin/virtualenv
-rwxr-x--- 1 root kvm 132400 May 28 2012 /usr/bin/virt-viewer
-rwxr-x--- 1 root kvm 23886 Dec 7 2013 /usr/bin/virt-win-reg
-rwxr-x--- 1 root kvm 3531 Jul 1 04:46 /usr/bin/virt-xml-validate
尽管现在我无法通过常规 SSH 连接访问任何这些命令,但我仍然可以通过virt-viewer
SSH 隧道远程执行(如上所述)来启动 VM。
那么,我怎样才能使只有特定的用户帐户才能访问虚拟机?
编辑:
以下是虚拟机启动时显示的内容/var/log/libvirt/qemu/cards2.log
,以防万一提供任何迹象:
LC_ALL=C PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin QEMU_AUDIO_DRV=none /usr/bin/kvm -S -M pc-1.1 -enable-kvm -m 2048 -smp 8,sockets=8,cores=1,threads=1 -name cards2 -uuid 70905b35-9df3-71c9-d5e9-f804a2826055 -no-user-config -nodefaults -chardev socket,id=charmonitor,path=/var/lib/libvirt/qemu/cards2.monitor,server,nowait -mon chardev=charmonitor,id=monitor,mode=control -rtc base=utc -no-shutdown -device piix3-usb-uhci,id=usb,总线=pci.0,地址=0x1.0x2 -drive file=/var/kvm/cards2.qcow,if=none,id=drive-ide0-0-0,format=raw -device ide-hd,总线=ide.0,unit=0,drive=drive-ide0-0-0,id=ide0-0-0,bootindex=1 -drive if=none,id=drive-ide0-1-0,readonly=on,format=raw -device ide-cd,总线=ide.1,unit=0,drive=drive-ide0-1-0,id=ide0-1-0 -netdev tap,fd=23,id=hostnet0 -device rtl8139,netdev=hostnet0,id=net0,mac=52:54:00:c6:14:68,总线=pci.0,地址=0x3 -chardev pty,id = charserial0 -device isa-serial,chardev = charserial0,id = serial0 -vnc 127.0.0.1:3 -vga cirrus -device virtio-balloon-pci,id = balloon0,bus = pci.0,addr = 0x4
编辑2:
另一方面,这似乎只是 的问题virt-viewer
,而不是 的问题virsh
。
例如,以下是在远程客户端上执行的一些命令:
$ virsh --connect qemu+ssh://[email protected]/system
error: failed to connect to the hypervisor
error: End of file while reading data: nc: unix connect failed: Permission denied: Input/output error
$ virsh --connect qemu+ssh://[email protected]/system
Welcome to virsh, the virtualization interactive terminal.
Type: 'help' for help with commands
'quit' to quit
答案1
KI 明白了。virt-viewer 不与 libvirtd 交互 - 它通过 ssh 连接到主机并设置隧道以允许访问基于 VNC 的虚拟机虚拟显示器(在我的情况下是 127.0.0.1:5903)。除非在 127.0.0.1 上对 VNC 进行防火墙保护,否则很难解决这个问题。否则普通用户通常可以自由地与本地主机建立 TCP 连接。我不知道如何只允许 root 用户,也许有办法。
也许 selinux 可以做到这一点?
因此最简单的事情就是设置 VNC 密码。您可以在 SSH 中执行诸如限制转发和 X11 转发之类的操作,但这可能不是 100% 安全的,并且可能还会给 root 带来问题。而且用户登录后仍然可以访问 127.0.0.1/vnc。
更新
根据 Mike(其他答案)和 Michael Hampton(评论)的说法,您可以使用 TLS 与 VNC 通信,而不是密码,因此如果密码对您来说不够好,您将获得相当不错的安全性。感谢他们两人,我完全不知道。
http://wiki.libvirt.org/page/VNCTLSSetup
和
答案2
作为Ryan 的回答上面说,“virt-viewer 不与 libvirtd 交互”。libvirtd 和 VNC(virt-viewer 连接的)完全单独的身份验证方法. VNC 可以使用
- 单一密码验证
- SASL 身份验证
- x509 证书
- 组合证书和前两个证书之一
单一密码
如果使用单个密码,它可以是存储在文件中的全局密码/etc/libvirt/qemu.conf
,也可以在 VM 配置中添加特定于 VM 的密码:
<graphics type='vnc' port='-1' autoport='yes' passwd='PASSWORD'/>
注意,这些密码必须以纯文本形式存储。
SASL 身份验证
这允许每个虚拟机使用多个用户名和密码组合。密码也经过哈希处理,而不是以纯文本形式存储的单个密码。有关说明看这里。
x509 证书
这实际上是我相信直接回答了这个问题(但我还没有测试过)。通过这种方式,您可以通过使用存储在服务器上的证书进行身份验证来限制哪些用户可以连接到 VNC 实例。要撤销特定用户或组的权限,只需将系统范围的客户端证书文件的权限设置为该用户不可读。您还可以生成每个用户的证书并撤销访问权限。
不幸的是,设置起来相对困难。首先需要在服务器上创建根 CA,生成 x509 客户端/服务器证书,配置服务器,配置客户端并测试设置, 进而限制访问。
答案3
您是否尝试过使用 polkit 来限制用户的访问权限?我也想这样做,所以最终得到了这样的结果:
- 将虚拟机命名为用户名*虚拟机名称
现在在 polkit 规则文件中编辑规则如下
function myFunction(username, virtualmachine) { var arr = virtualmachine.split("*"); if(arr[0]==username){ return true; } else{ return false; } } // Allow passwordless connection to qemu:///system polkit.addRule(function(action, subject) { if (action.id == "org.libvirt.unix.manage") { return polkit.Result.YES; } }); // Give full access to 'vm' polkit.addRule(function(action, subject) { if (action.id.indexOf("org.libvirt.api.domain.") == 0 ) { if (action.lookup("connect_driver") == 'QEMU' && myFunction(subject.user, action.lookup("domain_name"))) { polkit.log("vm=" + action.lookup("domain_name") + "action =>"+myFunction(subject.user, action.lookup("domain_name"))); polkit.log("subject=" + subject); polkit.log("ok"); return polkit.Result.YES; } else { return polkit.Result.NO; } } });
现在只有相应的用户才能看到虚拟机本身。
享受