Mounten eines vmdk Laufwerks im Linux Host – I – vmware-mount

Manchmal muss man sich auf einem Linux-Virtualisierungs-Host direkt - d.h. ohne Umweg über virtualisierte Gastsysteme - mit dem Inhalt von "vmdk"-Dateien auseinandersetzen. Ich stelle in diesem und nachfolgenden Beiträgen ein paar einfache Möglichkeiten vor, die ich selbst immer mal zum Mounten von Filesystemen, die sich innerhalb von vmdk-Dateien befinden, in den Verzeichnisbaum meiner Linux-Workstations benutze. Als Beispiele müssen dabei NTFS-Testpartitionen einer vmdk-Disk herhalten, die einer virtuellen Maschine mit Win7 zugeordnet wurden.

Szenarien für den direkten Zugriff unter Linux?

"vmdk"-Dateien dienen unter Linux primär dazu, VMware-Gastsysteme - aber z.B. auch Virtualbox- und qemu-Gastsysteme - mit einem virtuellen "Festplatten"-Unterbau auszustatten. Ich spreche nachfolgend daher auch von "vmdk-Disks". Ein allgemeiner Begriff, der das Prinzip von virtuellen Disks in Form von Dateien umschreibt, ist der eines Disk-Images.

Eine vmdk-Disk kann wie eine echte Platte auch Filesysteme (wie Ext4, NTFS oder BrtFS) aufnehmen. Unter KVM korrespondieren zu "vmdk" etwa "qcow2"-Dateien. Die Nutzung von Linux-Dateien als Container für Filesysteme bringt beim Virtualisieren einige Vorteile mit sich: u.a. kann man die virtuellen Platten relativ problemlos zwischen Hosts hin- und her bewegen. Natürlich lässt sich auch die Durchführung von Backups für "vmdk"-Dateien besonders einfach mit Linux-Bordmitteln durchführen.

Nun könnte man sagen, dass man auf die über "vmdk" bereitgestellten Filesysteme ja immer über die virtuelle VMware-Gast-Maschine selbst zugreifen kann. Das stimmt so nicht uneingeschränkt: Bisweilen muss man etwa die Pflege des/der auf der vmdk-Datei installierten Filesystems/e über Tools des Hosts betreiben. In anderen Fällen ist eine Bereinigung von eingefangenen Viren auf einem NTFS-Filesystem nötig, ohne dass das betroffene Gast-System gebootet werden soll. Ein anderes wichtiges Szenario ist die forensische Analyse von Inhalten der virtuellen Maschine - z.B. eines kompromittierten Windows-Gastsystems - durch Linux-Tools. Für letzteres reicht oftmals der lesende Zugriff. Weitere Anwendungsfälle sind logischerweise auch Pen-Tests (oder Hacker-Angriffe), bei denen der "Angreifer" von einem (teil-)eroberten Virtualisierungshost aus die Extraktion von Daten aus dort vorhandenen vmdk-Dateien virtueller Maschinen anstrebt.

Toolunterstützung unter Linux?

Die Spezifikation zu "vmdk" ist seit einiger Zeit offen; man erwartet daher, dass der Zugriff auf Inhalte von vmdk-Dateien (bzw. -"Laufwerken") unter Linux gut unterstützt wird. Unterstützung bedeutet für mich dabei primär die Erfüllung zweier Anforderungen:

  • Der Inhalt von "vmdk"-Disks sollte sich für den berechtigten User nach ein paar Schritten so darstellen, als gebe es dort (ggf. mehrere) Partitionen mit je einem unter Linux handhabbaren Filesystem (wie etwa NTFS von MS).
  • Unter diesen Filesystemen muss man dann eines auswählen und - wie von echten Festplatten gewohnt - mounten können.

Für den Anwender ist der Einsatz entsprechender Tools unter Linux unterschiedlich komfortabel: Einige Tools führen alle notwendigen Schritte inkl. des Mountens für den User bequem in einem Rutsch durch; besonders nachvollziehbar ist das Vorgehen hinter den Kulissen des/der jeweiligen Kommandos dann aber nicht. Dies gilt im Besonderen für die Behandlung sog. vmdk-Container.

FUSE, Loop Devices - Komplexität durch Snapshots, "sparse vmdk-Container" mit mehreren "Extension Files" und mit mehreren internen Partitionen/Filesystemen

Es gibt vier Hindernisse, die Entwicklern von vmdk-Tools überwinden müssen:

  • Sparse-vmdk: Spezielle Schwierigkeiten bei der Analyse der in vmdk-Disks verborgenen Filesysteme bereitet u.a. die Tatsache, dass eine einzelne vmdk-"Disk" oftmals in Form eines Containers daherkommt, der sich über mehrere vmdk-Dateien (jedes davon z.B. mit einer Größe von 4GB) erstreckt.
    Man spricht hier von "growable split and sparse file vmdk"; die "virtuelle" Platte wächst auf dem Host durch immer neu angelegte 2GB oder 4GB große Extents erst im Lauf der Zeit auf die Gesamtgröße an. Auch jedes einzelne neue Extension File selbst wächst dabei bedarfsgerecht an.
    Es gibt dann eine "führende", beschreibende vmdk-Datei - etwa mydisk.vmdk - und etliche weitere Extension-Dateien mit der Endung "-sNNN" - also z.B. "mydisk-sNNN.vmdk"; "NNN" steht dabei für eine dreistellige Nummer. Die führende Datei nennt man auch Deskriptor-Datei (s. hierzu den nächsten kommenden Artikel).
  • Mehrere Partitionen auf einer Disk: In beiden Fällen (sparse und flat) kommt hinzu, dass eine vmdk-Disk mehrere Partitionen beinhalten kann.
  • Loop-Devices und Offsets: Hat man die Partitionen in einer vmdk-Disk erstmal erkannt, muss man entsprechende Linux-"Devices" für den Zugriff als Blockdevice definieren. Dabei muss man sich natürlich auch um den sog. "Offset" einer spezifischen Partition relativ zum Anfang der beherbergenden Disk-Datei(en) kümmern.
  • Snapshots: Weiter verkompliziert wird die Handhabung für den Nutzer noch dadurch, dass man unter VMware Snapshots einer virtuellen Maschine anlegen kann. Solche Snapshots äußern sich in weiteren Zusätzen der vmdk-Dateien; z.B. mydisk-000001-s001.vmdk. Man muss also unter der Menge vorhandene vmdk-Disk-Dateien geeignete Snapshot-Dateien auswählen (z.B. mydisk-000001.vmdk). Dabei können die führende Snapshot-Datei und die ehemals führende Datei (die auch der Snapshot mitnutzt) u.U. in verschiedenen Verzeichnissen liegen (s.u.). Noch weitere Namens-Zusätze unterscheiden übrigens ggf. Clones virtueller Maschinen.

Ergänzende Hinweise (im nächsten Artikel liefere ich dazu auch Links):

Zu einer "growable split and sparse Disk" (Container) gibt es auch die Variante, dass zwar über mehrere Files hinweg gesplittet wird, aber der gesamte Plattenplatz von vornherein allokiert wird. Die erste Extent-Datei nennt man auch "Base-File" des vmdk-Disk-Images.
Das Gegenteil zu einer Sparse Disk, die über viele Extension Files verteilt ist, ist das sog. "monolithic file vmdk"; dabei wird von Anfang an nur genau eine vmdk-Datei für die angestrebte virtuellen Platte angelegt. Das bringt neben strukturellen Unterschieden u.a. geringfügige Performance-Vorteile. Aber auch hier gibt es wieder zwei Möglichkeiten: Die Datei kann von vornherein den gesamten Platz der virtuellen Disk allokieren, oder sie kann langsam wachsen. In letzterem Fall spricht man auch von einer "Monolithic Sparse Disk".

Bei aktuellen Linux-Werkzeugen zu vmdk führt der Weg zur Lösung der oben genannten Probleme intern regelmäßig über die Nutzung von FUSE und Loop-Devices. Letztere werden manchmal auch Loopback-Devices genannt; sie sind aber nicht mit dem gleichnamigen Netzwerk-Device "lo" zu verwechseln. Siehe zu Loop-Devices etwa
Wikipedia-Artikel zu Loop-Devices;
OSDevv.org zu Loopback-Device;
http://www.tldp.org/HOWTO/archived/Loopback-Root-FS/Loopback-Root-FS-2.html.

In "vmdk"-Containern mit einer Vielzahl von sparse vmdk-Dateien, aber auch in wachsenden monolithischen vmdk-Dateien ist die Adressierung von Sektoren und Daten-Blöcke unterschiedlicher Partitionen verständlicherweise kompliziert. Auf solche vmdk-Disk-Images kann man unter Linux deshalb weder fdisk noch kpartx direkt loslassen. Leider. Aber kleine Umwege mit linux-eigenen Zusatztools führen auch dann zum Ziel - selbst wenn man nicht das nachfolgend besprochene Tool von VMware einsetzen will.

Zugriff mit dem VMware-Tool "vmware-mount"

Hat man die VMware-Workstation für Linux lizenziert, finden sich nach der Installation unter "/usr/bin/" eine Reihe von Kommando-Tools vor, die mit "vmware-" beginnen.

mytux:~ # vmware
vmware                            vmware-installer                  vmware-ping
vmware-authd                      vmware-license-check.sh           vmware-tray
vmware-authdlauncher              vmware-license-enter.sh           vmware-usbarbitrator
vmware-collect-host-support-info  vmware-modconfig                  vmware-vdiskmanager
vmware-fuseUI                     vmware-mount                      vmware-vim-cmd
vmware-gksu                       vmware-netcfg                     vmware-vprobe
vmware-hostd   

Die meisten dieser Kommandos haben eine Option "help", die Informationen liefert. "man"-Seiten gibt es leider nicht.

Für uns relevant ist im aktuellen Kontext "vmware-mount". Dieses nützliche CLI-Werkzeug ist auch Teil des VMware VDDK (s. folgenden Link vddk/; das VDDK wird unabhängig von der VMware WS angeboten und enthält auch Tools für den Remote-Zugriff auf Virtual Disks eines VMware ESX-Servers).

"vmware-mount help" zeigt die nötigsten Infos und Optionen zum Kommando an:

mytux:~ # vmware-mount help
VMware DiskMount Utility version 6.5.0, build-7528167

Usage: vmware-mount diskPath [partition num] mountPoint
       vmware-mount [option] [opt args]

There are two modes for mounting disks.  If no option is
specified, we mount individual partitions from virtual disks
independently.  The filesystem on the partition will be
accessible at the mount point specified.

The -f option mounts a flat representation of a disk on a
user-specified mount point.  The user must explicitly unmount
the disk when finished.  A disk may not be in both modes at once.

Options: -p <diskID>      list all partitions on a disk
         -l <diskID>      list all mounted partitions on a disk
         -L               list all mounted disks
         -d <mountPoint>  cleanly unmount this partition
                          (closes disk if it is the last partition)
         -f <diskPath> <mountPoint> mount a flat representation of the disk
                          at "mountPoint/flat."
         -k <diskID>      unmount all partitions and close disk
         -K <diskID>      force unmount all partitions and close disk
         -x               unmount all partitions and close all disks
         -X               force unmount all partitions and close all disks
         -r               mount the disk or partition read-only
         -o               comma-separated list of options to be passed
                          to the 'mount' when mounting a partition

 
Wissen muss man demnach noch, was eine sog. "" ist; diese Info erhält man z.B. aus einem von unter VMware bereitgestellten PDF (VMwareDiskMount.pdf :

"In the following list of options, is an identifier of the form username@hostname:/path/to/disk for remote disks, or just the /path/to/disk for local disks."

Man kann diskIDs für vmdk-Files auf ESX-Servern einsetzen. Das interessiert uns hier nicht weiter.
Auf lokalen Linux-Systemen entspricht eine diskID gerade einem Pfad (Path) zu einer führenden vmdk-Datei.

Identifikation von Partitionen mit vmware-mount

Probieren wir "vmware-mount" einfach mal lokal aus; auf meinem Testsystem liegt etwa unter "/vmw/Win7" eine Windows 7-Installation für VMware Workstation, die u.a. eine kleine vmdk-Disk namens "Win7_x64_ssd_ex.vmdk" mit einer NTFS-Partition für Testzwecke beherbergt. Um es einfach zu machen, besteht dieses Disk-Image nur aus genau einem vmdk-File (monolithic sparse disk). Es sind keine Extension Files vorgesehen; der Speicherplatz ist aber nicht vorallokiert. "vmware-mount" hat damit erwartungsgemäß keine Probleme:

mytux:/vmw # vmware-mount -p /vmw/Win7/Win7_x64_ssd_ex.vmdk/ 
Nr      Start       Size Type Id Sytem                   
-- ---------- ---------- ---- -- ------------------------
 1       2048   12576768 BIOS  7 HPFS/NTFS

Es wird korrekterweise genau eine Partition mit NTFS erkannt (6GB; 512Byte Sektorgröße). Wären mehrere File-Systeme enthalten, würden die entsprechend aufgelistet werden (s.u.).

fdisk erkennt weder die Partitionen einer über genau ein File repräsentierten monolithischen vmdk-Disk noch die eines echten vmdk-Containers

"fdisk -l" erkennt im Gegensatz zu vmware-mount nur die Blockstruktur des Files als Ganzes, nicht aber dessen interne Filesystem-Struktur:

mytux:~ # fdisk -l /vmw/Win7/Win7_x64_ssd_ex.vmdk 
Disk /vmw/Win7/Win7_x64_ssd_ex.vmdk: 34.9 MiB, 36569088 bytes, 71424 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes

Das gilt, obwohl für meine spezielle Test-Disk nur genau ein (wachsendes) vmdk-File vorliegt:

mytux:~ # la /vmw/Win7/ | grep ex
-rw-rw-rw-  1 myself  users   36569088 Mar 23 18:03 Win7_x64_ssd_ex.vmdk

Nun umfasst meine virtuelle Maschine aber auch noch eine weitere Test-Disk, deren Container tatsächlich zwei unterschiedliche Files beinhaltet:

mytux:/vmw/Win7 # la | grep ssdx
-rw-------  1 myself  users 2344157184 Mar 27 19:38 Win7_x64_ssdx-s001.vmdk
-rw-------  1 myself  users     131072 Mar 27 19:37 Win7_x64_ssdx-s002.vmdk
-rw-------  1 myself  users        511 Mar 27 19:34 Win7_x64_ssdx.vmdk

Leider liefert fdisk auch für diesen Fall kein besseres Ergebnis:

mytux:/vmw/Win7 # fdisk -l Win7_x64_ssdx.vmdk 
fdisk: cannot open Win7_x64_ssdx.vmdk: Inappropriate ioctl for device
mytux:/vmw/Win7 # fdisk -l Win7_x64_ssdx-s001.vmdk 
Disk Win7_x64_ssdx-s001.vmdk: 2.2 GiB, 2344157184 bytes, 4578432 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes

Dagegen ermittelt vmware-mount auch für diesen komplexen vmdk-Container die richtige Filesystem-Information:

mytux:/vmw/Win7 # vmware-mount -p Win7_x64_ssdx.vmdk 
Nr      Start       Size Type Id Sytem                   
-- ---------- ---------- ---- -- ------------------------
 1       2048    5310464 BIOS  7 HPFS/NTFS
 2    5312512    3072000 BIOS  7 HPFS/NTFS

Aus diesem Grund vermutet man, dass vmware-mount intern zunächst einmal das hoch-spezifische vmdk-(Container)-Format in ein für Linux handhabbares "flat-file"-Format aufdröselt. Zur linux-konformen Handhabung der vmdk-Spezifikation wird dabei intern auf zeitgemäße FUSE-Mechanismen zurückgegriffen. Sagt zumindest eine Recherche zu unterschiedlichen FUSE-Formaten im Internet ...

Mounten

Die allgemeine Form des "vmware-mount"-Kommandos ist:

myself@mytux:~> su -c 'vmware-mount /vmw/Win7/Win7_x64_ssd_ex.vmdk /mnt/vmdk/'

Zur Durchführung des Mounts braucht man root-Rechte. Im obigen Fall muss man also das root-Passwort kennen. Alternativ wechselt man gleich in eine root-Shell.

Wir sehen dann in meinem Testfall etwa folgende Inhalte:

myself@mytux:~> la /mnt/vmdk/        
insgesamt 9
drwxrwxrwx 1 root root 4096 22. Mär 10:57 .
drwxr-xr-x 5 root root 4096 20. Mär 18:36 ..
drwxrwxrwx 1 root root    0 22. Mär 10:34 $RECYCLE.BIN
drwxrwxrwx 1 root root    0 21. Mär 08:41 System Volume Information
-rwxrwxrwx 1 root root   11 22. Mär 10:57 ufo1.txt
drwxrwxrwx 1 root root    0 22. Mär 10:36 ufodir
-rwxrwxrwx 1 root root    6 20. Mär 18:35 ufo.txt

Beispiele mit mehreren Partitionen innerhalb einer vmdk-Disk und mit mehreren vmdk-Files eines echten vmdk-Containers diskutiere ich weiter unten. Dabei läuft alles aber weitgehend analog zum eben erläuterten Beispiel ab.

Zwischenschritte von vmware-mount

vmware-mount nimmt uns freundlicherweise gleich mehrere Aktionen ab:

  • Involvieren von "FUSE"-basierten Methoden zur Bereitstellung der "vmdk"-Disk als zusammenhängendes "flat"-File. Dieses (scheinbar) zusammenhängende File wird in einem temporären Verzeichnis unter "/run/vmware/fuse" bereitgestellt
    /run/vmware/fuse/ID-Nummer/flat
    Das Verzeichnis erhält eine ID-Nr, die die Disk identifiziert. Die ID wird als Hash generiert.
  • Anlegen eines Loop-Devices (hier: /dev/loop0) mit richtiger Offset-Positionierung (hier: 1048576).
  • Mounten des Loop-Devices (hier /dev/loop0) auf dem Ziel-Mount-Punkt (hier: /mnt/vmdk); das geschieht wiederum mit Hilfe des Fuse-Plugins für ntfs-ng3

Mehr Information?

Ein paar weiterführende Informationen findet man für unser Testbeispiel durch folgende Kommandos:

mytux:~ # mount
....
/dev/fuse on /run/vmware/fuse/13958668715283886016 type fuse (rw,nosuid,nodev,relatime,user_id=0,group_id=0,allow_other)
/dev/loop0 on /mnt/vmdk type fuseblk (ro,nosuid,nodev,relatime,user_id=0,group_id=0,allow_other,blksize=4096)
...
mytux:~ # losetup -l
NAME       SIZELIMIT  OFFSET AUTOCLEAR RO BACK-FILE                                  DIO
/dev/loop0         0 1048576         0  0 /run/vmware/fuse/13958668715283886016/flat   0
....
mytux:~ # cat /run/vmware/fuse/13958668715283886016.info 
.encoding = "UTF-8"
backingPath = "/vmw_win7/Win7_x64_ssd_ex.vmdk"
diskName = "/vmw_win7/Win7_x64_ssd_ex.vmdk"
mountPath = "/run/vmware/fuse/13958668715283886016"
refCount = "1"
privateFlatFile = "TRUE"
isRemote = "FALSE"
openFlags = "0"
readOnly = "FALSE"
mountPath0 = "/mnt/vmdk"
loopPath0 = "/dev/loop0"

 
Auf die Bestimmung des Offsets kommen wir weiter unten zurück.

Sicheres Unmounten

Hat man mittes vmware-mount einen schreibenden Zugriff realisiert, so ist schon allein wegen des umfangreichen Cachings auf einem Linux-Host ein sicheres Unmounten erforderlich: Dabei erfolgt vorab eine Synchronisation (Sync) von geänderten Daten vom Cache in das/die Container-File/s hinein. Das Unmounten erfordert die Angabe der Option "-d":

mytux:~ # vmware-mount -d /mnt/vmdk/ 

Anzugeben ist dabei lediglich der Mount-Point. Manchmal dauert der Unmount-Prozess wg. der Syncs zur Festplatte einen Tick.

Mounten als Flat File?

Die Option "-f" (s. oben) deutet an, dass "vmware-mount" dem Linux-User auch die Möglichkeit gibt, einen vmdk-Container einfach nur in ein zusammenhängendes "flat"-File umzuwandeln, das man dann selbst einer weiteren Behandlung zuführen kann:

mytux:~ # vmware-mount "-f" /vmw/Win7/Win7_x64_ssd_ex.vmdk /mnt
mytux:~ # la /mnt
total 6291456
-rw-rw-rw- 1 myself users 6442450944 Mar 23 18:03 flat
mytux:~ # fdisk -l /mnt/flat
Disk /mnt/flat: 6 GiB, 6442450944 bytes, 12582912 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x77138461

Device     Boot Start      End  Sectors Size Id Type
/mnt/flat1       2048 12578815 12576768   6G  7 HPFS/NTFS/exFAT

Wie man die in einem solchen "Flat"-File enthaltenen Filesysteme konkret über Loop-Devices nutzen kann, besprechen wir im übernächsten Artikel, in dem wir ein natives Linux-Tool für den Zugriff auf einen vmdk-Disk-Container benutzen werden.

Vorsicht mit Modifikationen und Rechten bei NTFS-Partitionen einer vmdk-Disk

Da wir gerade bei Rechten waren, ist eine Warnung bzgl. NTFS-Systemen in vmdk-Containern angebracht:

Die User und Rechte im virtualisierten Gastsystem (hier Win7) sind im Linux-Host nicht ohne weiteres bekannt. Bei der Anwendung von ntfs-3g müssen daher Standard-"Umsetzungen" von Linux-UIDs/GIDs auf Windows SIDs verwendet werden sowie Standard-ACL-Abbildungen erfolgen. Im Fall von "vmware-mount" bedeuten die intern gewählten Standard-Umsetzungen:

Warnung 1: Nach dem oben besprochenen Einsatz von vmware-mount erhält jeder Linux-User auf dem Linux-System Lese- und Schreibrechte - sowohl am Flat-File wie auch bzgl. des gemounteten Filesystems.

Das ist leider unabhängig von den (ursprünglichen) Linux-Rechten des Mount-Punktes (hier: /mnt/vmdk). Man probiere das selbst aus und lasse sich die Rechte vor und nach dem Mounten anzeigen. Das hat denn ggf. auch Konsequenzen im virtualisierten Windows-System:

Warnung 2: Evtl. manuell nach dem vmware-mount angelegte Dateien/Ordner auf dem NTFS-System gehören später unter dem virtualisierten Windows zwar den dortigen Administratoren - aber auch dort hat jeder Windows-User trotzdem Vollzugriff.

Diese Rechte-Situation zu ändern ist meines Wissens mit VMware-Tools alleine nicht möglich. Siehe zu einer feingranulareren, Nutzer-unterstüzten Abbildung aber:
Windows Partitionen einbinden mit NTFS-3G.

Read-Only-Mount

Im Zweifel ist es besser, auf Nummer sicher zu gehen und die Filesystem der virtuellen Disk-Images nur read-only zu mounten. Also (als root):

mytux:~ # vmware-mount -r /vmw/Win7/Win7_x64_ssd_ex.vmdk /mnt/vmdk/

Obwohl die Rechte danach immer noch identisch zum vorherigen rw-Mount angezeigt werden, sind faktisch keine Schreibzugriffe mehr möglich. das verhindert aber immer noch nicht den Diebstahl von Daten durch unbefugte Nutzer. In einem kommenden Artikel komme ich beim Zugriff auf "flat"-Files über Loop-Devices auf dieses Thema zurück.

2-te Partition einer Snapshot-vmdk-Disk mounten

Abschließend habe ich zu unserer Test-Disk mal drei Snapshots angelegt und sie zudem danach in zwei NTFS-Partitionen unterteilt. Dann ergibt sich folgendes komplexere Bild:

Die ursprüngliche vmdk-Disk lag unter "/vmw/Win7/", die virtuelle Maschine mit ihrer Haupdisk aber unter "/vmw/Win7Prod/". Die Snapshots der ursprünglichen Disk
/vmw/Win7/Win7_x64_ssd_ex.vmdk
wurden automatisch aber unter "/vmw/Win7Prod/" abgelegt - der letzte als
/vmw/Win7Prod/Win7_x64_ssd_ex-000003.vmdk.

Der Unterschied mach sich sich schon beim Betrachten der Partitionen bemerkbar:

mytux:/vmw/Win7Prod # vmware-mount -p ../Win7/Win7_x64_ssd_ex.vmdk 
Nr      Start       Size Type Id Sytem                   
-- ---------- ---------- ---- -- ------------------------
 1       2048   12576768 BIOS  7 HPFS/NTFS

mytux:/vmw/Win7Prod # vmware-mount -p Win7_x64_ssd_ex-000003.vmdk 
Nr      Start       Size Type Id Sytem                   
-- ---------- ---------- ---- -- ------------------------
 1       2048    6295552 BIOS  7 HPFS/NTFS
 2    6297600    6279168 BIOS  7 HPFS/NTFS

Mounten der zweiten Partition im dritten Snapshot zeigt:

mytux:/vmw/Win7Prod # la | grep _ex
-rw------- 1 myself  users   42860544 Mar 27 11:19 Win7_x64_ssd_ex-000001.vmdk
-rw------- 1 myself  users    1572864 Mar 27 11:51 Win7_x64_ssd_ex-000002.vmdk
-rw------- 1 myself  users    1572864 Mar 27 11:56 Win7_x64_ssd_ex-000003.vmdk

mytux:/vmw/Win7Prod # vmware-mount  Win7_x64_ssd_ex-000003.vmdk 2 /mnt/vmdk

mytux:/vmw/Win7Prod # la /mnt/vmdk
total 8
drwxrwxrwx  1 root root 4096 Mar 27 11:15 .
drwxr-xr-x 38 root root 4096 Mar 20 11:14 ..
drwxrwxrwx  1 root root    0 Mar 27 11:08 System Volume Information
drwxrwxrwx  1 root root    0 Mar 27 11:50 tull
mytux:/vmw/Win7Prod7 # la /run/vmware/fuse
total 8
drwxr-xr-x 3 root   root    80 Mar 27 12:08 .
drwxr-xr-x 5 root   root   180 Mar 27 11:56 ..
dr-xr-xr-x 2 myself users 4096 Mar 27 12:08 11844985246325345490
-rw-r--r-- 1 root   root   344 Mar 27 12:08 11844985246325345490.info
mytux:/vmw/Win7Prod # losetup
NAME       SIZELIMIT     OFFSET AUTOCLEAR RO BACK-FILE                                  DIO
/dev/loop0         0 3224371200         0  0 /run/vmware/fuse/11844985246325345490/flat   0

 
Der Offset errechnet sich hier übrigens aus einem Standard vmdk-Offset von 2048 * 512 Byte plus der Größe der ersten Partition

2048 * 512 + 6295552 * 512 = 6297600 * 512 = 3224371200

Ganz analog läuft unser Beispiel mit dem echten Container "Win7_x64_ssdx.vmdk", der zwei Extension-Files und zwei Filesysteme beinhaltet:

mytux:/vmw/Win7 # vmware-mount -p Win7_x64_ssdx.vmdk 
Nr      Start       Size Type Id Sytem                   
-- ---------- ---------- ---- -- ------------------------
 1       2048    5310464 BIOS  7 HPFS/NTFS
 2    5312512    3072000 BIOS  7 HPFS/NTFS
mytux:/vmw/Win7 # vmware-mount  Win7_x64_ssdx.vmdk /mnt2
mytux:/vmw/Win77 # la /mnt2
total 8
drwxrwxrwx  1 root root    0 Mar 27 19:35 $RECYCLE.BIN
drwxrwxrwx  1 root root 4096 Mar 27 19:35 .
drwxr-xr-x 38 root root 4096 Mar 20 11:14 ..
drwxrwxrwx  1 root root    0 Mar 27 19:34 System Volume Information
mytux:/vmw/Win7 # vmware-mount -d /mnt2
umount: /var/run/vmware/fuse/15887816320560912647.links/19: target is busy
        (In some cases useful info about processes that
         use the device is found by lsof(8) or fuser(1).)
mytux:/vmw/Win7 # vmware-mount -d /mnt2
Failed to unmount partition '/mnt2': Nothing mounted at the given mountpoint
mytux:/vmw/Win7 # vmware-mount  Win7_x64_ssdx.vmdk 2 /mnt2
mytux:/vmw/Win7 # la /mnt2
total 196124
drwxrwxrwx  1 root root      4096 Mar 27 19:38 .
drwxr-xr-x 38 root root      4096 Mar 20 11:14 ..
drwxrwxrwx  1 root root         0 Mar 27 19:37 System Volume Information
-rwxrwxrwx  2 root root 200822784 Nov  4  2013 mysql-installer-community-5.6.14.0.msi
mytux:/vmw/Win7 # vmware-mount -d /mnt2

Hier sieht man übrigens, dass man bei einer manchmal auftauchende Fehlermeldung "target is busy" im Unmount-Process, die u.a. auch durch Desktop-Suchmaschinen bedingt sein kann, nicht gleich in Panik verfallen muss.

Man beachte beim zweiten Mount-Versuch die 2 in "vmware-mount Win7_x64_ssdx.vmdk 2 /mnt2"; diese 2 spezifiziert das zweite Filesystem. Auch in diesem Fall wird natürlich ein "Flat-File" angelegt:

mytux:/vmw/Win7 # vmware-mount  Win7_x64_ssdx.vmdk 2 /mnt2
mytux:/vmw/Win7 # la /run/vmware/fuse 
total 8
drwxr-xr-x 3 root root    80 Mar 27 20:50 .
drwxr-xr-x 5 root root   180 Mar 27 19:38 ..
dr-xr-xr-x 2 rmo  users 4096 Mar 27 20:50 15887816320560912647
-rw-r--r-- 1 root root   299 Mar 27 20:50 15887816320560912647.info
mytux:/vmw/Win7 # la /run/vmware/fuse/15887816320560912647 
total 4194304
-rw------- 1 myself  users 4294967296 Mar 27 19:34 flat
mytux:/vmw/Win7 # 

Fazit

vmware-mount bietet eine einfache Möglichkeit, Partitionen, die in vmdk-Containern enthalten sind, unter Linux zu mounten. Container kann man aber auch einfach nur als ein Flat-File mounten und die Behandlung der enthaltenen Partitionen über Loop-Devices selbst übernehmen. Die automatisch vergebenen Rechte (voller Lese- und Schreibzugriff durch jedermann) erfordern aber Vorsicht.

Im nächsten Beitrag

Mounten eines vmdk-Laufwerks im Linux Host – II – Einschub, Spezifikation, Begriffe

liefere ich zunächst einige Hinweise zur vmdk-Spezifikation nach und versuche dann, durch Rückgriff auf ein Tool aus dem qemu-Bereich, das erforderliche Flat-File zu einem vmdk-Container ohne vmware-mount bereitzustellen.

Links

https://www.novell.com/communities/coolsolutions/retrieve-modify-take-backup-files-inside-vmdk-offline-mode/

Reaktivierung des Backups eines Windows-Gastes unter VMware Workstation

Es gibt eine ganze Reihe von Situationen, in denen man auf ein (komplettes) Backup einer unter VMware installierten Gastmaschine zurückgreifen möchte:

  • Updates/Upgrades: Oft genug verursachen ureigenste Updates des Betriebssystem-Herstellers oder aber bestimmter Programm-Suites erhebliche Probleme. Das gilt für Windows-Systeme in besonderem Maße. OK - es gibt die Wiederherstellungspunkte unter Windows selbst. Um die nutzen zu können, muss das System aber noch lauffähig sein.
  • Fehler von Benutzern mit Admin-Rechten: Wiederherstellungspunkte schützen nicht vor bestimmten gravierenden Fehlern von Anwendern mit hohen Berechtigungen auf dem VMware-Host wie auf der VMware-Gast-Maschine - echte Backups sind grundsätzlich unerlässlich.
  • Änderungen an der HW-Ausstattung der virtuellen Maschine: Für Performance-Tests möchte man ggf. mit der HW-Ausstattung der virtuellen Maschine experimentieren. HW-Änderungen sind oft auch im Zusammenhang mit VMware-Upgrades angebracht.
  • Pentests: Eine ganz eigene Klasse von Systemmanipulationen entsteht zudem im Zuge von Tests in einem Pentest-Labor: je nachdem, mit welchen Angriffsvektoren man sich da auseinandersetzt, kann das Ziel-System, also das VMware-Gastsystem, so in Mitleidenschaft gezogen werden, dass es danach schlicht nicht mehr funktionstüchtig ist.

Für all diese Situationen muss man vorausschauend planen. VMware bietet natürlich einen Snapshot-Mechanismus zur Fixierung des Zustands einer virtuellen Maschine an. Das schützt einen aber nicht vor Fehlern oder Ausfällen auf dem Virtualisierungshost selbst. Zudem muss man die Snapshot-Strategie konsequent anwenden; das erfordert in manchen Situationen einen erheblichen zusätzlichen Speicherplatz auf den Festplatten des Virtualisierungshosts und führt ggf. zudem systematisch zu Performance-Einbußen.

Meine Strategie ist grundsätzlich die, von wichtigen produktiven VMware-Installationen unter Linux zusätzlich zu Snapshots regelmäßig Kopien der gesamten Maschine anzufertigen und auf Partitionen externer Backup-Systemen zu verschieben. Mit Kopien meine ich echte Linux-Kopien der einer virtuellen Maschine im Linux-System zugeordneten Definitions- und virtuellen Hard-Disk-Dateien (cp -dpRv bzgl. der zu einer Maschine gehörigen .vcmx-, .vmxf-, .vmsd, .nvram-, .vmdk-Dateien). Von der vmx-Datei lege ich vorsorglich eine zweite Kopie (unter anderem Namen) an. Warum wird aus dem folgenden Text erkenntlich werden.

Nun ist ja bekannt, dass MS mit Windows vor allem Geld verdienen will. Intern überwacht das System daher Zustände und Veränderungen der (z.T. virtuellen) HW sowie anderer Parameter, die auf eine Veränderung der Systemumgebung hindeuten. Glaubt Windows bzw. Microsoft, dass solche Veränderungen einer Lizenzverletzung entsprechen, muss eine neue Aktivierung des Betriebssystems vorgenommen werden. Je nach Lizenzeinschränkungen kann das natürlich schiefgehen - im Besonderen, wenn Reaktivierungen in relativ kurzen Zeitabständen vorgenommen werden oder z.B. eine OEM-Lizenz plötzlich einer aus MS-Sicht neuen PC-Plattform zugeordnet wird.

Das Dumme ist, dass gerade Änderungen der HW-Ausstattung einer virtuellen Maschine (s. den obigen Punkt 3), die völlig legal erfolgen, aus Microsoft-Sicht böse sein können. Bestimmte Änderungen der (virtuellen) HW-Ausstattung werden von MS einfach mal so interpretiert, als habe man die zugrunde liegende PC-Plattform gewechselt. So ist ziemlich leicht, durch die Kombination zweier Änderungen einer virtuellen Maschine (Memory-Erweiterung + neue Netzwerkkarte oder CPU-Erweiterung + zusätzl. Netzwerkkarte) eine Neuaktivierung auszulösen. Das ist an sich schon ärgerlich. Ganz ekelhaft wird das Auslösen einer Windows-Reaktivierung aber beim Rückgriff auf ein Backup und dessen Inbetriebnahme. Im Besonderen dann, wenn das Problem der laufenden Windows-Maschine, das den Rückgriff auf ein Backup verursacht, durch ein Windows-Update selbst hervorgerufen wurde.

Falsche Reaktion auf Rückfragen von VMware

Ein Fehler, den man unter VMware schnell macht und der anschließend nicht mehr so einfach zu korrigieren ist, ist folgender:

Man hat eine Kopie aller Dateien einer virtuellen Windows-Maschine unter VMware erstellt und natürlich nicht weiter benutzt. Das laufende Windows-System ist aufgrund irgendwelcher Aktionen zerschossen. Man löscht die zugehörigen Dateien (ggf. auch aus Platzmangel). Man kopiert die Dateien des letzten Backups vom Backup-System zurück in eine Zielpartition des Linux-Systems. Man öffnet die virtuelle Maschine und startet sie. Dann kommt eine typische Frage von VMware mit etwa folgendem verkürzten Inhalt:

The virtual machine may have been moved or copied. ... In order to configure certain management and networking features VMware needs to know which. Did you move this virtual machine, or did you copy it? If you don't know, answer "I copied it".
Haben sie die Maschine kopiert oder verschoben? Im Zweifel soll man dann den Auswahlpunkt "Kopiert" anklicken.

Die Wahl "Kopiert" erscheint dann logisch, da das Backup ursprünglich ja mal als Kopie entstanden ist. Leider wird man dann nach dem Starten der Backup-Installation feststellen, dass eine Neuaktivierung von Windows erforderlich ist. Die ggf. fehlschlägt; man kann dann trotz Backups nicht mehr produktiv mit dem Gastsystem arbeiten.

In diese Falle bin ich selbst schon getappt. Zu beachten ist: Man hat in dem von mir beschriebenen Prozess nichts Illegales getan. Die Windows-Lizenz sieht das Anlegen von Backups vor. Man benutzt in dem beschriebenen Prozess die angelegte Backup-Kopie auch nicht parallel zum Original. (Das würde aus einem bestimmten Grund - s.u. - auch Zusatzmaßnahmen erfordern).

Ursache und Problemlösung

Im lokalen LAN müssen MAC-Adressen eindeutig sein, damit die Zuordnung von IP-Adresse zu MACs eindeutig wird und das ARP-Protokoll korrekt funktionieren kann. Wird eine Kopie einer virtuellen Maschine angelegt, so kann es natürlich sinnvoll sein, die MAC der virtuellen Maschine zu ändern, um bei einem Start des Originals und der Kopie zwei identische MAC-Adressen im Netz zu vermeiden. Antwortet man auf die obige Frage mit "Copied oder Kopiert", so passiert genau das: VMware ändert die Mac-Adressen der NICs der "kopierten" virtuellen Maschine. Aus Sicht von Windows hat das System dann eine oder gar mehrere neue Netzwerkkarten bekommen - im Spiel um eine Windows-Neuaktivierung entspricht dies einem sehr hoch bewerteten Kriterium.

VMWare vergibt zudem pro virtueller Maschine eine eindeutige UUID, die an die BIOS-Kennung (SMBIOS Descriptor) gebunden wird und somit auch von Windows erkennbar ist. Hierauf reagiert ein Konzern, dessen Erfolg auf Geldverdienen mit Lizenzen aufgebaut ist, natürlich allergisch. Beantwortet man also die obige (berechtigte) Frage von VMware mit "Kopiert", so wird die UUID von VMware geändert. Windows erkennt das und löst nach meiner Erfahrung in jedem Fall eine Reaktivierung aus, um eine Lizenzverletzung zu prüfen.

Leider begibt man sich durch beide Effekte als User schnell in Teufels (MS Lizenz-) Küche, wenn man auf die obige Frage von VMware falsch antwortet - selbst wenn man nicht Illegales tut und nur Backups reaktivieren will. Dies gilt im Besonderen dann, wenn man lediglich eine günstige OEM-Lizenz für sein Windows erworben hat, die ja relativ strikt eine bestimmte HW gebunden wird.

Will man solche Probleme vermeiden, gilt also:

Die richtige Antwort bei Reaktivierung eines Backups und Ersetzung der originalen virtuellen Maschine ist: "Moved" oder "Bewegt" - unabhängig davon, dass der Backup-Erstellung ein echter Kopierprozess zugrunde lag.

Selbst wenn diese Antwort mal falsch sein sollte: Alle UUID-Probleme, ja selbst das Netzwerkkarten-Problem, lassen sich bei Bedarf auch anders lösen. Eine bei MS vergeigte Lizenz durch Backup-Reaktivierung erfordert dagegen einen wesentlich höheren Aufwand an Zeit und Nerven.

Eine weitere Regel ist: Werft auch bei einer zerschossenen Windows-Maschine die zugehörige vmx-Definitionsdatei nicht sofort ins digitale Nirwana. Mit ihrer Hilfe kann man ggf. noch etwas retten, wenn die Aktivierung der Backup-Kopie bei Microsoft fehlschlagen sollte.

Manuelle UUID-Einstellungen und manuelle Vorgaben für Kopien

Der Vollständigkeit halber möchte ich darauf hinweisen, dass das Verhalten von VMware bzgl. der UUID-Änderung durch Anweisungen in der Definitionsdatei einer virtuellen Maschine beeinflusst werden kann. Siehe hierzu einige der unten angegebenen Links.

Auch die MAC-Einstellungen sind in der vmx-Datei natürlich zugänglich für evtl. notwendige Änderungen oder Rückschreibungen auf die ursprünglichen Werte.

Links

https://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=1541
https://www.vmware.com/support/ws5/doc/ws_move_uuid_moving_virtual_machines.html
https://pubs.vmware.com/workstation-12/index.jsp#com.vmware.ws.using.doc/GUID-533B2C4F-7BD5-41EB-8392-2B9FE687AE50.html
https://pubs.vmware.com/workstation-12/index.jsp?topic=%2Fcom.vmware.ws.using.doc%2FGUID-533B2C4F-7BD5-41EB-8392-2B9FE687AE50.html
https://jojitsoriano.wordpress.com/2010/09/03/avoiding-activation-when-movingcopying-a-windows-7-vmware-image/

VMware WS – bridging of Linux bridges and security implications

Virtual bridges must be treated with care when security aspects get important. I stumbled into an unexpected kind of potential security topic when I experimented with a combination of KVM and VMware Workstation on one and the same Linux host. I admit that the studied scenario was a very special and academic one, but it really gave me an idea about the threat that some programs may change important and security relevant bridge parameters on a Linux system in the background - and you as an admin may only become aware of the change and its security consequences indirectly.

The scenario starts with a virtual Linux bridge "br0" (created with "brctl"). This Linux bridge gets an IP-address and uses an assigned physical NIC for direct bridging to a physical LAN. You may want to read my previous blog article
Opensuse – manuelles Anlegen von Bridge to LAN Devices (br0, br1, …) für KVM Hosts
for more information about this type of direct bridging.

In our scenario the Linux brigde itself then gets enslaved as an ethernet capable device by a VMware bridge. See also: Opensuse/Linux – KVM, VMware WS – 3 virtuelle Brücken zwischen den Welten (see the detailed description of "Lösungsansatz 2").

Under which circumstances may such a complicated arrangement be interesting or necessary?

Direct attachment of virtualization guests to physical networks

A Linux host-system for virtualization may contain KVM guests as well as VMware Workstation [WS] guests. A simple way to attach a virtual guest to some physical LAN of the Linux host (without routing) is to directly "bridge" a physical device of the host - as e.g. "enp8s0" - and then attach the guest to the virtual bridge. Related methods are available both for KVM and VMware. (We do not look at routing models for the communication of virtual guests with physical networks in this article).

However, on a host, on which you started working with KVM before you began using VMware, you may already have bridged the physical device with a standard Linux bridge "br0" before you began/begin with the implementation of VMware guests.

Opensuse, e.g., automatically sets up Linux bridges for all physical NICs when you configure the host for virtualization with YaST2. Or you yourself may have configured the Linux bridge and attached both the physical device and virtual "tap"-devices via the "brctl" and the "tunctl" commands. Setting up KVM guests via virt-manager also may have resulted in the attachment of further virtual NIC (tap-) devices to the bridge.

The following sketch gives you an idea about a corresponding scenario:

kvm_vmware_b2b_bridge_4

Ignore for a moment the upper parts and the displayed private virtual networks there. In the lower part you recognize our Linux host's "direct bridge to LAN" in grey color with a red stitched border line. I have indicated some ports in order to visualize the association with assigned (named) virtual and physical network devices.

The bridge "br0" plays a double role: On one side it provides all the logic for packet forwarding to its target ports; on the other side it delivers the packets meant for the host itself to the Linux-kernel as if the bridge were a normal ethernet device. This is not done via an additional tap device of the host but directly. To indicate the difference "br0" is not sketched as a port.

The virtual and physical devices are also visible e.g. in the output of CLI commands like "ifconfig", "ip" or "wicked" with listing options as soon as the guest systems are started. The command "brctl show br0" would in addition inform you what devices are enslaved (via virtual ports) by the bridge "br0".

Note that the physical device has to operate in the so called "promiscuous mode" in this scenario and gets no IP-address.

Bridging the Linux bridge by VMware

Under such conditions VMware still offers you an option to bridge the physical device "enp8s0" - but after some tests you will find out that you are not able to transmit anything across the NIC "enp8s0" - because it is already enslaved by your Linux bridge ... Now, you may think : Let us create an additional Linux TAP-device on the host, add it to bridge "br0" and then set up a VMware network bridged to the new tap device. However, I never succeeded with bridging from VMware directly to a Linux tap device. (If you know how to do this, send me an email ...).

There are 2 other possibilities for directly connecting your VMware guests (without routing) to the LAN. One is to "bridge the Linux bridge br0" - by administrative means of VMware WS. The other requires a direct connection of the VMware switch via its Host Interface to the Linux-bridge with the spanning tree protocol enabled. We only look at the solution based on "bridging the bridge" in this article.

We achieve a cascaded bridge configuration in which the VMware switch enslaves a Linux bridge via VMwares "Virtual network editor":

vmware_vne_8

Such a solution is working quite well. The KVM guests can communicate with the physical LAN as well as with the VMware guests as long as all guests NICs are configured to be part of the same network segment. And the VMware guests reach the physical LAN as well as the KVM guests.

The resulting scenario is displayed in the following sketch:

kvm_vmware_b2b_bridge_5

In the lower part you recognize the "cascaded bridging": The ethernet device corresponding to the bridge "br0" is enslaved by the VMware bridge "vmnet3" in the example. The drawing is only schematic - I do not really know how the "bridging of the bridge" is realized internally.

Interestingly enough the command "brctl" on the Linux side does NOT allow for a similar type of cascaded "bridging of a Linux bridge". You cannot attach a Linux bridge to a Linux bridge port there.

We shall see that there is a good reason for this (maybe besides additional kernel module aspects and recursive stack handling).

Basic KVM guest "isolation" on a Linux bridge ?

A physical IEEE 802.1D bridge/switch may learn what MAC-addresses are reachable through which port, keep this information in an internal table and forward packets directly between ports without flooding packets to all ports. Is there something similar for virtual Linux bridges? The Linux bridge code implements a subset of the ANSI/IEEE 802.1d standard - see e.g. http://www.linuxfoundation.org/collaborate/workgroups/networking/bridge#What_does_a_bridge_do.3F.
So, yes, in a way: There is a so called "ageing" parameter of the bridge. If you set the ageing time to "0" by

brctl setageingtime br0 0

this setting brings the bridge into a "hub" like mode - all accepted packets are sent to all virtual ports - and a privileged user of a KVM guest may read all packets destined for all guests as well as for the LAN/WAN as soon as he switches the guest's ethernet device into the "promiscuous mode".

However, if you set the ageing parameter to a reasonable value like "30" or "40" then the bridge works in a kind of "switch" mode which isolates e.g. KVM guests attached to it against each other. The bridge then keeps track of the MAC adresses attached to its virtual ports and forwards packets accordingly and exclusively (see the man pages of "brctl"). Later on in this article we shall prove this by the means of a packet sniffer. (We assume normal operation here - it is clear that also a virtual bridge can be attacked by methods of ARP-spoofing and/or ARP-flooding).

Now, let us assume a situation with

brctl setageingtime br0 40

and let our Linux bridge be bridged by VMware. If I now asked you whether a KVM guest could listen to the data traffic of a VMware guest to the Internet, what would you answer?

What does "wireshark" tell us about KVM guest isolation without VMware started?

Let us first look at a situation where you have 2 KVM guests and VMware deactivated by

/etc/init.d/vmware stop

KVM guest 1 [kali2] may have an address of 192.168.0.20 in our test scenario, guest 2 [kali3] gets an address of 192.168.0.21. Both guests are attached to "br0" and can communicate with each other:

kvm_ne_12

kvm_ne_13

We first set explicitly

brctl setageing br0 30

on the host. Does KVM guest 1 see the network traffic of KVM guest 2 with Internet servers?

To answer this question we start "wireshark" on guest "kali3", filter for packets of guest "kali2" and first look at ping traffic directly sent to "kali3":
kvm_ne_14

Ok, as expected. Now, if we keep up packet tracking on kali3 and open a web page with "iceweasel" on kali2 we will not see any new packets in the wireshark window. This is the expected result. (Though it can not be displayed as it is difficult to visualize a non-appearance - you have to test it yourself). The Linux virtual bridge works more or less like a switch and directs the internet traffic of kali2 directly and exclusively to the attached "enp8s0"-port for the real ethernet NIC of the host. And incoming packets for kali2 are forwarded directly and exclusively from enp8s0 to the port for the vnet-device used by guest kali2. Thus, no traffic between guest "kali2" and a web server on the Tnternet can be seen on guest "kali3".

But now let us change the ageing-parameter:

brctl setageing br0 0

and reload our web page on kali2 again:

kvm_ne_15

Then we, indeed, see a full reaction of wireshark on guest kali3:
kvm_ne_16

All packets to and from the server are visible! Note that we have not discussed any attack vectors for packet sniffing here. We just discussed effects of special setting for the Linux bridge.

Intermediate result: Setting the ageing-parameter on a linux bridge helps to isolate the KVM guests against each other.

Can we see an Internet communication of a VMware guest on a KVM guest?

We now reset the ageing parameter of the bridge and start the daemons for VMware WS on our Opensuse host:

 
mytux:~ # brctl setageing br0 30 
mytux:~ # /etc/init.d/vmware start
Starting VMware services:                                                                 
   Virtual machine monitor                                             done               
   Virtual machine communication interface                             done               
   VM communication interface socket family                            done               
   Blocking file system                                                done               
   Virtual ethernet                                                    done               
   VMware Authentication Daemon                                        done               
   Shared Memory Available                                             done               
mytux:~ #               

 
Then we start a VMware guest with a reasonably configured IP address of 192.168.0.41 within our LAN segment:
kvm_ne_18
Then we load a web page on the VMware guest and have a parallel view at a reasonably filtered wireshark output on KVM guest "kali3":

kvm_ne_19

Wireshark:
kvm_ne_20

Hey, we can see - almost - everything! A closer look reveals that we only capture ACK and data packets from the Internet server (and other sources, which is not visible in our picture) but not packages from the VMware guest to the Internet server or other target servers.

Still and remarkably, we can capture all packets directed towards our VMware windows guest on a KVM guest. Despite an ageing parameter > 0 on the bridge "br0"!

Guest isolation in our scenario is obviously broken! To be able to follow TCP-packets and thereby be able to decode the respective data streams fetched from a server to a distinct virtualization guest from other virtualization guests is not something any admin wants to see on a virtualization host! This at least indicates a potential for resulting security problems!

So, how did this unexpected "sniffing" become possible?

Bridges and the promiscuous mode of an attached physical device

What does a virtual layer 2 Linux bridge with an attached (physical) device to a LAN do? It uses this special device to send packets from virtualization guests to the LAN and further into the Internet - and vice versa it receives packets from the Internet/LAN sent to the multiple attached guests or the host. Destination IP addresses are resolved to MAC-addresses via the ARP-protocol. A received packet is then transferred to the specific target guest attached at the bridge's virtual ports. If the ageing parameter is set > 0 the bridge remembers the MAC-address/port association and works like a switch - and thus realizes the basic guest isolation discussed above.

Let us have a look at the Linux bridge of our host :

 
mytux:/proc/net # brctl show br0 
bridge name     bridge id               STP enabled     interfaces
br0             8000.1c6f653dfd1e       no              enp8s0
                                                        vnet0
                                                        vnet4

 
The physical device "enp8s0" is attached. The additional network interfaces "vnet0", "venet4" devices are tun-devices assigned to our 2 virtual KVM guests "kali2" and "kali3".

There is a very basic requirement for the bridge to be able to distribute packets coming from the LAN to their guest targets: The special physical device - here "enp8s0" - must be put into the "promiscuous mode". This is required for the device to be able to receive and handle packets for multiple and different MAC- and associated IP-addresses.

How can we see that the "enp8s0"-device on my test KVM host really is in a promiscuous state? Good question: Actually and as far as I know, this is a bit more difficult than you may expect. Most standard tools you may want to use -
ifconfig, ip, "netstat -i" - fail to show the change if done in the background by bridge tools. However, a clear indication in my opinion is delivered by

mytux:/proc/net # cat /sys/class/net/enp8s0/flags 
0x1303

Watch the 3rd position! If I understand the settings corrrectly, I would assume that anything bigger than 1 there indicates that the IFF_PROMISC flag of a structure describing NIC properties is set - and this means promiscuous mode. It is interesting to see what happens if you remove the physical interface from the bridge

 
mytux:/proc/net # brctl delif br0 enp8s0
mytux:/proc/net # cat /sys/class/net/enp8s0/flags 
0x1003
mytux:/proc/net # brctl addif br0 enp8s0
mytux:/proc/net # cat /sys/class/net/enp8s0/flags 
0x1303
mytux:/proc/net # cat /sys/class/net/enp9s0/flags 
0x1003
mytux:/proc/net # cat /sys/class/net/vnet0/flags 
0x1303
mytux:/proc/net # cat /sys/class/net/vnet4/flags 
0x1303
mytux:/proc/net # 

 
The promiscuous mode is obviously switched on by the "brctl addif"-action. As a comparison see the setting for the physical ethernet device "enp9s0" not connected to the bridge. (By the way: all interfaces attached to the bridge are in the same promiscuous mode as "enp8s0". That does not help much for sniffing if the bridge works in a switch-like mode).

Another way of monitoring the promiscuous state of a physical ethernet device in virtual bridge scenarios is to follow the and analyze the output of systemd's "journalctl":

mytux:~ # brctl delif br0 enp8s0
mytux:~ # brctl addif br0 enp8s0

The parallel output of "journalctl -f" is:

 
...
.Jan 12 15:21:59 rux kernel: device enp8s0 left promiscuous mode
Jan 12 15:21:59 rux kernel: br0: port 1(enp8s0) entered disabled state
....
....
Jan 12 15:22:10 mytux kernel: IPv4: martian source 192.168.0.255 from 192.168.0.200, on dev enp8s0
....
....
Jan 12 15:22:13 mytux kernel: device enp8s0 entered promiscuous mode
Jan 12 15:22:13 mytux kernel: br0: port 1(enp8s0) entered forwarding state
Jan 12 15:22:13 mytux kernel: br0: port 1(enp8s0) entered forwarding state
...

 

Promiscuous or non promiscuous state of the Linux bride itself?

An interesting question is: In which state is our bridge - better the ethernet device it also represents (besides its port forwarding logic)? With stopped vmware-services? Let us see :

mytux:~ # /etc/init.d/vmware stop
....
mytux:~ # cat /sys/class/net/br0/flags 
0x1003

 
Obviously not in promiscuous mode. However, the bridge itself can work with ethernet packets addressed to it. In our configuration the bridge itself got an IP-address - associated with the host:

mytux:~ # wicked show  br0 enp8s0 vnet0 vnet4
enp8s0          enslaved
      link:     #2, state up, mtu 1500, master br0
      type:     ethernet, hwaddr 1c:6f:65:3d:fd:1e
      config:   compat:/etc/sysconfig/network/ifcfg-enp8s0

br0             up
      link:     #5, state up, mtu 1500
      type:     bridge
      config:   compat:/etc/sysconfig/network/ifcfg-br0
      addr:     ipv4 192.168.0.19/24
      route:    ipv4 default via 192.168.0.200

vnet4           device-unconfigured
      link:     #14, state up, mtu 1500, master br0
      type:     tap, hwaddr fe:54:00:27:4e:0a

vnet0           device-unconfigured
      link:     #18, state up, mtu 1500, master br0
      type:     tap, hwaddr fe:54:00:85:20:d1
mytux:~ # 

 
This means that the bridge "br0" also acts like a normal non promiscuous NIC for packets addressed to the host. As the bridge itself is not in promiscuous mode it will NOT handle packets not addressed to any of its attached ports (and associated MAC-addresses) and just throw them away. The attached ports - and even the host itself (br0) - thus would not see any packets not addressed to them. Note: That the virtual bridge can separate the traffic between its promiscuous ports and thereby isolate them with "ageing > 0" is a reasonable but additional internal feature.

What impact has VMware's "bridging the bridge" on br0 ?

However, "br0" becomes a part of a VMware bridge in our scenario - just like "enp8s0" became a part of the linux bridge "br0". This happens in our case as soon as we start a virtual VMware machine inside the user interface of VMware WS. Thinking a bit makes it clear that the VMware bridge - independent of how it is realized internally - must put the device "br0" (receiving external data form the LAN) into the promiscuous mode". And really:

mytux:/sys/class/net # cat /sys/class/net/br0/flags 
0x1103
mytux:/sys/class/net # 

 
This means that the bridge now also accepts packets sent from the Internet/LAN to the VMware guests attached to the VMware bridge realized by a device "vmnet3", which can be found under the "/dev"-directory. These packets arriving over "enp8s0" first pass the bridge "br0" before they are by some VMware magic picked up sat the output side of the Linux bridge and transmitted/forwarded to the VMware bridge.

But, obviously the Linux program responsible for the handling of packets reaching the bridge "br0" via "enp8s0" and the further internal distribution of such packets kicks in first (or in parallel) and gets a problem as it now receives packets which cannot be directed to any of its known ports.

Now, we speculate a bit: What does a standard physical 802.1D switch typically do when it gets packets addressed to it - but cannot identify the port to which it should transfer the packet? It just distributes or floods it to all of its ports!

And hey - here we have found a very plausible reason for our the fact that we can read incoming traffic to our VMware guest from all KVM guests!

Addendum 29.01.2016:
Since Kernel 3.1 options can be set for controlling and stopping the flooding of packets for unknown target MACs to specific ports of a Linux bridge. See e.g.:
http://events.linuxfoundation.org/sites/events/files/slides/LinuxConJapan2014_makita_0.pdf
The respective command would be :

echo 0 > /sys/class/net//brport/unicast_flooding

It would have to be used on all tap ports (for the KVM guests) on the Linux bridge. Such a procedure may deliver a solution to the problem described above. I have tested it, yet.

Conclusion

Although our scenario is a bit special we have learned some interesting things:

  1. Bridging a Linux bridge as if it were a normal ethernet device from other virtualization environments is a dangerous game and should be avoided on productive virtualization hosts!
  2. A Linux bridge may be set into promiscuous mode by background programs - and you may have to follow and analyze flag entries in special files for a network device under "/sys/class/net/" or "journalctl" entries" to get notice of the change! Actually, on a productive system one should monitor these sources for status changes of network devices.
  3. A Linux bridge in promiscuous mode may react like a 802.1D device and flood its ports with packets for which it has not learned MAC adresses yet - this obviously has security and performance implications - especially when the flooding becomes a permanent action as in our scenario.
  4. Due to points 2 and 3 the status of a Linux bridge to a physical ethernet device of a host must be monitored with care.

Regarding VMware and KVM/Linux-Bridges - what are possible alternatives for "linking" the virtual bridges of both sides to each other and enable communication between all attached guests?

One simple answer is routing (via the virtualization host). But are there also solutions without routing?

From what we have learned a scenario in which the virtual VMware switch is directly attached to a Linux bridge port seems to be preferable in comparison to "bridging the bridge". Port specific MAC addresses for the traffic could then be learned by the Linux bridge - and we would get a basic guest isolation. Such a solution would be a variation of what I have described as "Lösung 3" in a previous article about "bridges between KVM and VMware":
KVM, VMware WS – 3 virtuelle Brücken zwischen den Welten
However, in contrast to "Lösung 3" described there we would require a Linux bridge with activated STP protocol - because 2 ethernet devices would be enslaved by the Linux bridge. Whether such a scenario is really more secure, we may study in another article of this blog.

Links

See especially pages 301 - 304

http://www.linuxfoundation.org/collaborate/workgroups/networking/bridge#What_does_a_bridge_do.3F
See especially the paragraph "Why is it worse than a switch?"

Promiscuous mode analysis
https://www.kernel.org/doc/Documentation/ABI/testing/sysfs-class-net
http://grokbase.com/t/centos/centos/1023xtt5fd/how-to-find-out-promiscuous-mode
https://lists.centos.org/pipermail/centos/2010-February/090269.html
Wrong info via "netstat -i "
http://serverfault.com/questions/453213/why-is-my-ethernet-interface-in-promiscuous-mode