J’administre des serveurs de virtualisation, nous avons un contrôle complet des HV. L’administration des VMs est à la charge des clients.

Ubuntu est le système d’exploitation le plus couramment utilisé sur nos machines virtuelles. Nous utilisons les cloud images pour leur déploiement. La configuration initiale est gérée par cloud-init qui s’occupe du réseau et des clés SSH. C’est aussi lui qui installe automatiquement le paquet qemu-guest-agent.

Un virt-inspector sur l’image que l’on utilise nous donne des informations sur ce paquet.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
[fifi@kwaks:~]# virt-inspector noble-server-cloudimg-amd64.prep.img | xmllint --xpath '//application[name="qemu-guest-agent"]' -
<application>
        <name>qemu-guest-agent</name>
        <epoch>1</epoch>
        <version>8.2.2+ds</version>
        <release>0ubuntu1</release>
        <arch>amd64</arch>
        <url>http://www.qemu.org/</url>
        <source_package>qemu</source_package>
        <summary>Guest-side qemu-system agent</summary>
        <description>QEMU is a fast processor emulator: currently the package supports Alpha, ARM,
CRIS, i386, LoongArch, M68k (ColdFire), MicroBlaze, MIPS, PowerPC, RISC-V,
S390x, SH4, SPARC, x86-64, Xtensa and other emulations. By using dynamic
translation it achieves reasonable speed while being easy to port on new host
CPUs.
.
This package provides a daemon (agent) to run inside qemu-system
guests (full system emulation).  It communicates with the host using
a virtio-serial channel org.qemu.guest_agent.0, and allows one to perform
some functions in the guest from the host, including:
 - querying and setting guest system time
 - performing guest filesystem sync operation
 - initiating guest shutdown or suspend to ram
 - accessing guest files
 - freezing/thawing guest filesystem operations
 - others.
.
Install this package on a system which is running as guest inside
qemu virtual machine.  It is not used on the host.</description>
      </application>

Ce paquet installera une unité systemd qui, dans un contexte de virtualisation, permettra à l’hyperviseur d’envoyer des commandes comme fsfreeze et fsthaw. Ces commandes permettent de réaliser des snapshots sains des machines virtuelles. Il peut également être utilisé pour lancer des opérations TRIM sur le stockage des machines virtuelles afin d’accélérer les migrations à chaud avec du stockage local.

Il arrive que nos clients perdent l’accès à leurs machines virtuelles, souvent pour les mêmes raisons :

  • Erreur de configuration du firewall
  • Erreur de configuration réseau
  • Suppression des clés SSH

Récupérer un shell

le firewall trop aggressif

1
2
[fifi@kwaks:~]# ssh vm1.internal.com
ssh: connect to host vm1.internal.com port 22: Connection refused

On se connecte sur l’hyperviseur et nous allons examiner les règles nftables en place

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
[fifi@kwaks:~]# qm guest exec 100 -- /bin/bash -c "nft list ruleset" | jq -r '.["out-data"]' | echo -e "$(cat)"
table inet filter {
	chain input {
		type filter hook input priority filter; policy drop;
	}

	chain forward {
		type filter hook forward priority filter; policy accept;
	}

	chain output {
		type filter hook output priority filter; policy accept;
	}
}

Côté machine virtuelle, on voit dans les journaux de l’unité qemu-guest-agent la trace de nos commandes

1
2
root@vm1:/home/ubuntu# journalctl -u qemu-guest-agent -f
Jan 28 23:20:46 vm1 qemu-ga[632]: info: guest-exec called: "/bin/bash -c nft list ruleset"

Dans ce cas, nous pouvons au choix ajouter une règle nftables pour autoriser notre trafic d’administration, ou simplement arrêter nftables.

1
2
3
4
5
[fifi@kwaks:~]# qm guest exec 100 -- /bin/bash -c "nft add rule inet filter input tcp dport 22 accept"
{
   "exitcode" : 0,
   "exited" : 1
}
1
2
3
4
5
[fifi@kwaks:~]# qm guest exec 100 -- /bin/bash -c "systemctl stop nftables"
{
   "exitcode" : 0,
   "exited" : 1
}

La VM est de nouveau accessible :

1
2
[fifi@kwaks:~]# ssh vm1.internal.com
Welcome to Ubuntu 24.04 LTS

Erreur de configuration réseau

Ici notre VM’s n’a plus d’IP :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
[fifi@kwaks:~]# qm guest cmd 100 network-get-interfaces
[
   {
      "hardware-address" : "dc:00:b0:bd:d9:0a",
      "ip-addresses" : [
         {
            "ip-address" : "fe80::be24:11ff:febd:d90a",
            "ip-address-type" : "ipv6",
            "prefix" : 64
         }
      ],
      "name" : "eth0",
      "statistics" : {
         "rx-bytes" : 1114133363,
         "rx-dropped" : 1,
         "rx-errs" : 0,
         "rx-packets" : 10006089,
         "tx-bytes" : 2728706943,
         "tx-dropped" : 0,
         "tx-errs" : 0,
         "tx-packets" : 3165011
      }
   }
]

Dans ce genre de cas, nous pouvons utiliser le qemu-agent pour modifier la configuration réseau, ou simplement utiliser les adresses link-local.

1
2
[fifi@kwaks:~]# ssh fe80::be24:11ff:febd:d90a%br0.2
Welcome to Ubuntu 24.04 LTS

Le pourcentage sur la commande ssh permet de spécifier au système Linux sur quelle interface il doit envoyer le trafic. En effet, les IPv6 link-local ne sont pas globalement uniques mais uniquement sur un lien. Ce fonctionnement est défini dans la RFC 4007.

Suppression des clés ssh

Dans le cas d’un client qui souhaite ajouter une clé, suite à un effacement de son authorized_keys ou à la perte de sa clé SSH.

1
2
3
4
5
[fifi@kwaks:~]# qm guest exec 100 -- /bin/bash -c "echo 'ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBXz5q/J6LhP/N8uW9T5I8ENyGxnFMq3k+aUX/T31xFR riri@coin' >> /root/.ssh/authorized_keys"
{
   "exitcode" : 0,
   "exited" : 1
}

La VM est de nouveau accessible :

1
2
fifi@kwaks:~# ssh vm1.internal.com
Welcome to Ubuntu 24.04 LTS

Ajout de restrictions aux capacités du qemu-guest-agent

Pour terminer, voici une astuce qui peut nous protéger contre l’exécution de code arbitraire avec le qemu-guest-agent

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
root@vm1:~# cat /etc/systemd/system/qemu-guest-agent.service
[Unit]
Description=QEMU Guest Agent
BindsTo=dev-virtio\x2dports-org.qemu.guest_agent.0.device
After=dev-virtio\x2dports-org.qemu.guest_agent.0.device

[Service]
ExecStart=/usr/sbin/qemu-ga -b guest-file-open,guest-file-close,guest-file-read,guest-file-write,guest-file-seek,guest-file-flush,guest-exec,guest-exec-status
Restart=always
RestartSec=0

Avec cette configuration, l’administrateur recevra une erreur s’il appelle un guest exec.

1
2
[fifi@kwaks:~]# qm guest exec 100 -- /bin/bash -c "echo 'ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBXz5q/J6LhP/N8uW9T5I8ENyGxnFMq3k+aUX/T31xFR riri@coin' >> /root/.ssh/authorized_keys"
Agent error: Command guest-exec has been disabled