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

Opensuse/Linux – KVM, VMware WS – virtuelle Brücken zwischen den Welten

Bei der Wahl einer Virtualisierungsumgebung auf einem Linux-Host spielen viele Faktoren eine Rolle. Kosten, Anzahl der Gäste, Ressourcenbelastung des Hosts, Verfügbarkeit von Monitoring- und Admin-Umgebungen – aber auch die Kompatibilität mit den zu implementierenden Gastsystemen. Ich betrachte in diesem Artikel ausschließlich Linux-Arbeitsplatzsysteme als Virtualisierungshosts – also Desktops oder Laptops. Auf solchen Systemen verfolge ich dabei andere Interessen als auf Hosts für Server-Gast-Systeme:

In meinem Desktop-Umfeld spielen Windows-Gastsysteme für Entwicklungs- und für Penetrationstetsts neben Mehrzweck-Linux-Systemen wie Debian oder Kali2 eine Rolle. Ich benötige nur wenige und rudimentär ausgestattete Gäste. Die durchschnittliche Belastung des Virtualisierungs-Hosts ist somit relativ gering. Die Kosten sollen möglichst klein sein, die administrativen Möglichkeiten ausreichend, d.h. ohne Luxus. Für alle Gastsysteme gilt aber, dass die emulierte grafische Oberfläche hinreichend flüssig bedienbar sein muss.

Für die Windows-Desktops verwende ich deshalb eine VMware-Workstation-Umgebung, da mir diese Virtualisierungs-Plattform erfahrungsgemäß gut handhabbare Windows-Gastsysteme inkl. einer schnellen grafischen Oberfläche liefert. Zur Not auch mit 3D-Grafik-Unterstützung. Linux-Gäste fahre ich dagegen unter der KVM/Qemu-Virtualisierungsinfrastruktur – durch virtio-Treiber, Spice und Video XQL ist dort die grafische Nutzeroberfläche (inzwischen) hinreichend schnell (wenn z.Z. auch noch ohne 3D-Support). Libvirt/virt-manager liefern für KVM ausreichende und bequeme Möglichkeiten der Administration.

Mixt man – wie ich – zwei unterschiedliche Virtualisierungsumgebungen auf ein und demselben Host, so entstehen neue Begehrlichkeiten. Das gilt im Besonderen für die Konfiguration eines Pentest-Labors und die schnelle Abänderung der Netzwerk-Konfiguration. Für Penetrationstests isoliert man die Gäste i.d.R. in privaten Netzwerken. Diese werden jeweils durch eine virtuelle Bridge repräsentiert – mit oder ggf. auch mal ohne Host-NIC, um auch den Host an das jeweilige Netzwerk anbinden zu können. Ein direktes Bridging zu physikalischen Devices des Hosts bringt dagegen je nach Testsituation zu viele Gefahren für den Hosts selbst und dessen LAN-Umgebung mit sich.

“Host-Only-Netzwerke” [HON] kann man sowohl unter VMware WS als auch unter KVM realisieren. Jedes Host-Only-Netzwerk definiert ein bestimmtes Netzwerksegment, dem die jeweiligen Gastsysteme und ggf. der Host über spezielle virtuelle NICs zugeordnet werden.

In vorliegenden Artikel will ich auf die Frage eingehen, ob und wie man

  • Gäste einer “KVM”-Umgebung an eine Host-Only-Bridge Bridge einer VMware WS-Umgebung
  • und/oder umgekehrt Gäste einer “VMware WS”-Umgebung an eine Host-Only-Bridge Bridge einer KVM-Umgebung

anbinden kann. Natürlich könnte man immer über den Host zwischen den Netzwerksegmenten der Virtualisierungsumgebungen routen. Das ist sicher die schnellste Art der Kopplung. Mich interessieren in diesem Artikel aber Möglichkeiten, die ohne Routing auskommen. Ich meine also Szenarien, in denen die Gastsysteme der beiden Virtualisierungsumgebungen Teil eines logischen Netzwerk-Segmentes (auf Layer 3) werden.

Es geht also um eine Art “Cross”-Bridging” für bestimmte Gäste der unterschiedlichen Virtualisierungsumgebungen. Ich stelle hierfür nachfolgend drei verschiedene Lösungen vor. Eine vierte Lösung – eine elegante Spielart der dritten Lösung – wird im kommenden Artikel Fun with veth devices, Linux virtual bridges, KVM, VMware – attach the host and connect bridges via veth
vorgestellt.

Wozu braucht man die Möglichkeit einer gegenseitigen direkten Anbindung von Gästen einer “KVM”- oder “VMware WS”-Umgebung an ein Host-Only-Netzwerk der jeweils anderen Virtualisierungs-Infrastruktur?

Stattet man die Gastsysteme mit nur einer NIC aus, welche über die Verwaltungstools der jeweiligen Virtualisierungsinfrastruktur an die dort beheimatete virtuelle Bridge angebunden wird, so können die Gastsysteme des Segments der einen Virtualisierungsumgebung mit den Gastsystemen des Segments der jeweils anderen Virtualisierungsumgebung nur dann kommunizieren, wenn Routing über den Host und dessen Paketfilter zugelassen wird. Damit sind unter Penetrationstest-Bedingungen aber erneut Sicherheitsrisiken (“packet leackage” ins physikalische Netz) verbunden.

Umgekehrt gilt: Auch ohne Paketfilter erzwingen die Standardeinstellungen der Router/Forwarding-Funktionalität eines Linux-Systems Einschränkungen – u.a. werden IP-gespoofte Pakete, mit Ursprungsadressen im jeweils anderen Segment, nicht vom Linux-Kernel des Hosts weitergeleitet. Unter diesen Bedingungen kann im Rahmen von Penetrationstests dann z.B. ein NMAP Idle-Scan von einem Linux-System im KVM-Segment über ein “idle” Windows-System zu einem Windows-Target im VMware-Segment nicht durchgespielt werden.

Grundsätzlich ist meine Anforderung die, dass man auf die Vorteile der jeweiligen Virtualisierungsumgebung für die Gast-Einrichtung nicht verzichten will, unter bestimmten Bedingungen aber eine direkte – d.h. routing-freie – Anbindung eines Gastsystems an das Host-Only-Netzwerksegment der jeweils anderen Virtualisierungsumgebung nutzen möchte – über eine entsprechende konfigurierte (ggf. zusätzliche) virtuelle NIC.

Ich wollte das schon länger mal aus Prinzip ausprobieren – einfach um zu sehen, ob und wie das ggf. geht. Durch Aktivierung/Deaktivierung von NICs und zugehörigen Profilen will ich für ein Gastsystem schnell zwischen Szenarien mit Routing und ggf. zwischengeschalteten Paketfiltern einerseits und direkter Segment-Anbindung andererseits umschalten können.

Das Ganze ist aber auch unter dem Aspekt interessant, dass ein direktes “cascaded” oder “nested” Bridging von Linux-Bridges nicht möglich ist. So stellt sich u.a. die Frage: Wie bekommt man eine VMware Bridge an eine Linux-Bridge angeschlossen?

Netzwerk-Editoren

In der “VMware WS”-Umgebung nutzt man zur Konfiguration virtueller Netzwerke/virtueller Bridges als User root den “Virtual Network Editor” (s. Abbdg.), unter KVM den “Virtual Machine Manager” (virt-manager > “Edit” >> “Connection Details” >> “Virtual Networks”) und/oder eine Kombination aus “brctl”- und “ip” bzw. “tunctl”-Kommandos.

VMware Virtual Network Editor [VNE]
vmware_vne_1

KVM Virtual Machine Manager => Virtual Networks
kvm_ne_1

CLI-Kommandos: brctl/tunctl/ip
Wir kommen auf die praktische Anwendung dieser Kommandos weiter unten zurück. (Siehe aber auch: Opensuse – manuelles Anlegen von Bridge to LAN Devices (br0, br1, …) für KVM Hosts.) Festzuhalten bleibt zunächst, dass ein mittels “tunctl” erzeugtes virtuelles “tap”-Device (Layer 2 Ethernet Device) nur genau einer Linux-Bridge zugeordnet werden kann. Ein Kaskadieren von Bridges (= direktes Einhängen einer Linux-Bridge in eine andere) ist wie gesagt auch nicht möglich.

Ein paar Anmerkungen zum VMware VNE:
nVermutlich reichen die Konfigurationsmöglichkeiten der VMware WS nicht an die der großen VMware Vitualisierungsumgebungen heran – hinreichend sind sie aber. So kann man u.a. Host-Only-Netzwerke (Bridges) mit oder ohne NAT erzeugen. Bei der Erzeugung eines VMware Host-Only-Segments wird automatisch eine Host-NIC für die erzeugte Bridge mit erzeugt. Diese Host-NIC für das VMware Host-Only-Netz erscheint dann – obwohl virtuell – als Ethernet-Device des Hostes.

vmnet1          device-unconfigured
      link:     #11, state up, mtu 1500
      type:     ethernet, hwaddr 00:50:56:c0:00:01
      addr:     ipv4 192.168.48.1/24

vmnet2          device-unconfigured
      link:     #12, state up, mtu 1500
      type:     ethernet, hwaddr 00:50:56:c0:00:02
      addr:     ipv4 192.168.3.1/24

 
Das ist insofern bemerkenswert, als es in einem entscheidenden Punkt anders aussieht als bei den “tap”- und Bridge-Devices, die man (z.B. mit virt-manager) zu virtuellen “vibr”-Bridges in der KVM-Welt erzeugt:

Der Typ des virtuellen VMware Devices ist “ethernet”! Nicht “bridge” oder “tap”.

Die VMware-Umgebung bietet auch ein direktes Bridging zu physikalischen Host-NICs an. Erzeugt man virtuelle Devices unter Linux und verfolgt, was sich dann auf der VMware-Seite tut, so sieht man: Die VMware Umgebung erkennt neue Netzwerk-Devices (wie erzeugte virtuelle Linux-Bridges und Linux Tap-Devices) und bietet (zumindest theoretisch) ein direktes Bridging auch zu diesen virtuellen Devices an.

Wie bringt man nun mit diesem Rüstzeug die unterschiedlichen Virtualisierungs-Welten bzw. ihre Gastsysteme auf einem Linux-Desktop-System zusammen? Welche Möglichkeiten gibt es?

Lösungsansatz 1: Anbindung von KVM-Gästen an das virtuelle VMware-Netz mittels “macvtap”-Devices

Im ersten Lösungsansatz möchte ich versuchen, ausgewählte KVM-Gäste der Linux-Bridge direkt an das virtuelle VMware-Netz anzubinden. Das soll vom Effekt her ungefähr so aussehen:

kvm_to_vmware

Im Zentrum des Interesses steht “Guest0” im KVM-Bereich. Das eine Interface (vnet1) dieses Gastes ist regulär an die Linux-Bridge “virbr0” angebunden. Von dort könnte über den Host ins VMware-Netz geroutet werden. Das wollen wir aber vermeiden und statt dessen über ein weiteres Interface die nahtlose Anbindung von Guest0 an das virtuelle Netz “vmnet1” auf der VMware-Seite erreichen – unter Umgehung irgendwelcher Paketfilter des Hostes. Siehe die gestrichelte Linie. Auch wenn wir das nicht direkt in der dargestellten Form verwirklichen können, so soll doch zumindest der effektive Datentransport der Logik dieses Bildes entsprechen.

Der VMware WS VNE bietet eine direkte Anbindung virtueller “tap”-Devices von VMware Gästen an die vmnet1-Bridge leider nicht an. Das einzige Element von “vmnet1”, das auf der Linux-Seite für evtl. Manipulationen zur Verfügung steht, ist die zugehörige virtuelle Host-NIC gleichen Namens. Was können wir damit aus Sicht eines KVM-Gastes tun?

macvtap-Devices?

KVM unterstützt seit einigen Jahren die Nutzung physikalischer Ethernet Devices durch Gastsysteme in Form sog. virtueller “macvtap”-Bridge-Devices. Zur Einführung siehe
http://virt.kernelnewbies.org/MacVTap

Ein weiterer sehr lesenswerter Artikel hat mein Verständnis beträchtlich erhöht:
https://seravo.fi/2012/virtualized-bridged-networking-with-macvtap

Der folgende
Artikel zeigt, wie man macvtap Devices in einer mit “libvirt” verwalteten Umgebung manuell über entsprechende Einträge in XML-Konfigurationsdateien einbindet.

 
Weitere interessante Artikel zu macvtap-Devices sind:
https://wiki.math.cmu.edu/iki/wiki/tips/20140303-kvm-macvtap.html
http://www.furorteutonicus.eu/2013/08/04/enabling-host-guest-networking-with-kvm-macvlan-and-macvtap/

Man beachte, dass alle genannten Artikel auf physikalische Devices als sog. “lower devices” einer “macvtap”-Bridge Bezug nehmen. Kann man evtl. auch virtuelle VMware-Devices in einer macvtap-Bridge nutzen?

Nutzung von VMware Host-NICs in einer MacVtap-Bridge?

Die Vermutung liegt nahe, dass aus Sicht des Linux-Kernels lediglich relevant ist, dass ein entsprechender “device node” mit zugeordneten Treibern und einem unterstützten Ethernet Stack vorhanden ist. VMware hat hier ganze Arbeit geleistet:

Die virtuellen Host-NICs für die virtuellen VMware Host-Only-Netze erscheinen unter “ifconfig” als vollwertige Ethernet Devices (s.o.). Unter dem Verzeichnis “/dev/” findet man zudem zugehörige Dateien für zeichenorientierte Geräte.

Also: Warum nicht mal ein virtuelles VMware “Ethernet”-Devices in KVM über MacVtap bridgen? Man könnte dann einem KVM-(Linux)-Gast-System eine virtuelle NIC zuordnen, die das Ethernet-Device “vmnet1” über den “macvtap”-Mechanismus nutzt. Wird das virtuelle Device im KVM-Gastsystem danach mit einer IP-Adresse versehen, die zum VMware-Netzwerk-Segment “vmnet1” passt, sollte der KVM-Gast direkt im VMware-Netz erreichbar sein bzw. direkt mit Gästen des VMware-Netzes kommunizieren können.

Konfiguration eines MacVtap-Devices auf einem KVM-Gast mit virt-manager

Um meinem Kali2-Gastsystem in der KVM-Umgebung testweise ein macvtap-Device zuzuordnen benutze ich “virt-manager”. (Ich gehe dabei davon aus, dass der libvirtd-Dämon gestartet wurde, nachdem das virtuelle VMware-Netz angelegt wurde, so dass die “vmnet”-Netzwerk-Devices der KVM-Umgebung mit Sicherheit bekannt sind.)

kvm_ne_3

Mit dem Ergebnis:

kvm_ne_2_800

Nun ggf. das Gastsystem nochmal rebooten. Dann die neue virtuelle NIC im Gastsystem konfigurieren – hier in einem Kali2-System:

kvm_ne_4_800

Danach unter VMware WS ein Gastsystem starten. Hier z.B. ein altes XP-System mit einer IP 192.168.48.3. Dann auf beiden Seiten pingen:

kvm_ne_5

vmware_vne_2

Sieht doch gut aus! Nun auch noch testweise einen nmap-Scan durchführen:

kvm_ne_6

Bestens – Lösungsansatz 1 funktioniert offenbar! Wenn intern auch nicht exakt so, wie im einleitenden Bild dargestellt.

Lösungansatz 2: Der umgekehrte Weg über eine virtuelle Linux-Bridge

Nun wollen wir uns um den umgekehrten Ansatz kümmern. Ein ausgewählter VMware WS-Gast soll irgendwie an eine Linux-Bridge, die von KVM-Gästen bereits über tap-Devices genutzt wird, angebunden werden. Die nachfolgende Abbildung zeigt, wie man sich das in etwa vorstellen kann.

vmware_to_kvm

Im Gegensatz zum entsprechenden Bild für den Lösungsansatz 1 haben wir jetzt die Möglichkeit des Routings über den Host ganz ausgeblendet. Zu beachten ist auch, dass das 192.168.48.0/24-Netz sich jetzt auf der rechten Seite befindet. Der Host selbst erhält in unserem Szenario nicht mal eine eigene, and die Bridge angeschlossene virtuelle NIC.

Die entscheidende Frage ist, ob und wie VMware WS dazu zu bekommen ist, eine Linux-Bridge zu nutzen, die mit “brctl addbr” erzeugt wird. Wer einen genauen Blick auf die ursprüngliche VMware-Netz-Konfiguration meines Testsystems weiter oben wirft, stellt fest, dass VMware offenbar virtuelle Netzwerke mit Zugriff auf eine Linux-Bridge (im Beispiel br0) einrichten kann. Das “br0”-Device ist auf meinem Testsystem eine direkte Linux-Bridge zu einem physikalischen Device. Was aber nichts daran ändert, dass es sich dabei um eine kernel-unterstützte Bridge handelt. Deshalb liegt es nahe, das ganze Spiel mal mit einer Linux-Bridge für ein rein virtuelles Host-Only-Netzwerk zu probieren.

Um Verwerfungen zu vermeiden, fahren wir dazu unseren KVM-Gast runter, entfernen dann das oben eingerichtete MacVtap-Device aus diesem Gast mittels “virt-manager”. Dann wechseln wir als root in den VMware Network Editor und löschen das Netzwerk “vmnet1”. Die entsprechende Host-NIC ist ist danach auch nicht mehr als Character-Device unter Linux vorhanden. In der Konfiguration der VMware-Gäste entfernen wir zur Sicherheit entsprechende Netzwerk-Karten vollständig.

Nun richten wir manuell eine Linux-Bridge namens “virbr_vmw” auf unserem Linux-Host ein:

mytux:/etc/init.d # brctl addbr virbr_vmw
mytux:/etc/init.d # ifconfig virbr_vmw 192.168.48.1 netmask 255.255.255.0 broadcast 192.168.48.255 
maytux:/etc/init.d # wicked show all
...
...
virbr_vmw       device-unconfigured
      link:     #47, state up, mtu 1500
      type:     bridge
      addr:     ipv4 192.168.48.1/24
...

 
Wir wechseln dann erneut zu VMwares “Virtual Network Editor”. Hier fügen wir ein neues Netzwerk hinzu. Und zwar im Modus “Bridged” – hierdurch wird für die VMware-Gäste eine Bridge zum Sharen eines Linux-Devices erzeugt. Wir verwenden für das neue virtuelle Netzwerk den inzwischen wieder freigewordenen Namen “vmnet1”:

vmware_vne_3

Durch eine VMware-Automatik wird das Netzwerk “vmnet1” dabei vorerst der nächsten freien physikalischen Netzwerkschnittstelle – soweit vorhanden – zugeordnet. In meinem Fall ist das das Device “enp9s0”:

vmware_vne_4

Wir können das aber ändern und wählen über die Combobox vielmehr die neu angelegte Linux-Bridge “virbr_vmw” aus :

vmware_vne_5

[Sollte die Linux-Bridge noch nicht in der Auswahl angezeigt werden, müssen die VMware-Dienste ggf. runter gefahren und dann über die entsprechen Skripte (/etc/init.d/vmware restart) neu gestartet werden.]

In den Konfigurationseinstellungen eines geeigneten VMware-Gastes legen wir nun ein Netzwerk-Interface zum virtuellen Netz “vmnet1” an. Wir fahren den Gast (in unserem Testfall ein XP-System) anschließend hoch und konfigurieren dort das neue Device mittels der Konfigurationswerkzeuge des VMware-Gastes (hier eines Windows-Systems). Soweit, so gut. Unsere Bridge kann natürlich von unserem Linux-Host aus angepingt werden. Ist unser VMware-Gast aber auch vom Host aus erreichbar?

kvm_ne_7

Offenbar ja! Aber wir haben insgesamt noch keine permanente, statische Konfiguration sondern nur eine temporäre erzeugt, die beim nächsten Systemboot verloren gehen würde.

Nun machen wir die ganze Sache auf unserem Opensuse-System permanent. Dazu legen als root unter dem Verzeichnis “/etc/sysconfig/network” eine Datei “ifcfg-virbr_vmw” an – mit folgendem Inhalt:

BOOTPROTO='static'
BRIDGE='yes'
BRIDGE_FORWARDDELAY='0'
BRIDGE_PORTS=''
BRIDGE_STP='off'
BROADCAST=''
DHCLIENT_SET_DEFAULT_ROUTE='yes'
ETHTOOL_OPTIONS=''
IPADDR='192.168.48.1/24'
MTU=''
NETWORK=''
PREFIXLEN='24'
REMOTE_IPADDR=''
STARTMODE='auto'
NAME=''

 
Im Gegensatz zu einer evtl. schon vorhandenen Bridge “br0” ordnen wir dem Bridge-Device aber keine physikalische NIC des Hostes (wie etwa “enp9s0”) zu!

Hinweis: Debian- oder Red Hat-Anhänger nutzen entsprechende Konfigurationsdateien ihres Systems, die sich teils in anderen Verzeichnissen befinden, einen anderen Namen haben und eine im Detail abweichende Syntax erfordern.

Nun fahren wir alle evtl. noch laufenden virtuellen Maschinen runter und re-booten danach unseren Host. Nach dem Booten sollte man nach Eingabe des Kommandos “ifconfig” in ein Host-Terminal u.a. Folgendes sehen:

virbr_vmw Link encap:Ethernet  HWaddr EA:93:44:6E:45:55  
          inet addr:192.168.48.1  Bcast:192.168.48.255  Mask:255.255.255.0
          inet6 addr: fe80::e893:44ff:fe6e:4555/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:132 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:0 (0.0 b)  TX bytes:21008 (20.5 Kb)

 
Wir fahren unseren VMware-Gast wieder hoch und prüfen, ob ein An-Pingen des Hostes möglich ist.

vmware_vne_6

Wenn nicht, so ist noch etwas an der Konfigurationsdatei falsch. Ggf. mit YaST über die dortigen Module zur Netzwerk-Konfiguration prüfen. Zur Sicherheit auch nochmal die Routen auf dem Host und im VMware-Gast kontrollieren.

Nun wenden wir uns unserem KVM-Gast-System zu. Über die Verwaltungsoberfläche von virt-manager fügen wir der Hardware des Gastes ein neues Device hinzu:

kvm_ne_8

Wir starten danach den KVM-Gast und konfigurieren dort das neue Ethernet-Device mit den Mitteln des Gastsystems (hier mit Kali2/Debian-Einstellungswerkzeugen):

kvm_ne_9

Abschließend testen wir wieder Pings in Richtung Host, VMware-Gast und zurück:

kvm_ne_11

vmware_vne_7

So liebe ich Virtualisierung! Weitere KVM-Gäste benötigen lediglich ein Netzwerk-Interface zur Bridge “virbr_vmw” – und dann stehen auch sie schon in Verbindung zu entsprechend konfigurierten Gästen des VMware-Systems.

Lösungsansatz 3: Einbinden des VMware-Ethernet-Devices in die Linux-Bridge

Lösungsansatz 1 bot eine Möglichkeit zur direkten Anbindung einzelner KVM-Gäste an das VMware Host-Only-Netzwerk. Es stellt sich die Frage: Geht das nicht auch kollektiv?

Dazu müsste man das von VMware bereitgestellte Ethernet-Device in die Linux-Bridge einbinden. Sprich das Host-Interface des VMware-Switches muss Teil der Linux-Bridge werden. Das entspräche einem Kaskadieren von Bridges. Funktioniert das? Bildlich sähe das dann etwa wie folgt aus:

vmw-to_kvm_1

Die erste Frage, die sich einem beim Betrachten stellt, ist: Wie vermeidet man Kollisionen in der Addresszuweisung? DHCP-seitig sollte nach dem Einhängen der des VMware-Devices nur noch genau ein DHCP-Dienst laufen – z.B. der auf der Linux-Seite. Dazu muss beim Einrichten des VMware-Netzwerkes die angebotene DHCP-Funktionalität abgewählt werden.

Der andere Punkt ist der, dass man zumindest mit dem “Virtual Machine Manager” ein Problem bekommt, wenn man ein virtuelles Host-Only-Netzwerk anlegen will, dass das gleiche Segment betrifft, aus dessen Adressbereich anderen virtuellen oder physikalischen Devices bereits IP-Adressen zugewiesen wurden. Also legt man als Erstes am besten die Bridge auf der rechten Seite der obigen Abbildung an. Wir benutzen dazu KVM’s virt-manager:

vmw-to_kvm_2

Das Netzwerk taucht in meinem Fall in Form der virtuellen Bridge “virbr2” auf dem Host auf (mit “brtcl show” prüfbar). Nun ordnen wir einem KVM-Gast noch ein entsprechendes virtuelles Device zu:

vmw-to_kvm_3

Wir können diesen Gast schon mal starten und die Zuordnung zur Bridge prüfen:

mytux:~ # brctl show virbr2
bridge name     bridge id               STP enabled     interfaces
virbr2          8000.005056c00008       yes             virbr2-nic
                                                        vnet4
mytux:~ # 

 
OK, jetzt aber zur VMware-Seite. Ein neues virtuelles Netzwerk ist auch im VNE schnell angelegt:

vmw-to_kvm_4

r
(Hinweis: Das ist nicht mehr das standardmäßige vmnet8 Host-Only-Network, das VMware nach einer anfänglichen Installation automatisch konfiguriert, sondern mein eigenes. Ihr könnt zum Testen natürlich auch das vorkonfigurierte verwenden – oder statt der “8” eine andere Nummer wählen).

Leider ist VMware beim Generieren des gleichnamigen Host-Interfaces gnadenlos und überprüft im Gegensatz zu KVM nicht, ob der Adressraum Überschneidungen aufweist:

mytux:~ # ip address show       
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default 
...
18: virbr2: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default 
    link/ether 52:54:00:6b:ab:44 brd ff:ff:ff:ff:ff:ff
    inet 192.168.6.1/24 brd 192.168.6.255 scope global virbr2
       valid_lft forever preferred_lft forever
19: virbr2-nic: <BROADCAST,MULTICAST> mtu 1500 qdisc pfifo_fast master virbr2 state DOWN group default qlen 500
    link/ether 52:54:00:6b:ab:44 brd ff:ff:ff:ff:ff:ff
20: vmnet8: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UNKNOWN group default qlen 1000
    link/ether 00:50:56:c0:00:08 brd ff:ff:ff:ff:ff:ff
    inet 192.168.6.1/24 brd 192.168.6.255 scope global vmnet8
       valid_lft forever preferred_lft forever
    inet6 fe80::250:56ff:fec0:8/64 scope link 
       valid_lft forever preferred_lft forever
mytux:~ # 

 
So gehts natürlich nicht – wir entfernen die IP-Adresse manuell vom VMware-Interface:

mytux:~ # ip addr del 192.168.6.1/24 broadcast 192.168.6.255 dev vmnet8

 

Nachtrag, 30.01.2016:
Interessanterweise wurde nach einem heutigen Kernelupdate und einer Neukompilation der VMware-Programme der VMware-Dienst “Virtual Ethernet” zur Aktivierung der virtuellen VMware-Netze nicht mehr erfolgreich gestartet, wenn dadurch Überlapps in der IP-Adresse mit irgendeiner gestarteten KVM-Bridge produziert wurden. In einem solchen Fall muss man die VMware Standard-DHCP-Einstellungen für das betroffene virtuelle Netzwerk in der Datei “/etc/vmware/netzwerkname/dhcpd/dhcpd.conf” für das erzeugte Ethernet-Device der Bridge manuell abändern.

Nun kommt ein wichtiger Punkt:

Welche IP ordnen wir dem Interface “vmnet8” statt dessen zu? Erinnern wir uns an Linux-Bridges zu physikalischen Ethernet-Devices (s. etwa: Opensuse – manuelles Anlegen von Bridge to LAN Devices (br0, br1, …) für KVM Hosts):
Dem Ethernet Device (in seiner Funktion als Uplink-Device) darf dort keine IP-Adresse zugeordnet sein! Die richtige Antwort ist auch in diesem Fall: Keine IP-Adresse für das vmnet-Device!

Da wir schon schon auf der Kommandozeile sind, ordnen wir jetzt unserer Bridge “virbr2” das Device “vmnet8” manuell zu:

mytux:~ # brctl addif virbr2 vmnet8
mytux:~ # brctl show virbr2
bridge name     bridge id               STP enabled     interfaces
virbr2          8000.005056c00008       yes             virbr2-nic
                                                        vmnet8
                                                        vnet4
mytux:~ # 

 
Nun statten wir unseren exemplarischen VMware-Gast noch mit einem passenden Interface aus:

vmw-to_kvm_5

Dann fahren wir den VMware-Gast hoch, konfigurieren unsere neue
Netzwerkschnittstelle dort mit den vorhandenen Tools des Gast-Betriebssystems (hier Windows) manuell und probieren, ob wir den Host erreichen können:

vmw-to_kvm_6

Bestens! Nun zu unserem Linux-KVM-Gast:

vmw-to_kvm_7

Alles klar! Lösung 3 funktioniert. Der Leser, der das nachbaut, kann ja selbst weitere Tests durchführen.

Lösung 3 erscheint mir persönlich unter den drei hier besprochenen Ansätzen die strukturell klarste zu sein. Sie hat allerdings den Nachteil, dass man sich selbst darum kümmern muss, dass dem VMware Interface (hier “vmnet8”) auch beim nächsten Systemstart die IP-Adresse entzogen wird. Sobald der VMware-Dienst startet, konfiguriert er “vmnet8” ansonsten nämlich wieder mit einer Adresse. Ich habe bislang keine Möglichkeit gefunden, das über die VMware-Netzwerk-Konfigurations-Tools und zugehörige Konfigurationsdateien unter “/etc/vmware” abzustellen.

Auch die Zuordnung des VMware Devices zur Linux-Bridge sollte man am besten selbst vornehmen, um von der Reihenfolge des Starts der diversen Virtualisierungsdienste etwas unabhängiger zu werden. Für die Abarbeitung entsprechender Kommandos erstellt man sich ein kleines Script, dass man mit ein bisschen Geschick auch als eigenen systemd-Service in den systemd-Startup-Vorgang einbinden kann.

Alternativer Lösungsansatz 4: Nutzung von veth-Device-Paaren für die Bridge-Kopplung

Ein anderer Weg zur Realisierung einer Bridge-Kopplung im Geiste von Lösung 3 besteht darin, die VMware Bridge von vornherein als Bridge zu einem im Linux-System angelegten “veth”-Device zu kreieren. Das zweite Interface des veth-Paars wird dann zur Anbindung an die Linux-Bridge eingesetzt. Ehrlich gesagt, ist das dann die Lösung, die ich für die wirklich beste halte. Ich gehe auf den Einsatz von veth-device-Paaren für ein strukturiertes Bridge-Linking ausführlich in einem kommenden Artikel ein (Fun with veth devices, Linux virtual bridges, KVM, VMware – attach the host and connect bridges via veth).

Performance der vorgestellten Lösungen?

Ein gute Frage! Ohne gezielte Messungen traue ich mich nicht, hierzu Aussagen zu machen. MacVtap bietet z.B. eine leichtgewichtige und auch performante Methode, ein Ethernet-Interface zu nutzen. Die Frage ist allerdings, wie gut das Character-Device, das VMware auf dem Host für ein virtuelles Netz bereitstellt, mit mehreren Kommunikationsströmen zwischen KVM-Gästen und VMware-Gästen, die in Lösung 1 und Lösung 3 gleichzeitig über dieses eine (!) Interface transferiert werden müssen, klarkommt. In Lösung 2 hängt dagegen alles an der unter Linux definierten (und vom Kernel unterstützten) virtuellen Bridge, die gleichzeitig von Gästen aus beiden Virtualisierungs-Umgebungen geteilt wird.

Schwer einzuschätzen …… Bin für Hinweise dankbar. In meinem Mini-Labor für Penetrationstests konnte ich bislang keine signifikanten Unterschiede ausmachen. Werde die Sache aber im Auge behalten …

Security

Standard-Bridges haben aus Security-Sicht einen grundlegenden Nachteil: Sie müssen mindestens über ein angeschlossenes Netzwerk-Interface Pakete für verschiedene IP-Adressen entgegennehmen können. Was bedeutet das eigentlich im Fall unserer zweiten und dritten Lösung für die Sicherheit? Eine sehr gute Frage, die man dann aber auch gleich für die Standardbridge “br0” stellen muss. Hier muss ich den Leser vertrösten. Ich werde mich in kommenden Artikeln mit diesem
Thema etwas intensiver auseinandersetzen. Siehe u.a.:
VMware WS – bridging of Linux bridges and security implications

Für den Augenblick möchte ich allerdings folgende explizite Warnung aussprechen:

Warnung : Das Bridgen einer Bridge – wie in Lösung 2 – ist aus Security-Gesichtspunkten ein gefährliches Spiel. In Pentest-Labors mag so etwas nützlich sein – in Produktivumgebungen sollten beim Admin alle roten Warnleuchten angehen, da die Bridge dann selbst – und nicht nur ein spezielles Uplink-Interface – in den “promiscuous mode” versetzt wird.
 
Eine Abschottung des Datenverkehrs bestimmter Gastsysteme von und mit externen Systemen gegen ein Mithören durch andere Gäste ist dann nicht mehr garantiert – selbst wenn die Linux-Bridge das im Normalfall leisten würde.  
 
Man muss dann sehr genau wissen, was man tut, und ggf. explizit untersuchen, wie die Linux-Bridge auf die Modifikationen durch erneutes Bridging reagiert.

Fazit

Was haben wir erreicht? Die von einer “VMware WS” bereitgestellten virtuellen Devices des Hosts erscheinen unter Linux als vollwertige (zeichen-orientierte) Ethernet-Devices. Sie können von einem KVM-Gast z.B. über die Einrichtung eines individuellen MacVtap-Devices genutzt werden. Nach Konfiguration mit IP-Adressen und passenden Routen wird der KVM-Gast dann für alle praktischen Anwendungen Mitglied des VMware-Netzes.

Umgekehrt und alternativ lässt sich eine virtuelle Linux-Bridge, die mit einer IP-Adresse ausgestattet wurde, unter VMware als direkt gebridgtes Ethernet-Device von mehreren VMware-Gästen nutzen. KVM-Gäste werden an die Linux-Bridge mit Standard-Verfahren angebunden. VMware-Gäste, die über das Bridging der Linux-Bridge an selbige Linux-Bridge angeschlossen wurden, kommunizieren direkt mit allen KVM-Gastsystemen.

Beiden Lösungen 1 und 2 ist gemeinsam, dass sie ein bereits virtualisiertes Devices auf einer Metaebene nochmals in virtualisierter Form nutzen. Das allein macht diese Lösungen – wie ich finde – spannend.

Am elegantesten erscheint im Rückblick jedoch Lösung 3 (bzw. Lösung 4) zu sein. Der VMware-Switch wird dabei einfach und ohne IP-Adresse in die Linux-Bridge integriert. Das Vmware-Hostinterface funktioniert dann wie ein Uplink-Device zum VMware-Switch.

Alle beschriebenen Methoden können im Einzelfall jedoch erhebliche Sicherheitsimplikationen nach sich ziehen. Damit werde ich mich in kommenden Artikeln befassen.

Immerhin:
Durch Aktivierung oder Deaktivierung von entsprechend konfigurierten Ethernet-Devices auf KVM- und VMware-Gästen kann man in allen drei dargestellten Fällen schnell zwischen

  • einer Konfiguration mit einer über den Host gerouteten Verbindung zum VMware-Netz
  • oder einer Konfiguration mit einer direkten Ein-/An-Bindung der Gastsysteme in das jeweils andere Netz ohne Routing

hin- und herschalten.

Das erhöht u.a. die Flexibilität für das Durchspielen verschiedener Penetrationstest-Szenarien in einem virtuellen Test-Labor eines Linux-Hostes beträchtlich. Man kann sich natürlich aber auch etliche Alltags-Szenarien vorstellen, in denen diese Art des Brückenschlags zwischen den Welten nützlich ist. Solange es keine speziellen Sicherheitsanforderungen gibt ….

Viel Spaß nun mit dem Einsatz von Brücken zwischen den Virtualisierungswelten von VMware WS und KVM unter Linux!

KVM – Anlegen eines privaten, isolierten Netzwerks mit virt-manager

Im vorhergehenden Artikel dieses Blogs
Opensuse – manuelles Anlegen von Bridge to LAN Devices (br0, br1, …) für KVM Hosts
hatte ich 2 Arten der Anbindung eines KVM-Gastsystems an die physikalische Umwelt des KVM-Hostes diskutiert. Ich hatte angemerkt, dass es unter KVM/libvirt neben einem direkten Bridging zu einer physikalischen Host-NIC natürlich auch die Möglichkeit gibt, KVM-Gäste an ein sog. “Host-Only-Network” [HON] anzubinden. Intern wird dieses Netzwerk durch eine virtuelle Bridge repräsentiert. Soll man aus dem HON heraus mit der physikalischen Umwelt (LAN) kommunizieren, muss man auf dem KVM-Host Routing zwischen einer bereitgestellten virtuellen Host-NIC der Bridge zu einer physikalischen NIC des Hostes ermöglichen. Letztere leitet die Pakete dann ins LAN.

Unterlässt man das Routing (und/oder filtert man Pakete aus dem HON) auf dem Host, so befinden sich Gastsystem und Host in einem isolierten virtuellen Netz, aus dem nach außen ohne weitere Vorkehrungen nicht kommuniziert werden kann. Dem isolierten Netz können natürlich weitere Gäste beitreten.

Wegen der Nachfrage einer Leserin, zeige ich nachfolgend kurz die Anlage eines virtuellen Host-Only-Netzwerks unter KVM mittels “virt-manager”. Ich setze voraus, dass der “libvirtd”-Daemon läuft.

Man ruft als root “virt-manager” auf und geht im Übersichtsfenster auf “Edit >> Connection Details” und dort auf den Reiter “Virtual Networks”. Dort findet man unter der Übersichtsliste zu bereits vorhandenen Netzwerken, einen Button mit einem “+” Symbol zum Anlegen eines neuen Netzwerks. Ich zeige nachfolgend die Dialogsequenz:

new_network_1

new_network_2

new_network_3

new_network_4

new_network_5

Die Bridge und eine zugehörige Host-NIC tauchen dann auch in der Liste der vorhandenen Netzwerk-Devices auf. Unter Opensuse zeigt das Komamndo “wicked show all” dann etwa ein virbr-Device (virtual bridge – im Beispiel ein “virbr2”):

virbr2          device-unconfigured
      link:     #73, state device-up, mtu 1500
      type:     bridge
      addr:     ipv4 192.168.120.1/24

virbr2-nic      device-unconfigured
      link:     #74, state down, mtu 1500, master virbr2
      type:     tap, hwaddr 52:54:00:c9:bd:24

 
Das neue Netzwerk findet sich dann auch in Form einer XML-Netzwerk-Konfigurations-Datei unter “/etc/libvirt/qemu/networks/host2.xml” wieder:

<!--
WARNING: THIS IS AN AUTO-GENERATED FILE. CHANGES TO IT ARE LIKELY TO BE
OVERWRITTEN AND LOST. Changes to this xml configuration should be made using:
  virsh net-edit host2
or other application using the libvirt API.
-->

<network>
  <name>host2&
lt;/name>
  <uuid>f47c2d04-b1d6-48bf-a6dc-a643d28b38d3</uuid>
  <bridge name='virbr2' stp='on' delay='0'/>
  <mac address='52:54:00:c9:bd:24'/>
  <domain name='host2'/>
  <ip address='192.168.120.1' netmask='255.255.255.0'>
    <dhcp>
      <range start='192.168.120.128' end='192.168.120.254'/>
    </dhcp>
  </ip>
</network>

 
Will man eine solche Host-Only-Bridge von einem KVM-Gast aus nutzen, so muss man für diesen Gast ein entsprechendes “Netzwerk”-Device (NIC) anlegen, das der Bridge zugeordnet wird. “virt-manager” bietet auch hierfür entsprechende grafische Dialoge an. Ich gehe davon aus, dass eine virtuelle Maschine (z.B. namens “kali2”) bereits existiert. Man öffnet deren Konfigurations-Oberfläche durch Doppelklick auf den entsprechenden Eintrag in der Liste aller KVM-Instanzen unter “virt-manager”. Im sich öffnenden Fenster klickt man weiter auf den Button mit dem “i”-Symbol:

new_network_6

Danach taucht das Device auch in der XML-Konfigurationsdatei für den Gast auf – in meinem Beispiel etwa für einen Kali-Gast mit der Datei “/etc/libvirt/qemu/kali.xml” – ich zeige nur den relevanten Ausschnitt:

    <interface type='network'>
      <mac address='52:54:00:0d:3c:8b'/>
      <source network='host2'/>
      <model type='virtio'/>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x0d' function='0x0'/>
    </interface>

 
Danach muss man den Gast neu starten und in ihm natürlich das neu aufgetauchte Netzwerk-Interface manuell konfigurieren – falls man nicht auf DHCP setzt und/oder besondere Einstellungen benötigt. Man merke sich hierzu die MAC-Adresse, um bei mehreren NICs nicht den Überblick zu verlieren! Man achte auch auf das Default-Gateway, wenn Routing über den Host gewünscht ist.

Achtung: Das neue virtuelle Netzwerk des Gastes ist mit “ifconfig”, “ip” oder “wicked” Kommandos erst als ein “vnetN-Device sichtbar, wenn der Gast gestartet und aktiv ist. Das “N” steht dabei für eine fortlaufende Nummer, die vom System (libvirt) vergeben wird. Z.B. taucht unter “wicked show all” dann ggf. ein Device “vnet3” auf:

virbr2          device-unconfigured
      link:     #73, state device-up, mtu 1500
      type:     bridge
      addr:     ipv4 192.168.120.1/24

virbr2-nic      device-unconfigured
      link:     #74, state down, mtu 1500, master virbr2
      type:     tap, hwaddr 52:54:00:c9:bd:24
...
...
vnet3           device-unconfigured
      link:     #17, state up, mtu 1500, master virbr2
      type:     tap, hwaddr fe:54:00:0d:3c:8b

 
Man beachte, dass sowohl die Host-Nic, als auch das Device des Gastes “tap”-Devices sind. Allg. Infos zu tap-devices finden sich hier:
https://www.kernel.org/doc/Documentation/networking/tuntap.txt
https://de.wikipedia.org/wiki/TUN/TAP

Hinweise für Leser, die die Konfiguration lieber manuell und über die Kommandozeile durchführen mögen

Wie man eine virtuelle Bridge auf dem KVM-Host mittels des “brctl”-Kommandos einrichtet, benennt und wie man ihr “tap”-Devices zuordnet, habe ich im Prinzip bereits früher am Beispiel einer direkten Bridge zu einem physikalischen Device beschrieben:
Opensuse – manuelles Anlegen von Bridge to LAN Devices (br0, br1, …) für KVM Hosts
Siehe aber auch hier:
http://www.linux-kvm.org/page/Networking#Configuring_Guest_Networking – Abschnitt (Private Network)

“tap”-Devices kann man manuell und temporär über das Kommando “tunctl” auf dem Host erzeugen.
Siehe etwa :
http://unix.stackexchange.com/questions/86720/can-i-create-a-virtual-ethernet-interface-named-eth0
http://serverfault.com/questions/347895/creating-tun-tap-devices-on-linux
http://www.naturalborncoder.com/virtualization/2014/10/17/understanding-tun-tap-interfaces/
http://blog.elastocloud.org/2015/07/qemukvm-bridged-network-with-tap.html

Die Zuordnung von “tap”-Devices zu einer virtuellen Linux-Bridge erfolgt über das “brctl addif”-Kommando. Nun fehlt also nur noch eine Methode, um einmal erzeugte “tap”-Devices in die Konfiguration eines Gastes einzubinden.

Ich kenne einige Leute, die starten ihre virtuellen Maschinen lieber eigenhändig und über Scripts statt über virt-manager. Dann kann die Netzwerk-Konfiguration des Gastsystems in Form passender Optionsparameter des Kommandos “qemu-system-x86_64” (mit weiteren Optionen für KVM-Unterstützung; s.u.) oder des Kommandos “qemu-kvm” zum Starten eines KVM-Gastes geschehen. Eine Übersicht über diese Möglichkeit findet man hier:
http://qemu-buch.de/de/index.php?title=QEMU-KVM-Buch/_Netzwerkoptionen/_Virtuelle_Netzwerke_konfigurieren
In abgekürzter Form auch hier :
https://bbs.archlinux.org/viewtopic.php?pid=1148335#p1148335
https://bbs.archlinux.org/viewtopic.php?pid=1424044#p1424044

Eine weitere Alternative ist hier beschrieben (s. den Abschnitt zu “Private Networking”):
http://www.linux-kvm.org/page/Networking#Configuring_Guest_Networking

Übrigens: “qemu-kvm” ist auf aktuellen Linux-Systemen meist nur ein kleines Shell-Script-Kommando, dass “qemu-system-x86_64” mit KVM-Hardware-Unterstützungsoptionen aufruft! Siehe zum Unterschied zw. “qemu-system-x86_64” und “qemu-kvm” etwa
http://www.linux-kvm.com/content/qemu-kvm-or-qemu-system-x8664%EF%BC%9F).
Die Optionen des “qemu-kvm”-Kommandos sind z.B. hier beschrieben:
https://www.suse.com/documentation/sles11/book_kvm/data/cha_qemu_running_gen_opts.html
Eine Zusammenfassung zu tap-Devices und verschiedenen Bridging-Varianten gibt auch
https://www.suse.com/documentation/sles11/book_kvm/data/cha_qemu_running_networking.html

Will man die Tools von “libvirt/virt-manager” zum Starten der virtuellen Maschine benutzen, dann kann die “manuelle” Definition von virtuellen NICs für einen KVM-Gastes aber auch mittels des “virsh edit”-Kommandos zur Manipulation des XML-Files für die
Gastkonfiguration durchgeführt werden.
Siehe:
http://serverfault.com/questions/665440/set-up-network-interfaces-in-ubuntu-for-kvm-virtual-machine

In einigen Situationen kann es auch erforderlich sein, den Gast im laufenden Betrieb um ein Netzwerkinterface zu einem neu definierten virtuellen Netz zu erweitern. Informationen hierzu findet man hier:
http://www.linuxwave.info/2014/12/hot-attach-and-hot-detach-network.html
https://kashyapc.fedorapeople.org/virt/add-network-card-in-guest.txt

Opensuse – manuelles Anlegen von Bridge to LAN Devices (br0, br1, …) für KVM Hosts

Wenn man sich mit KVM beschäftigt, taucht u.U. das Thema auf, dass dem einen oder anderen KVM-Gastsystem ggf. ein virtuelles Netzwerk-Device im “bridged mode” zugeordnet werden soll. Dabei wird ein physikalisches Netzwerkdevice (NIC) des KVM-Hostes vom Gastsystem als Ressource für Verbindungen in die Netzwerkumgebung des Hosts genutzt. Das Gastsystem erhält eine IP-Adresse im physikalischen LAN des Hosts. Ich hatte ein solches Vorgehen in einem früheren Artikel als “direktes Bridging zum LAN” bezeichnet, um es von anderen Formen des Einsatzes virtueller Brigdes abzugrenzen. Wir beschreiben in diesem Artikel Elemente einer solchen Bridge-Konfiguration und gehen dann der Frage nach, wie man die Bridge mittels Linux-Kommandos manuell anlegt.

YaST legt virtuelle direkte LAN-Bridges im Rahmen einer Hypervisor-Installation automatisch an

Unter Opensuse unterstützt einen YaST nicht nur bei der Einrichtung von Netzwerk-Devices sondern auch beim grundlegenden Setup eines KVM- oder XEN-Hostes. Im Zuge eines solchen Setups (YaST2 >> “Install Hypervisor and Tools”) legt YaST automatisch für jedes vorhandene und konfigurierte physikalische Device des Hostes – z.B. enp8s0 – eine durch Gäste “direkt” nutzbare Bridge – z.B. br0 – an. Damit auch der Host über die Bridge kommunizieren kann, wird der physikalischen Schnittstelle (hier enp8s0) die IP-Adresse entzogen und dem erzeugten Bridge-Device (z.B. br0) zugeordnet. Siehe hierzu etwa:
http://libvirt.org/ formatdomain.html# elementsNICS
bzw.
http://libvirt.org/ formatdomain.html# elementsNICSBridge

Wozu ist eine direkte LAN-Bridge eines KVM-Hosts eigentlich gut?

Es gibt verschiedene Möglichkeiten KVM- (oder auch XEN-) Gastsysteme mit einer physikalischen LAN-Umgebung des Hosts zu verbinden. Eine “Direct Bridge To Lan” bietet einen bequemen, wenn auch nicht den sichersten Weg, einzelne Gäste in das LAN zu integrieren. Dabei teilen ggf. mehrere KVM Gastsysteme und der Host ein physikalisches Netzwerk-Device zur direkten Paketübermittlung in das physikalische LAN – und darüber wiederum ggf. ins Internet. Derartige direkte Bridges werden typischerweise mit einer Bezeichnung der Form “brN” (N steht für eine Nummer) versehen.

Wir leisten uns zum besseren Verständnis einen kurzen Exkurs: Die nachfolgende Skizze zeigt schematisch zwei unterschiedliche Arten der Anbindung von KVM-Gästen an physikalische Netze.

kvm_br0_2

Das Bild dient nur einer grundsätzlichen Veranschaulichung und ist nicht in jedem Detail ernstzunehmen. Wie der Ethernet-Protokollstapel für verschiedene virtuelle Devices intern tatsächlich verarbeitet wird, sei mal dahingestellt.

Direct Bridge to LAN:
Im unteren Bereich erkennt man den Einsatz eines physikalischen Ethernet-Devices “enp8s0” im Rahmen einer “Direct Bridge to LAN”.

Die Bridge ist zwar ein virtuelles Konstrukt (mit Kernel-Unterstützung); im Sinne der Zeichnung kann man sich aber vorstellen, dass sie wie ein realer Hub/Switch mit diversen Ports versehen ist, an die wiederum physikalische und virtuelle Netzwerkdevices angebunden werden. Ich habe die Ports mit den entsprechenden Bezeichnungen der angebundenen Devices versehen.

Die Bridge übernimmt dabei eine Doppel-Rolle – einerseits entspricht sie einem host-bezogenen Ethernet-Netzwerk-Device mit einer IP-Adresse und garantiert eine entsprechende Paketverarbeitung im Kernel; andererseits subsummiert sie die gesamte Logik zur Ethernet-Paketelimination bzw. -Paket-Verteilung zwischen den virtuellen Ports. Die Bridge behandelt Pakete
normalerweise und im Gegensatz zur physikalischen NIC dabei nicht im “promiscuous mode”, sondern verwirft Pakete, die angeschlossenen Devices nicht zugeordnet werden können. (Für bestimmte Zwecke kann man eine Linux-Bridge aber auch in einen “promiscuous mode” versetzen.)

Die Bridge ist bei bestimmten Einstellungen (sog. ageing-Parameter; s. die “man”-Seiten für das Kommando “brctl”) ferner in der Lage, wie ein Switch zu fungieren und Pakete gezielt und ausschließlich zu den richtigen Target-Ports weiterzuleiten. Das ist der Standard; die Bridge kann aber auch in einen HUB-Modus versetzt werden. Wegen einer weitgehenden Gästeisolation ist das aber selten wirklich wünschenswert.

Das physikalische Interface (enp8s0) wird gezielt mit der Bridge assoziiert (s.u.) und übernimmt in etwa die Funktionen eines physikalischen Uplinks. Die physikalische NIC wird bei der Bridgezuordnung automatisch in den sog. “promiscuous mode” geschaltet, da sie ja Pakete für verschiedene IP- bzw. MAC-Adressen in Empfang nehmen muss.

Die beiden dargestellten KVM-Gastsysteme nutzen die Kapazitäten der physikalischen NIC über die Bridge. Hierzu werden weitere virtuelle Netzwerk-Interfaces (tun/tap-Devices) “vnet0” und “vnet2” verwendet, die in die Konfiguration des Gastsystems aufgenommen und natürlich auch der Bridge zugeordnet werden.

Der Host selbst erhält im Beispiel über die Adresse 192.168.2.1, die br0 zugeordnet wurde, Kontakt zum umliegenden physikalischen LAN. Die Gastsysteme teilen sich die physikalischen Ressource über die Adressen 192.168.2.5 bzw. 192.168.2.6. Sie erscheinen mit diesen Adressen direkt im (physikalischen) LAN und sind (je nach Firewall-Einstellungen) von dort aus auch ansprechbar. Dem physikalischen Interface (enp8s0) selbst wird in dieser Konfiguration keine IP zugeordnet.

Alternative – Host-Only-Bridge und Routing:
Im oberen Bereich der Abbildung ist dagegen eine weitere virtuelle Bridge “virbr0” dargestellt ist, die ein reines “Host-Only Netzwerk” realisiert. Die beiden Gäste wie der Host können über (virtuelle) NICs auch mit einer solchen rein virtuellen Bridge “virbr0” verbunden werden. Das der Bridge ggf. zugeordnete virtuelle Host-Device taucht bei einer Standardvorgehensweise mit KVM oder libvirt-Tools (virt-manager !) normalerweise unter der Bezeichnung “virbr0-nic” auf. Diese Bridge-Variante, die im Grunde wie ein virtueller Switch funktioniert, wird jedoch nicht direkt mit einem physikalischen Device verbunden. Sind die Gastsysteme nur an eine solche “virbr0” angebunden, so erfordert eine Verbindung zur Außenwelt ein (ggf. NAT-) Routing auf dem Host zwischen dem virtuellen Interface “virbr0-nic” des Hostes und einer seiner physikalischen NICs. Eine solche – relativ kontrolliert und gut absicherbare – Situation trifft man häufig auf produktiven KVM-Hosts an.

Hinweis: Die Skizze dient nur der Illustration unterschiedlicher Typen virtueller Bridges – und stellt kein praktisch sinnvolles Szenario dar. Würde man die dargestellte – wenig ressourcenschonende – Situation tatsächlich realisieren, müsste man natürlich aufpassen, keine Netzwerk-Loops durch problematisches Routing zu generieren. Auch die Namensgebung pro Host und Netzwerk sowie die DHCP-Dienste für die beiden Netze müssten strikt getrennt werden. Ein Default Gateway sollte dann nur für eine Netzwerkverbindung definiert sein, hier für das physikalische LAN.

Ich mache ausdrücklich darauf aufmerksam, dass ein direktes Bridging zwar eine einfache Möglichkeit darstellt, Gastsysteme an die physikalische Umwelt anzubinden. Das Ganze ist aus Sicherheitsgründen aber durchaus problematisch – zu denken ist vor allem an ARP- und auch IP-Spoofing durch die Gastsystemnutzer. Der Host muss deshalb mit einer Kombination von iptables- und ebtables-Regeln ausgestattet werden, um die direkte Bridge abzusichern. Auch und
gerade, wenn der Host noch Routing-Aufgaben übernimmt. In produktiven Umgebungen ist eher auf Host-Only Konfigurationen mit/ohne NAT zu setzen.

Auf Test- und Übungssystemen – insbesondere lokalen Pentest-Umgebungen, bei denen Zielsysteme für Übungen im gleichen oder unterschiedlichen virtuellen Segmenten untergebracht werden – vereinfacht eine temporäre Nutzung von gebridgten Host-Devices aber durchaus die regelmäßig erforderliche Aktualisierung von bestimmten Gastsystemen – man sollte nur nicht vergessen, diese Devices unter internen Penetrationstests in seinen virtuellen Netzen abzuklemmen. Für interne Pentest-Übungen zwischen Gästen eines Virtualisierungshosts wird man dagegen Host-Only Bridges – ohne (!) aktiviertes Routing auf dem Host – nutzen, die gegenüber der Umwelt isoliert sind. Aber auch wenn Penetrationstests nach außen gerichtet werden, kann die Nutzung virtuelle Maschinen hinter einer gebridgten NIC sinnvoll sein.

Manuelles Anlegen einer direkten br0-Bridge zu einem physikalischen Device

Eine durchaus interessante Frage ist, ob und wie man unter Opensuse/SLES eine solche Bridge auch manuell anlegen kann – z.B. wenn man sich (möglicherweise über YaST) die Bridge-Konfiguration zerschossen hat. (Z.B. dadurch, dass man in einem Anflug von Unkonzentriertheit der Ethernet-Schnittstelle über YaST irgendwann wieder direkt eine IP-Adresse zugeordnet hat).

Voraussetzung – ein aktivierbares Netzwerk-Interface

Ich möchte in diesem Artikel nicht auf die manuelle Anlage eines physikalischen Ethernet-Netzwerk-Devices selbst eingehen. Hierzu müsste man für moderne Linux-Systeme den aktuellen “udev”- und “systemd”-Mechanismus, das automatische Erkennen und Identifizieren von Devices gem. entspr. Datenbanken, die Bereitstellung von Gerätedateien unter “/dev”, das (automatische) Laden zugehöriger Treiber und auch die Vergabe von “predictable” Device-Namen besprechen (und verstehen). Hier zieht man sich besser auf YaST oder die suse-spezifischen Konfigurationsdateien unter “/etc/sysconfig/network” zurück, in denen bestimmte Parameter wie die IP-Adresse für ein Device permanent hinterlegt werden.

SuSE-spezifische Informationen zur Konfiguration findet man hier:
https://www.suse.com/ de-de/ documentation/ sled11/ book_sle_admin/ data/sec_basicnet_ manconf.html
und hier
https://www.suse.com/ documentation/ sles-12 /book_sle_admin/ data/ sec_basicnet_ manconf.html
Die letzte Doku passt auch gut zu Opensuse 13.2.

Übrigens: Wer verstehen will, wie udev/systemd zu den “predictable names” für Devices gelangen, der lese folgenden Artikel
https://major.io/ 2015/08/21/ understanding-systemds-predictable-network-device-names/

und meine Zusammenfassung unter
Linux-Namensgebung für physikalische Netzwerk-Devices

Ich gehe davon aus, dass es auf unserem KVM-Host z.B. bereits ein aktiviertes Ethernet-Device – in unserem Beispiel “enp8s0” – gibt. Soll es von KVM-Gästen über eine direkte virtuelle Bridge zum LAN genutzt werden, darf ihm beim Systemstart keine IP-Adresse zugeordnet werden. Dies kann man einerseits über “YaST2 >> Netzwerkeinstellungen” für diese NIC einstellen. Alternativ kann man manuell das opensuse-spezifische File “/etc/sysconfig/network/ifcfg-enp8s0” anlegen und mit leeren Konfigurationsanweisungen editieren:

mytux:/etc/sysconfig/network # cat ifcfg-enp8s0 
BOOTPROTO='none'
BROADCAST=''
ETHTOOL_OPTIONS=''
IPADDR=''
MTU=''
NAME=''
NETMASK=''
nNETWORK=''
REMOTE_IPADDR=''
STARTMODE='auto'
DHCLIENT_SET_DEFAULT_ROUTE='yes'
PREFIXLEN=''
mytux:/etc/sysconfig/network # 

Einrichtung einer Bridge mittels des Kommandos brctl

Opensuse 13.2 nutzt im Gegensatz zu früheren Opensuse-Versionen “wicked” zum Starten von NICs etc.. Durch den “compat”-Modus von “wicked” werden aber immer noch die klassischen “ifcfg-…”-Dateien, die unter “/etc/sysconfig/network” definiert sind, unterstützt und ausgelesen.

Leider ist die zugehörige Factory-Doku von SuSE zu diesem Themenkomplex noch nicht ausgereift. Es lohnt sich daher, zunächst ein Blick in die SLES12-Doku zu werfen. Siehe hierzu:
https://activedoc.opensuse.org/ book/ opensuse-reference/ chapter-13-basic-networking
https://www.suse.com/ de-de/ documentation/ sles-12/book_sle_admin/data/sec_basicnet_ manconf.html
Siehe ergänzend zu den bereits erwähnten Quellen auch :
https://activedoc.opensuse.org/ book/ opensuse-virtualization-with-kvm/ chapter-12-running-virtual-machines-with-qemu-kvm

Man kann eine Standard-Bridge “br0” unter Opensuse natürlich mit Hilfe von YaST2 einrichten.
Es lohnt sich aber, das mal manuell zu machen, um entsprechende Befehle und suse-spezifische Konfigurationsdateien kennenzulernen. Der entscheidende Befehl hierzu ist “brctl”, zu dem man sich unbedingt mal die man-pages durchlesen sollte.

Man beachte auch: Das Tool “Network-Manager” unterstützt bislang meines Wissens keine Bridge-Strukturen – im besonderen nicht “direkte” Linux-Bridges zu physikalischen NIC_Devices.

Das nachfolgende Beispiel zeigt die Anlage einer “direkten” Host-Bridge über “brctl addbr” und die Zuordnung zu einem physikalischen Ethernet Device (für direktes Bridging) mittels “brctl addif”. [Hierbei wurde vorausgesetzt, dass dem physikalischen Device bislang keine IP-Adresse zugeordnet wurde.] Die Aktivierung des erzeugten Bridge-Devices erfolgt ganz konventionell über “ifconfig br0 up”.

Der Bridge selbst wird dann mittels “ifconfig” sehr eine IP-Adresse zugeordnet. Dies ist dann die Adresse unter der der (KVM-) Linux-Host selbst nach außen kommunizieren kann. Natürlich hätte man das alles statt mit “ifconfig” auch mit dem Kommando “ip” und seinen Optionen erledigen können. Ich überlasse diese Übung dem Leser.

mytux:~ # ifconfig enp8s0 down 
mytux:~ # ifconfig enp8s0 up 
mytux:~ # brctl addbr br0
mytux:~ # ifconfig br0 up 
mytux:~ # brctl addif br0 enp8s0
mytux:~ # brctl show
mytux:~ # ifconfig br0 192.168.2.1 netmask 255.255.255.0 broadcast 192.168.2.255
mytux:~ # ifconfig br0 

Um diese erreichte Konfiguration permanent machen, muss man noch ein entsprechendes ifcfg-File unter “/etc/sysconfig/network” mit folgendem beispielhaften Inhalt anlegen:

mytux:/etc/sysconfig/network # cat ifcfg-br0
BOOTPROTO='static'
BRIDGE='yes'
BRIDGE_FORWARDDELAY='0'
BRIDGE_PORTS='enp8s0'
BRIDGE_STP='off'
BROADCAST=''
DHCLIENT_SET_DEFAULT_ROUTE='yes'
ETHTOOL_OPTIONS=''
IPADDR='192.168.2.1/24'
MTU=''
NETWORK=''
PREFIXLEN='24'
REMOTE_IPADDR=''
STARTMODE='auto'
NAME=''
mytux:/etc/sysconfig/network #

 
Nicht vergessen sollte man die Definition
eines Default-Gateways für Routing nach außen – im Beispiel etwa über einen Host “192.168.2.10”. Das erfordert eine weitere Textdatei namens “ifroute-br0” unter “/etc/sysconfig/network”. Der Inhalt besteht nur aus einer Zeile “default 192.168.2.10 – br0”:

mytux:/etc/sysconfig/network # cat ifroute-br0 
default 192.168.2.10 - br0 
mytux:/etc/sysconfig/network # 

 
Das ganze Vorgehen lässt sich natürlich für die Anlage weiterer direkter Bridge-Devices zu anderen noch vorhandenen physikalischen Erhernet-Devices wiederholen.

Über Tools zur Einrichtung von KVM-Gastsystemen (wie virt-manager) kann man nun virtuelle NICs der Gastsysteme anlegen und der erzeugten Bridge zuordnen. Ich gehe darauf in einem weiteren kommenden Artikel ein.

Steht die Bridge erst einmal, so kann man ihren Status und aktive, zugeordnete Devices über das Kommando “brctl show br0” ansehen:

mytux # brctl show br0
bridge name     bridge id               STP enabled     interfaces
br0             8000.1c6f653dfd1e       no              enp8s0
                                                        vnet0
                                                        vnet2

 
Der Befehl “wicked show all” zeigt übrigens auch die NIC-Zuordnung zu Bridges und zudem die IP-Adressen an:

mytux: # wicked show all           
lo              up
      link:     #1, state up
      type:     loopback
      config:   compat:/etc/sysconfig/network/ifcfg-lo
      leases:   ipv4 static granted
      leases:   ipv6 static granted
      addr:     ipv4 127.0.0.1/8 [static]
      addr:     ipv6 ::1/128 [static]

enp8s0          enslaved
      link:     #2, state up, mtu 1500, master br0
      type:     ethernet, hwaddr 1d:ff:76:5c:cd:4e
      config:   compat:/etc/sysconfig/network/ifcfg-enp8s0

br0             up
      link:     #4, state up, mtu 1500 
      type:     bridge               
      config:   compat:/etc/sysconfig/network/ifcfg-br0
      leases:   ipv4 static granted    
      addr:     ipv4 192.168.2.1/24 [static]
      route:    ipv4 default via 192.168.2.10

vnet0           device-unconfigured
      link:     #12, state up, mtu 1500, master br0
      type:     tap, hwaddr fe:54:00:cc:dd:ee

vnet1           device-unconfigured
      link:     #13, state up, mtu 1500, master br0
      type:     tap, hwaddr dd:54:00:dd:ee:ff

vnet2           device-unconfigured
      link:     #14, state up, mtu 1500, master br0
      type:     tap, hwaddr fe:54:00:22:33:44

Viel Spaß beim Experimentieren mit virtuellen Bridges!

 

Virtualisierte Netze mit KVM / qemu / libvirt – Hinweise und Links zur systematischen Einarbeitung

Ich befasse mich gerade mit einem Artikel zum Aufbau einer virtuellen Übungsumgebung für Penetrations-Tests unter Linux. Es geht dabei nicht um ressourcenschonendes Hosting – sondern um die Darstellung vollständiger Gastsysteme und ihrer Kommunikation in konfigurierbaren virtuellen Netzen. Die virtuellen Gastsysteme müssen zudem auf einfache Weise wieder im Originalzustand hergestellt oder eingespielt werden können. Eine Lösung mit vorgefertigten Containern (Docker, LXC) ist auf einer Workstation oder gar einem Laptop eher uninteressant; ich setze daher auf KVM/qemu für Linux-Gäste (wie Kali 2.0) und VMware WS/Player für Windows-Gäste.

Mir ist beim Schreiben erneut aufgefallen, dass interessierte Einsteiger es wahrlich schwer haben könnten, sich aus dem Sammelsurium an verstreuten Informationen im Internet einen Überblick über die Einrichtung virtueller Netzwerke unter Linux zu verschaffen. Das Niveau der zugehörigen Internet-Artikel ist uneinheitlich, die Verteilung der Information unübersichtlich. Einige Artikel sind allgmeingültig, andere stark distributionslastig. Das gilt auch für KVM/qemu und das Toolset libvirt/virt-manager.

Die oft kontextbezogene und z.T. überlappende bis synonyme Verwendung der Begriffe “Bridge”, “virtueller Switch” oder “virtuelles Netz” in verschiedenen Artikeln verwirrt Einsteiger möglicherweise. Ähnliches gilt für die Abkürzung “vlan” oder “vLAN”,

  • die einerseits die 802.1Q-basierte Kopplung (bonding) mehrerer NIC-Devices zur Erstellung logischer Segmente in physikalischen LANs bezeichnet (s. https://de.wikipedia.org/ wiki/ Virtual_Local_Area_Network),
  • die andererseits in vielen Artikeln kontextbezogen aber lediglich als Bezeichnung “virtuelles LAN” im Sinne eines virtualisierten Netzwerks auf einem Host mit Virtualisierungsumgebung (KVM/qemu, VMware, etc.) verwendet wird; oft genug ist jedoch auch das Bonding virtueller Netzwerk-Interfaces angesprochen.

Der Artikel
https://en.wikipedia.org/ wiki /Virtual_network
versucht eine Abgrenzung; stellt aber richtigerweise fest, dass auch die Kombination der Konzepte – also 802.q1-basierte vNIC-Kopplung in virtualisierten Netzwerken – möglich ist. Wir betrachten in diesem Artikel “virtualisierte Netzwerke” auf Basis virtueller Bridges/Switches (vBridge/vSwitch) und virtueller Netzwerk-Interfaces (vNICs) in Virtualisierungsumgebungen unter Linux.

Zur Verwirrung mag auch beitragen, dass man bei einer Internet-Recherche zwangsläufig auch über Artikel zu relativ speziellen Netzwerk-Konfigurationsmöglichkeiten stolpert. Etwa zu eine Bridge- oder “vepa”-Konfiguration auf Basis von “macvtap/mcvlan”-Devices, bei der eine direkte Kopplung virtueller mit physikalischen Devices des Hosts unter Nutzung spezieller Eigenschaften von Ethernet-Devices ermöglicht wird. Die richtige Einordnung dieser speziellen Varianten und ihrer Konsequenzen in den Gesamt-Kanon von Möglichkeiten zur Netzwerk-Virtualisierungen dürfte am Anfang sicher nicht leicht fallen.

Ich habe in diesem Artikel deshalb ein paar Links zusammengestellt,

  • deren Lektüre meiner Meinung nach eine gestaffelte und in der Komplexität steigende Lernkurve für die Einrichtung virtueller Netze unter KVM/qemu unterstützen kann;
  • die ich selbst in der Vergangenheit verschiedentlich zu Rate gezogen habe.

Leider habe ich nicht die Zeit, eine eigene Einführung in die Thematik virtualisierter Netze zu schreiben. Aber ich möchte die angegebenen Links doch mit ein paar Anmerkungen flankieren, die Schlüsselpunkte für das grundlegende
Verständnis zusammenfassen.

Vorbemerkungen zur Virtualisierung von Netzwerken unter Linux

Folgende Punkte scheinen mir zum Verständnis virtualisierter Netzwerke und ihrer Interaktion mit physikalischen Netzwerken essentiell zu sein:

Bridges
Linux und/oder unter Linux laufende Virtualisierungsumgebungen erlauben die Definition und Erstellung virtueller (Multiport)-Bridges. Solche Bridges können auf einem Linux-Host auch außerhalb und unabhängig vom libvirt- oder KVM/qemu-System kreiert werden. Eine virtuelle Multiport-Bridge unter Linux entspricht dabei in der üblichen Standardkonfiguration recht gut einem virtuellen Switch (vSwitch). Moderne Virtualisierungsumgebungen wie KVM/qemu erzeugen optimierte vBridges/vSwitches, die eng mit dem Kernel verzahnt sind

Virtuelle Netze
Ein virtueller Switch (z.B. ein “virbr0” unter KVM/qemu) realisiert in Kombination mit einem lokalen DHCP-Dienst die Grundlage für ein entsprechendes “virtuelles Netzwerk” (“vLAN”; hier nicht im Sinne von 802.Q1 verwendet). Ein solches virtuelles Netzwerk

  • kann auf dem Linux-Host ganz unabhängig vom physikalischen Netz existieren,
  • kann einen eigenen, für die angeschlossenen (virtuellen) Systeme gültigen IP-Adressbereich abdecken,
  • kann für den Host selbst über eine (ggf. spezielle) virtuelle Netzwerk-Schnittstelle zugänglich gemacht werden,
  • kann über verschiedene Methoden mit den physikalischen Netzen der Host-Umgebung verbunden oder von ihnen isoliert werden.

Es gibt somit unterschiedliche Varianten der Anbindung an oder der Isolierung virtueller Switches und ihrer zugehörigen virtuellen LANs vom Gastsystem und physikalischen Netzen.

Virtuelle Netzwerkdevices (vNICs)
Man kann einer (virtuellen) Linux-Bridge (bzw. einem virtuellen Switch)

  • rein virtuelle Netzwerk-Devices (vNics) von vitualisierten Gastsystemen,
  • ein virtuelles Netzwerk-Interface des Hosts selbst (“tap”-Device)
  • oder in speziellen Konfigurationen auch ein physikalisches Netzwerk-Interface (pNICs)

zuordnen. Virtuelle NICs für Gastsysteme und für den Virtualisierungs-Host werden über die jeweilige Virtualisierungsumgebung (z.B. KVM/qemu in optimierter Form) oder aber aber auch durch elementare Systemkommandos (wie etwa “tunctl”) bereitgestellt.

Die Bereitstellung virtualisierter vNICs (“tap”-devices) für den Host selbst dient dazu, die Kommunikation des Hosts mit virtuellen Switches und den daran angeschlossenen virtualisierten Systemen zu ermöglichen. So können z.B. Gastsysteme, die hinter einer KVM/qemu-Bridge “virbr0” liegen, vom Host aus über ein artifizielles Device “virbr0-nic”, das an einen Port der Bridge angeschlossen ist, angesprochen werden. Die Erstellung eines solchen vNICs für den Host muss aber (je nach Virtualisierungsumgebung) über spezielle Kommandos herbeigeführt werden.

Unterschiedliche Isolierungsgrade und virtuelle Netzwerk-Modelle
Virtuelle Netze und angeschlossene Gäste können je nach Zuordnung von vNICs und pNICS einen unterschiedlichen Grad der Isolierung gegenüber anderen virtuellen Netzen auf demselben Host, gegenüber dem Host selbst und seinen physikalischen Devices bzw. physikalischen Netzen
einnehmen. Je nach Auslegung des virtuellen Netzes spricht man auch von unterschiedlichen vLAN-Modellen oder vLAN-Varianten.

Anbindung virtueller Netze an physikalische Netze
Methoden zur Anbindung virtueller Netze eines Hosts an physikalische Netze sind u.a.:

  • das Routing zwischen virtuellen und physikalischen NICs auf dem Host,
  • das sog. “direkte Bridging” virtueller Devices von virtualisierten Gastsystemen zu und mit physikalischen Devices des Hosts,
  • die Bereitstellung besonderer virtueller Devices wie “macvtap” (zum direkten Teilen der Ressourcen eines physikalischen Netzwerk-Devices).

Virtuelle Devices von Virtualisierungsgästen werden im Falle der letzten beiden Verfahren direkt im physikalischen Netzsegment adressier- und ansprechbar und teilen sich Ressourcen mit einem vorhandenen physikalischen Interface (wie etwa eth0 oder enp8s0 unter Opensuse).

Im Falle des erstgenannten Verfahrens leitet der Host dagegen Netzwerkpakete, die von virtuellen Systemen und einem vSwitch-Port einer vBridge kommen, über sein eigenes virtuelles vNIC als Router/Gateway zu physikalischen pNICs und physikalischen Netzwerken weiter.
 
Hinzu kommen weitere Spezialverfahren, die z.T. die Definition besonderer virtueller Netzwerk-Devices erfordern.

Routing
Natürlich kann der Host Netzwerkpakete eines Virtualisierungsgastes vG1, der etwa in einem vLAN hinter einer vBridge “virbr0” lokalisiert sein mag, prinzipiell auch zu einem Gast vGx in einem anderen vLAN hinter einer vBridge “virbrx” weiterleiten, wenn er denn (virtuelle) Interfaces zu beiden vBridges besitzt. Natürlich müssen aber entsprechende Routing-Regeln definiert sein und durch paktefilter/Firewalls auch zugelassen werden.
Virtuelle Devices des Hosts (sog. “tap”-Devices), die in virtuelle Switches integriert werden, können einem Routing des Hosts unterworfen werden, müssen es aber nicht. Beispielsweise kann man Routing zwischen virtuellen LANs erlauben, Routing über physikalische Devices nach außen aber unterbinden. Entsprechende Route-Definitionen sind einerseits in die Routing-Tabellen des Hosts aufzunehmen und durch Skripts permanent zu machen, andererseits aber auch in den Paketfilter/Firewall-Einstellungen zu berücksichtigen. Paketfilter-Einstellungen (z.B. über netfilter-iptables/ebtables) können allgemeinere Routing-Regeln des Hosts dabei feingranularer eingrenzen oder bei Bedarf gänzlich aufheben.

“Direktes Bridging” zu einem physikalischen Device des Hosts
Eine besondere Variante des Bridgings ist das weiter oben bereits erwähnte “direkte Bridgen” virtueller Devices von virtualisierten Gastsystemen zu und mit einem physikalischen Device des Hosts. Die virtuellen Devices teilen sich dann das physikalische Device mit dem Host und erscheinen bei entsprechender IP-Adress-Zuordnung direkt im physikalischen Netz.

In manchen Artikeln wird eine entsprechende Bridge auch als eine “Public Bridge” bezeichnet. Leider sprechen einige Internet-Artikel salopp von “Bridging”, wenn sie eigentlich diese spezielle Variante des Aufbaues einer virtuellen Bridge meinen; andere Artikel beziehen “Bridging” dagegegen auf das generelle Verfahren der Erstellung einer virtuellen Bridge als Basis eines virtuellen Netzwerkes. Der Leser muss sich die richtige Interpretation manchmal etwas mühsam aus dem Kontext des Artikels herleiten.

Virtualisierungs-Toolsets
Virtualisierungstools wie “libvirt/virt-manager” unterstützen nicht nur
die Erstellung von Gastsystemen unter verschiedenen Virtualisierungsumgebungen (genauer Hypervisoren wie etwa “KVM/qemu”), sondern auch die Erstellung von (optimierten) virtuellen Bridges, von zugehörigen (optimierten) virtuellen Gast- und Host-Netzwerk-Devices (vNICs), DHCP-Diensten und damit insgesamt von virtuellen Netzen.

Paketfilterung und Firewalling ist auf verschiedenen Ebenen erforderlich
Virtuelle Devices des Host wie auch der virtualisierten Gastsysteme (!) können/müssen ebenso in iptables/ebtables-Regeln einer “netfilter”-basierten Firewall ebenso eingebunden werden wie die vorhandenen physikalischen Devices des Hosts auch. Es kommen u.U. aber spezielle Definitionen und Regeln zum Einsatz. Der Netfilter/iptables-Interpreter des Kernels “versteht” dabei u.a. auch spezielle Anweisungen zur Steuerung (direkt) gebridgter virtueller Devices hinter einem virtuellen Switch, die Signale über das virtuelle Host-Device in die Host-Umgebung senden oder aus dieser empfangen. Ein Präzisierung der iptables/ebtables-Regeln bzgl. der Weiterleitung der Signale von und zu direkt gebridgten Gast-Devices über die jeweilige virtuelle Bridge des Hostes Bridge ist in vielen Fällen dennoch unumgänglich (s. auch den folgenden Punkt). Besonders zu beachten ist, dass KVM/qemu – je nach Konfiguration – initial eigene Default-iptables/ebtables-Regeln etabliert. Diese werden bei Aktivierung eigener Firewall-Systeme durch andere Tools aber u.U. überschrieben. Eine Untersuchung und ein manueller Ausgleich sind oft erforderlich.

Sicherheitsrisiken bei (mehreren) direkten Bridges zu physikalischen Devices
Die “iptables”-Komponente von “netfilter” kümmert sich lediglich um den Pakettransport auf den Ebenen 3/4 des TCP-IP-Protokolls. “iptables” beachtet jedoch nicht den Level 2 (Ethernet, MAC-Adressen) des OSI- oder TCP/IP-Schichtenmodells. Virtuelle Switches können aber durch dieselben Angriffsmuster manipuliert werden, wie reale Switches. ARP Spoofing und ARP-Flooding sind hier zwei Stichworte. Angreifer können mit diesen Methoden die eindeutige Zuordnung von IP-Adressen zu MAC-Adressen bzw. von MAC-Adressen zu Switch-Ports aushebeln. Dadurch ist die Isolierung von Gastsystemen gegeneinander u.U. gefährdet und kann durchbrochen werden.

Sichere Konfigurationen erfordern deshalb neben dem Einsatz von iptables-Regeln auch noch zwingend den Einsatz von ebtables-Regelsätzen. Dies gilt im Besonderen auf Hosts mit direktem Bridging und ggf. mehreren “direkten Bridges” sowie aktiviertem “conntrack” in den iptables-Regeln. Eine saubere Trennung der ankommenden Pakete nach dem Ursprung, der die Verbindung initiierenden Adresse ist u.U. nicht mehr möglich, wenn Angreifer im gleichen LAN-Segment legale und illegale Pakete an dasselbe Target senden.
U.u. können selbst mehrere “direkte Bridges” auf ein und demselben Virtualisierungshost ohne ebtables-Regeln nicht zuverlässig gegeneinander abgeschottet werden. Bestimmte Angriffsverfahren, die virtuelle Bridges/Switches in einen “HUB Modus” zwingen, führen zur Möglichkeit des Mitlesens von Traffic durch einen Gast auf einer anderen Bridge als der, der der Gast zugeordnet ist. “Direkte virtuelle Bridges” sind auf produktiven Hosting-Systemen daher durchaus als potentiell problematisch einzustufen.

Ich hoffe, dem Leser mit diesen Statements ein paar Leitplanken zum besseren Einstieg in die Artikel hinter den nachfolgenden Links gegeben zu haben. Während die grundlegende Einrichtung geeigneter virtueller Bridges/Switches mit dem Gespann “libvirt/virt-manager” sehr schnell und sehr bequem gelingt, erfordern die zuletzt angesprochenen iptables/ebtables-Themen doch eine intensive Beschäftigung mit grundlegenden Netzwerk-Techniken und -Protokollen, netfilter-Regeln und dem ARP-Protokoll. Gerade dieses Feld ist aber ein Eldorado für Pen-Test-Übungen.

Ein paar grundlegende Definitionen zu (virtuellen) Bridges

Es schadet nicht, zu Beginn einer Einarbeitung in virtuelle Netze ein paar grundlegende Dinge zu Bridges/Switches und deren “Abgrenzung” zu rekapitulieren:

 
Wichtig ist zu verstehen, dass ein Switch im Kern einer Multiport-Bridge entspricht.
Es sollte nach der Lektüre der obigen Artikel klar sein, dass auch die Definition virtueller Netzwerke, die im Endeffekt über (virtuelle) Switches gesteuert werden, die Darstellung von virtuellen Multiport-Bridges und zugehöriger Regeln über den Kernel bzw. über vermittelnde und optimierende Virtualisierungs-SW erfordern wird.

Aufsetzen von Bridges unter Linux

An dieser Stelle ist es dann sinnvoll nachzulesen, wie man unter Linux (und spezifischen Linux-Distributionen) ganz allgemein virtuelle Bridges einrichten kann:

 
Ich empfehle hier dringend, sich mit dem Schlüsselkommando “brctl” und seinen Subkommandos auseinanderzusetzen (s. http://linux.die.net/ man/8/ brctl). Um eine Übersicht über angelegte Bridges/Switches und zugeordnete Interface auf einem Host zu erhalten, nutzt man “brctl show”. Dieses Kommando zeigt auch vBridges, zugehörige aktive Host- und Gastinterfaces an, die z.B. direkt mit Hilfe von KVM/qemu oder VMware und nicht manuell mit “brctl” erzeugt wurden.

Erwähnt sei an dieser Stelle auch, dass man ein HUB-ähnliches Verhalten der Bridge erzwingen kann:
http://www.linuxquestions.org/ questions/ linux-networking-3/can-a-bridge-be-configured-to-act-as-hub-not-a-switch-817170/
http://adamdoupe.com/ blog/ 2010/10/22/ configuring-linux-bridge-to-act-as-a-hub/
Dies its für Experimente nützlich zu wissen; ein solches HUB-Verhalten ist aber auf Virtualisierungshosts, auf denen Gäste und ihr Netzwerkverkehr gegeneinander abgeschirmt werden sollen, natürlich zu vermeiden.

libvirt/virt-manager als Interfaces und Tools für die Verwaltung virtueller Netzwerke (verschiedener Hypervisoren)

Der nächste Schritt besteht darin, sich darüber zu informieren, wie man unter Linux die Einrichtung ganzer virtueller Netzwerke auf (relativ) bequeme Weise steuern kann. Man wird zu recht vermuten, dass die Definition virtueller Bridges durch die Bereitstellung von Netzwerk-Schnittstellen für virtuelle Gastsysteme des eingesetzten Hypervisors und auch für den Host ergänzt werden muss. Hinzu kommen Basisdienste wie DHCP für das virtuelle Netzwerk. Das Gespann “libvirt/virt-manager” sind für diese Aufgaben unter Linux die erste Adresse. Das libvirt-Toolset unterstützt mehrere Hypervisoren. Eine “KVM/qemu”-basierte Virtualisierungsumgebung wird dabei zuverlässig unterstützt.

virt-manager liefert ein grafisches Interface zu libvirt, mit dem sich Gastsysteme und Netzwerke (relativ) bequem einrichten lassen. Die Gäste können zudem auf einer elementaren Ebene überwacht, an/ab-geschaltet oder “suspended” werden.

Einführung in libvirt:
https://de.wikipedia.org/ wiki/Libvirt
http://libvirt.org/
Eine Übersicht über die Hypervisoren, die libvirt unterstützt, ist hier zu finden:

https://libvirt.org/ drivers.html

Das erfolgreiche Nutzen von libvirt erfordert das Starten eines Daemons – libvirtd. Ein entsprechender “libvirtd.service” ist auf aktuellen Distributionen in die Target/Unit-Startreihenfolge von “systemd” zu integrieren. Zumindest bei Opensuse 13.2 geschieht dies mit der Installation der Virtualisierungsumgebung unter
“YaST2 >> Virtualisierung >> Install Hypervisor and Tools”
automatisch.

Graphischer Aufsatz “virt-manager” für KVM/qemu, Xen und LXC:

“virt-manager” unterstützt neben der Einrichtung von Gästen vor allem auch die Möglichkeit, komplette virtuelle Netze zu konfigurieren. Hierzu befasse man sich in einem gestarteten “virt-manager”-Fenster mit den Optionen, die man unter dem Menüpunkt
Edit >> Connection Details >> “Virtual Networks”
findet.

Ein weiterer wichtiger Punkt ist, dass “virt-manager” Konfigurationsdateien im XML-Format anlegt. Dies wiederum nutzen weitere libvirt-Programme zur Umsetzung der Virtualisierungsvorgaben über elementare Kommandostrukturen, die an den jeweiligen Hypervisor und seine Kernelintegration angepasst sind. Die XML-Konfigurationsdateien für Gastsysteme bzw. virtuelle Netze sind für KVM/qemu-Umgebungen (meist) in den Verzeichnissen
“/etc/libvirt”, “/etc/libvirt/qemu/” bzw. “/etc/libvirt/qemu/networks”
zu finden.

Neben “virt-manager” gibt es auch CLI-Interface zu libvirt namens “virsh”. Wir kommen weiter unten darauf zurück. Zunächst will ich aber ein paar Links zu einem Hauptthema für die Einarbeitung – nämlich unterschiedlichen virtuellen Netzwerk-Varianten – angeben.

Grundlegende Varianten virtueller Switches und deren Anbindung an physikalische Netze unter libvirt – Schlüsselartikel zur Übersicht

Bei der Auseinandersetzung mit Tools und ihren Möglichkeiten gerät man in Gefahr, vor lauter Bäumen den Wald nicht mehr zu sehen. Bei der Planung virtueller Netze ist es aber vor allem wichtig, sich mit den verfügbaren Varianten für die eigenen Einsatzzwecke auseinanderzusetzen. Dies gilt im besonderen für den Aufbau von Pen-Test-Umgebungen.

Der folgende Schlüssel-Artikel aus dem “libvirt WIKI” fokussiert auf verschiedene grundlegende virtuelle Netzwerkkonfigurationen und die Anbindung zugehörige virtuelle Switches an die physikalische Hostumgebung und physikalische Netze:

http://wiki.libvirt.org/ page/ VirtualNetworking
 
Weitere Strukturdiagramme zur Positionierung der virtuellen LANs findet man hier
http://www.libvirt.org/ archnetwork.html

Zu unterscheiden ist zwischen Konfigurationen, bei denen die Gastsysteme offiziell registrierte IP-Adressen erhalten und solchen, bei denen private Adressen verwendet werden.

In gerouteten Varianten über ein oder mehrere physikalische Interfaces des Hostes nach außen wird oft ein virtuelles (!) Device des Hosts, das wiederum mit einem virtuellen Switch verbunden ist, in geeignete Routing-Definitionen des Hostes eingebunden – mit und ohne NAT. Das ermöglicht Konfigurationen, bei denen die virtuellen Gäste hinter dem virtuellen Switch Zugriff auf das Internet oder aber andere virtuelle Netzwerke des Hostes erlangen können. Durch NAT-Einsatz kann dabei der direkte Zugriff von außen auf einen spezifischen Gast unterbunden werden. Es ist zu beachten, dass NAT auf IP-Ebene iptables-Regeln erfordert. Will man NAT auf MAC-Ebene realisieren, so ist der Einsatz von ebtables notwendig.

Für den Spezialfall einer direkten Bridge zu einem physikalischen Device findet man eine anschauliche Erläuterung grundlegender Prinzipien in folgenden zusammenhängenden Artikeln :
http://www.innervoice.in/ blogs/ 2013/12/02/ linux-bridge-virtual-networking/

http://www.innervoice.in/ blogs/ 2013/12/08/ tap-interfaces-linux-bridge/

Man beachte, dass der Autor nur den genannten Spezialfall genauer beschreibt. Einige der Aussagen gelten jedoch generell, und ich finde die Skizze im zweiten Artikel sehr instruktiv.

XML-Konfigurationsdateien für virtuelle Netzwerke unter libvirt/virt-manager

Die Konfiguration von virtuellen Netzwerken in Form von XML-Dateien, die für KVM/qemu dann unter “/etc/libvirt/qemu/networks” abgelegt werden, ist unter folgendem Link genauer behandelt:

https://libvirt.org/ formatnetwork.html

libvirt nutzt diese Dateien zur Umsetzung der Netzwerk-Konfiguration; virt-manager bietet, wie gesagt, nur ein grafisches Interface zur Erzeugung dieser Dateien.

Es lohnt sich, den genannten Artikel in Gänze durchzulesen:
Durch die beschriebenen Konfigurationsoptionen werden nämlich die unterschiedlichen virtuellen Netzwerk-Varianten noch einmal verdeutlicht (
siehe speziell die Optionen zum Konfigurationsparameter “forward”). Der Leser wird feststellen, dass es neben dem direkten Bridging noch weitere Möglichkeiten gibt, eine Kopplung von virtuellen Netzen an physikalische Host-Devices vorzunehmen – z.B. über mcvtap-Devices. Solche Netze erfordern jedoch Zusatzmaßnahmen, um den Host direkt mit Gästen hinter der Bridge kommunizieren zu lassen. Als Einsteiger würde ich mich deshalb zunächst mit normalem direkten Bridging vertraut machen, bevor man mit mcvtap-Konfigurationen experimentiert. Links zu diesem Spezialthema folgen weiter unten. Der Einsatz von mcvtaps kann aber aus Performance-Gründen interessant sein.

“virsh”-Komponente von libvirt für die Kommandozeile

libvirt kann statt über “virt-manager” auch über die Kommandozeile instruiert werden. Dabei kommt der CLI-Kommandointerpreter “virsh” zum Einsatz. Zur Konfiguration von virtuellen Netzwerken über den “virsh”-CLI-Interpreter siehe:

Zwischenstand und Wiederholung

Es sollte nach der bisherigen Lektüre klargeworden sein, dass den virtuellen Netzwerken Multiport-Bridge-Definitionen für den jeweiligen Hypervisor zugrunde liegen. (Die Bridge-Definitionen erfolgen dabei entweder über Linux “brctl”-Kommandos (s.u.) oder “ip”-Kommandos (iproute2) bzw. direkte Kommandos der Virtualisierungsumgebung für optimierte “vbridges” an den Kernel). Einer (Multiport-) “Bridge” können dann virtuelle und ggf. auch physikalische Devices zugeordnet werden. Die Konfiguration von kernel-optimierten “vBridges” und “vNICs” unter KVM/qemu ist am einfachsten mit “virt-manager” möglich.

Auf einer anschaulichen Ebene kann man sich vorstellen, dass virtuelle Netze über einen virtuellen Switch realisiert werden, der die Kommunikation zwischen mehreren Ports steuert.

Die Repräsentanz des virtuellen Netzes im Host kann über ein spezielles sog. “tap0”-Device gewährleistet werden, das eine virtuelle NIC im Host erzeugt, die wie physikalische NICs auch in iptables/ebtables-Regeln eingebunden werden kann. Diese Device “hängt” dann auch am virtuellen Switch und ermöglicht die Kommunikation des Hosts mit dem virtuellen Gästen hinter dem virtuellen Switch. Zur Einführung in Tap-Devices siehe

https://de.wikipedia.org/ wiki/TUN/TAP

http://backreference.org/ 2010/03/26/ tuntap-interface-tutorial/

Es wurde durch die Lektüre zudem deutlich, dass zwischen “direkten Bridges” zu physikalischen NIC-Devices und rein virtuellen Bridges zu unterscheiden ist. Die Repräsentanz einer rein virtuellen Brigde (bzw. Switches) im Host kann – wie gesagt – über ein spezielles tap-Device erfolgen, das zusätzlich zu erstellen ist. Unter dem aktuellen “libvirt/virt-manager”-Gespann ist dies meist eine zu wählende Option beim Einrichten der virtuellen Netze.

Beachte: Bei direktem Bridging erhält die Bridge selbst die IP-Adresse und nicht das physikalische Device (s.u.).

Also: Einer aufgesetzten Bridge (werden dann je nach Isolierungsgrad

  • situationsgerechte virtuelle Devices der Gäste der jeweiligen Virtualisierungsumgebung zugeordnet,
  • spezielle virtuelle Devices, die das virtuelle Netz für den Host zugänglich machen (mit oder ohne Routing auf dem Host)
    zugeordnet
  • oder aber in bestimmten Fällen des direkten Bridgings zur physikalischen Netzwerkumgebung eben auch physikalische Devices zugeordnet (wobei das physikalische Device dann keine IP erhält, sondern die Bridge (z.B. br0)). Die virtuellen NIC-Devices erscheinen dabei direkt im physikalischen Netzbereich des Hosts.

Virtuelle Netzwerkinterfaces (verschiedener Hypervisoren wie von Spezialfällen) für die Gäste und den Host, die an verschiedene Bridge/Switch-Typen angebunden werden können, werden hier behandelt:

http://qemu-buch.de/ de/ index.php?title=QEMU-KVM-Buch/ _Netzwerkoptionen/ _Virtuelle_Netzwerke_konfigurieren

http://libvirt.org/ formatdomain.html# elementsNICS

Performance-Optimierung
Nutzt man “virt-manager” werden einem je nach gewähltem Netzwerk-Typ unterschiedliche Modelle für virtuelle NICs beim Einrichten der Gäste bzw. auch beim Einrichten des Host-Tap-Interfaces angeboten. Man sollte durchaus mit verschiedenen Modellen experimentieren und die Performance testen. Unter Opensuse 13.1/13.2 habe ich durchweg gute Erfahrungen mit “virtio”-Treibern gemacht.

Hochfahren des Netzes und der virtuellen Gastdevices

Das Hochfahren von Netzwerk-Bridges und das Anlegen zugehöriger virtueller Host-Devices (z.B. virbr0) erfolgt unter aktuellen Distributionen meist über den “Autostart”-Mechanismus von “libvirt”. Man werfe bzgl. der automatisch zu startenden virtuellen Netzwerke einen Blick in das Verzeichnis
“/etc/libvirt/qemu/networks/autostart”.

So zeigt in einem Beispiel ein Opensuse-Host, für den mittels “virt-manager”
eine Bridge “br0” unter Einbindung des physikalische Devices
und eine rein virtuelle Bridge mit angeschlossenem Host-Device
definiert wurden, etwa folgendes nach dem Systemstart (inkl. libvirtd.service):

mytux:~ # brctl show
bridge name     bridge id               STP enabled     interfaces
br0             8000.aabbccddee11       no              enp8s0
virbr0          8000.ccddee112233       yes             virbr0-nic
mytux:~ # ifconfig
br0       Link encap:Ethernet  HWaddr AA:BB:CC:DD:EE:11  
          inet addr:192.168.12.1  Bcast:192.168.12.255  Mask:255.255.255.0
	  ...
enp8s0    Link encap:Ethernet  HWaddr BB:CC:DD:EE:11:AA  
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
	  ....	
virbr0    Link encap:Ethernet  HWaddr CC:DD:EE:11:22:33  
          inet addr:192.168.200.1  Bcast:192.168.200.255  Mask:255.255.255.0
	  ....

 
Welche Gastsysteme übrigens beim Systemstart des Hosts automatisch hochgefahren werden sollen, kann man ebenfalls über “virt-manager” festlegen. Das Ganze ist offenbar in den Start des “libvirtd.service” integriert. Siehe unter:
“/etc/libvirt/qemu/autostart”.

Unter “libvirt” und “KVM/qemu” gilt: Die vNICs von virtuellen Gastsystemen werden erst beim Starten und Einrichten dieser Gastsysteme erzeugt und an die Bridge angebunden. Die virtuellen vNIC-Devices der Gastsysteme sind vorher nicht existent, werden danach aber unter ifconfig und “brctl show” sichtbar!

mytux:~ # brctl show
bridge name     bridge id               STP enabled     interfaces
br0             8000.aabbccddee11       no              enp8s0
                                                        vnet0
virbr0          8000.ccddee112233       yes             virbr0-nic
                                                        vnet1

 
Die erstellten
virtuellen Ethernet-Devices werden unter KVM/qemu mit einem Treibermodell (z.B. virtio) unterlegt und in die startende virtuelle Maschine integriert. Gesteuert wird der gesamte Prozess über entsprechende Start-Kommandos für die virtuellen Maschinen. libvirt/virt-manager überdecken diesen Aufwand netterweise. KVM arbeitet dabei eng mit dem Kernel zusammen.

Manuell könnte man auf Betriebssystem-Ebene einen ähnlichen Vorgang etwa dadurch vollziehen, indem man durch Anwendung des “tunctl”-Befehles (erfordert unter Opensuse die Installation des entsprechenden Paketes!) virtuelle tap-Devices erzeugt, diese einem anschließenden “brctl addif” an die Bridge anbindet und dann dieses Device in einem qemu-Start-Befehl für einen virtuellen Gast benutzt. Das funktioniert auch – nur hat man hierbei keinerlei Optimierungsmöglichkeiten.

Es ist aus meiner Sicht grundsätzlich besser, sich auf die für den Kernel optimierten Devices zu verlassen, die man über die Virtualisierungsumgebung (KVM/qemu) und “virt-manager” als Frontend erzeugt.

Einschub: Pfad der Konfigurationsdateien unter Opensuse

Unter Opensuse findet man die Vorgaben und Startup-Skripts für Bridges (wie br0 etc.) zu physikalischen NIC-Devices unter

/etc/sysconfig/network.

Eine br0-Bridge wird von Opensuse 13.1/13.2 beim Einrichten des Systems als Virtualisierungshost über YaST meist bereits automatisch eingerichtet. Auf diese per “brctl” generierte Bridge kann dann unter “virt-manger” Bezug genommen werden. Dies ist sinnvoll etwa beim Einrichten von Gastsystemen mit einem direkt zum physikalischen Device gebridtem vNIC.

Libvirt bezogene Bridge- und Netzwerk-Definitionen – also solche, bei denen die vBridge direkt über die Virtualisierungsumgebung erzeugt wird – sind unter

/etc/libvirt/

bzw. unter

/etc/libvirt/qemu/networks

zu finden.

Umsetzung virtueller Netze unter “KVM/qemu”

In den Links zu libvirt/virt-manager wurde noch nicht gezeigt, auf was sich “libvirt/virt-manager” bei der Generierung von Netzwerken und zugeordneten virtuellen NICs letztlich stützen. Zudem sollte man sich darüber im klaren sein, dass man über ein wenig Skripting einen “KVM/qemu”-Hypervisor auch direkt ansteuern kann.

KVM ist ein Hypervisor zur Vollvirtualisierung, der als Linux Kernelmodul operiert. Er ist eng mit qemu verzahnt – und stellt eine optimierte Integration der Virtualisierungsumgebung in den Kernel dar. Zu qemu und KVM wird eine erste Einführung hier gegeben:
http://serverfault.com/ questions/208693/ difference-between-kvm-and-qemu

http://www.innervoice.in/ blogs/ 2014/03/10/ kvm-and-qemu/

http://www.linux-kvm.org/ page/Main_Page

Umfangreicher Artikel zur elementaren Konfiguration von qemu-Systemen:

http://qemu-buch.de/ de/index.php? title=QEMU-KVM-Buch/ _Netzwerkoptionen/ _Virtuelle_Netzwerke_konfigurieren

Networking unter KVM/qemu:
http://www.linux-kvm.org/ page/Networking

http://wiki.qemu.org/ Documentation/ Networking

https://en.wikibooks.org/ wiki/QEMU/ Networking

http://wiki.qemu.org/ Documentation/ Networking

https://people.gnome.org/ ~markmc/ qemu-networking.html

Interessant und anregend ist auch ein Studium der praktischen Beispiele, die etwa das Unternehmen Hetzner für seine gehosteten Server-Plattformen diskutiert:
http://wiki.hetzner.de/ index.php/ Kategorie:KVM

Zur Klärung, wie ein qemu-vLan begrifflich zu verstehen ist, siehe:
http://www-01.ibm.com/ support/ knowledgecenter/ linuxonibm/ liaat/ liaatbptap.htm

SLES- und Opensuse-spezifische Informationen zu KVM/qemu gibt es hier:
https://www.suse.com/ documentation/ sles-12/ singlehtml/ book_virt/book_virt.html

https://www.suse.com/ documentation/ sles-12/ singlehtml/ book_virt/ book_virt.html#cha.qemu.running.networking

https://www.suse.com/ documentation/ sles11/ book_kvm/data/ book_kvm.html

https://www.suse.com/ documentation/ sles11/book_kvm/ data/cha_qemu_ running_networking.html

https://activedoc.opensuse.org/ book/ opensuse-virtualization-with-kvm/ chapter-12-running-virtual-machines-with-qemu-kvm

https://activedoc.opensuse.org/ book/ opensuse-virtualization-with-kvm
https://www.howtoforge.com/ virtualization-with-kvm-on-an-opensuse-12.1-server

http://www.vorkon.de/ SU1210.001/ drittanbieter/ Dokumentation/ openSUSE_11.4/manual/ book.kvm.html

Für Debian-spezifische Informationen s. hier:

 
Ubuntu-spezifische Informationen finden sich hier:
https://help.ubuntu.com/ community/ KVMFeisty

NAT-Variante der Anbindung eines virtuellen Netzes an die physikalische Umgebung

Die NAT-Anbindung virtueller Netze an physikalische Netze wird hier diskutiert:
http://wiki.qemu.org/ Documentation/ Networking/NAT

Verschiedene virtuelle Netzwerk-Varianten für Debian-basierte Host-Systeme über die dortige iface-Konfiguration

Debian sammelt die Konfigurationsvorgaben zu Netzwerken und Netzwerk-Devices in einer “iface”-Datei. Siehe zu diesem Thema:

Beispiele für direktes Bridging mit physikalischem Host-Device

http://blog.elastocloud.org/ 2015/07/ qemukvm-bridged-network-with-tap.html
http://www.oneunified.net/ blog/ Virtualization/ BridgeTap.article
http://www.dedoimedo.com/ computers/ kvm-bridged.html
http://hzqtc.github.io/ 2012/02/ kvm-network-bridging.html

Windows-Gastsystem mit direktem Bridging
Artikel für praktische Beispiele mit einem Windows Guest für ein Bridging mit dem physikalischen Host-Device unter Debian-nahen Systemen sind folgende:
http://resources.infosecinstitute.com/ qemu-windows-guest-bridged-networking/

http://resources.infosecinstitute.com/ qemu-windows-guest-networking/

Alternative zum Direct Bridging: Netzwerk mit mcvtap/vepa devices

Leute, die Alternativen zum direkten Bridging suchen, weil sie evtl. Probleme mit der Performance bekommen, werden etvl. mit macvtyp-Devices glücklicher. Hier ein paar Artikel-Links dazu:
http://virt.kernelnewbies.org/ MacVTap

https://libvirt.org/ formatnetwork.html# elementsConnect

https://libvirt.org/ formatnetwork.html# examplesDirect
https://seravo.fi/ 2012/ virtualized-bridged-networking-with-macvtap

https://wiki.math.cmu.edu/ iki/wiki/ tips/ 20140303-kvm-macvtap.html

Netfilter, Firewalling und libvirt

Ich setze hier voraus, dass der Anwender von virtuellen Netzen bereit ist, sich in “netfilter” und seine iptables/ebtables-Komponenten selbst einzuarbeiten. Ich gebe hierzu nur wenige Literaturhinweise an:

https://people.redhat.com/ fcaviggi/ Firewalls.pdf

https://www.frozentux.net/ iptables-tutorial/iptables-tutorial.html
https://wiki.archlinux.org/ index.php/ Iptables

https://wiki.archlinux.org/ index.php/ Simple_stateful_firewall

http://ebtables.netfilter.org/ examples/ basic.html

https://laddumishra.wordpress.com/ 2012/01/19/ mac-filtering-and-bridging-firewalls-in-linuxubuntu/

Grundsätzlich möchte ich Paket-Filterung über eigene iptables/ebtables-Regeln und zugehörige Skripte abgrenzen von den elementaren Möglichkeiten, die “libvirt” bietet. Mein persönlicher Rat ist, sich mit den Möglichkeiten von libvirt zwar auseinanderzusetzen, um Kenntnisse über bestimmte, dort realisierte Standardfilter als
Lehrbeispiele zu erlangen. Sobald man die aber nachvollzogen hat, empfiehlt es sich aus meiner Sicht, diese Regeln in eigene Skripte überzuführen. Gerade beim Aufsetzen von Pen-Testing-Übungsumgebungen hat man dadurch eine wesentlich bessere Kontrolle über das System-Setup. Und was da gilt, kann für Hosting-Umgebungen nicht so falsch sein …

Libvirt bringt bereits eigene elementarste Regeln mit, die je nach Konfiguration der virtuellen Netze bei deren Erstellung mit erzeugt werden. Man überprüfe das mit “iptables -L”.

Wichtig ist zu verstehen, dass diese elementaren Definitionen durch andere Firewall-Tools auf dem eigenen Host abgeschaltet, gelöscht oder überschrieben werden können – auch versehentlich. Auf aktuellen Distributionen ist daher unbedingt die Startreihenfolge von iptables-Tools und die resultierenden Auswirkungen auf physikalische wie virtuelle Netze zu beachten! Für Opensuse-Freunde sind etwa folgende Hinweise angebracht:

Hinweise zur Susefirewall2:
So löscht etwa ein Starten der Susefirewall2 unter Opensuse 13.2/13.1 alle der bei einem vorhergehenden Start des “libvirtd.service” angelegten Regeln. Man beachte auch, dass die Susefirewall2 beim Abschalten Routing auf dem Host automatisch deaktiviert! (Auf diese von Opensuse zur Sicherheit implementiertes Vorgehen, bin ich beim schnellen Aufsetzen von Pentest-Umgebungen schon mehrfach hereingefallen.)

Fakt ist auch, dass die wenigen elementaren Default-Regeln von livirtd das Host-System mit seinen virtualisierten Netzen gegenüber bestimmten Angriffen relativ offen lassen.

Eine erste detailliertere Diskussion von iptables-Regeln für einfache virtuelle Netzwerkkonfigurationen erfolgt hier:
https://libvirt.org/ firewall.html

Dieser Artikel zeigt in seiner Mitte auch, dass es einen ganzen Satz komplexerer, vordefinierter Firewall-Regelsätze gibt, die man einerseits in Netzwerk-Definitionen unter libvirt, ggf. aber auch in eigene iptables/ebtables-Scripts einbeziehen kann. Für letzteres ist ein kleiner Umweg nötig:

Bitte beachtet, dass der Zugriff auf die vordefinierten Regeln unter Opensuse die Installation diverser zusätzlicher (!) Pakete in Ergänzung der Pakete libvirt-daemon, libvirt-client, virt-manager, virt-manager-common erfordert. Am einfachsten ist es jedoch, das Paket “libvirt” zu installieren. Danach “systemctl restart libvirtd.service” und schon funktioniert

mytux:~ # virsh
Welcome to virsh, the virtualization interactive terminal.

Type:  'help' for help with commands
       'quit' to quit

virsh # nwfilter-list
 UUID                                  Name                 
------------------------------------------------------------------
 01c82440-808d-4def-a22f-21848d896cbd  allow-arp           
 154492fb-3198-4de3-8e0c-b0ccbb8f9abc  allow-dhcp          
 60c01c9a-4039-49d9-8ed8-ca55090a6e1a  allow-dhcp-server   
 919ec06f-76bc-4c14-b0dd-5f7cc914edae  allow-incoming-ipv4 
 b3408089-22cf-4b5d-82fa-82769f43a2ed  allow-ipv4          
 c85622ce-1acb-4627-ba5d-cc93476dd5d7  clean-traffic       
 c7865ee0-8dd3-4d2c-98a1-1b3a811322df  no-arp-ip-spoofing  
 81f384b6-5576-4762-a708-33b218868ac6  no-arp-mac-spoofing 
 11fe3e29-2947-45a4-863e-b1e52b923ab2  no-arp-spoofing     
 07123a0e-6b8b-4883-9ef3-49ab88f6cfe2  no-ip-multicast     
 66c36165-89b6-461a-9427-1451b61f697f  no-ip-spoofing      
 ee3e292b-c795-4602-9cd4-3117bbdf36e1  no-mac-broadcast    
 144dd5af-449e-46dd-b9e8-f009d692ce35  no-mac-spoofing     
 ad6e6769-1c8e-40aa-9109-722144841c72  no-other-l2-traffic 
 cfde67c1-aafa-4a0f-8099-34ceb9469197  no-other-rarp-traffic
 18ada8c3-a132-4f89-9999-476f0fa2309e  qemu-announce-self  
 b45e1a74-e5b4-4af1-bd91-1d14bb65f9d8  qemu-announce-self-rarp

virsh # 

r
 
Die zugehörigen XML-Dateien findet man unter “etc/libvirt/nwfilter”.

Um die Sache je nach Blickwinkel noch komplizierter zu machen, erlaubt libvirt das Einbinden dieser Filter und eigener Regel-Sätze in XML-Form in die XML-Konfigurationsdateien zu Netzen/Gästen. Das wird im Detail hier behandelt:
https://libvirt.org/ formatnwfilter.html

Um Zugriff auf die iptables/ebtables-Regeln zu bekommen, kann man kann die Filter dann einfach mal testweise über die Einbindung in libvirt-XML-Dateien zur Anwendung bringen, sich die zugehörigen generierten iptables- und ebtables-Regeln über “iptables -L” und “ebtables -L” anzeigen lassen und später in modifizierter Form in eigene iptables-Scripts integrieren.

Folgender wichtiger Artikel zeigt, wie etwa der wichtige “clean-traffic”-Filter mit Hilfe von ebtables konkret von libvirt implementiert wird (besser im Jahr 2010 wurde):
https://www.redhat.com/ archives/ libvir-list/ 2010-June/ msg00762.html

Security-Themen im Zusammenhang mit virtuellen Netzen

Auch virtuelle Switches können durch dieselben Angriffsmuster manipuliert werden, wie reale Switches. ARP Spoofing und Flooding sind hier die Stichworte. Etliche Probleme der Berücksichtigung von gebridgten Devices bestehen deshalb darin, dass der Layer 2 des OSI-Schichtenmodells von iptables-Regeln ignoriert wird.

http://serverfault.com/ questions/ 457262/ configure-iptables-on-kvm-host-to-block-guest-bridge-traffic

Das führt z.B. bei der Benutzung von conntrack-Regeln unter iptables potentiell zu Schwierigkeiten. Gastsysteme können – z.B. über Ausnutzung des conntrack-Verhaltens und Erzwingen eines HUB- statt Switch-Verhaltens auf der Bridge den eigenen Datenfluss mit dem anderer Gäste mischen.

ARP-Spoofing kann sogar zu Problemen bei 2 getrennten Bridges führen. Siehe hierzu folgende Diskussionen:

http://patchwork.ozlabs.org/ patch/29319/

https://bugzilla.redhat.com/ show_bug.cgi?id=512206

http://serverbugs.com/ Question.aspx? q=-conntrack-tracking-private-TCP-sessions-between-VMs&i=593650
und entsprechende Teile von

http://blog.klauskiwi.com/ wp-content/ uploads/ 2010/08/ KVM-Security_en.pdf

Will man iptables auf direkten Bridges zu physikalischen Devices nutzen, so sind “physdev”-Definitionen erforderlich:
Siehe
http://people.netfilter.org/ kadlec/ ipset/ iptables.man.html
und dort den Abschnitt zu “physdev”.

Siehe auch:

und dort S.504 bis S.517.

Es wurde jedoch aus Sicherheitsgründen vielfach empfohlen, iptables auf direkt gebridten Hosts abzuschalten. Siehe hierzu neben den obigen Artikeln auch die Seiten 3 und 4 des folgenden Artikels:

https://www-01.ibm.com/ support/ knowledgecenter/ linuxonibm/liaat/ liaatsecurity_pdf.pdf
und

https://www-01.ibm.com/ support/ knowledgecenter/ linuxonibm/ liaat/ liaatkvmsecnetfilter.htm

https://wiki.archlinux.org/ index.php/ QEMU#Bridged_networking_ using_qemu-bridge-helper

http://wiki.libvirt.org/ page/ Networking – s. dort den Bereich über (direct) “bridged networking”

http://www.cyberciti.biz/ faq/ debian-ubuntu-linux-kvm-guest-shared-physical-network/

https://docs.fedoraproject.org/ en-US/ Fedora/13/ html/ Virtualization_Guide/ sect-Virtualization-Network_ Configuration-Bridged_ networking_with_libvirt.html

Siehe jedoch als Gegenmeinung :

http://netfilter.vger.kernel.narkive.com/ M0WsSp2h/ security-validity-of-iptables-in-multi-bridge-environment

Was immer ihr davon haltet, ich meine, dass Abhilfe generell durch die zusätzliche Etablierung von restriktiven ebtables-Regeln möglich ist. Die schaden zumindest nicht und helfen auch bzgl. ARP-Spoofing.

Zum Thema des ARP-Spoofings siehe u.a.

https://www.berrange.com/ posts/ 2011/10/03/ guest-mac-spoofing-denial-of-service-and-preventing-it-with-libvirt-and-kvm/

http://www.admin-magazine.com/ Articles/ Arp-Cache-Poisoning-and-Packet-Sniffing

sowie

http://www-01.ibm.com/ support/ knowledgecenter/ linuxonibm/liaat/ liaatkvmsecmac.htm

http://www.linux-magazin.de/ Ausgaben/2004/ 12/ Zugbruecke

http://www.linux-magazin.de/ Ausgaben/2004/12/ Zugbruecke/ %28offset%29/6

Etwas Off-Topic: ARP-Spoofing und Flooding wird übrigens auch als Problem für Docker-Implementierungen diskutiert:

https://nyantec.com/ en/ 2015/03/20/ docker-networking-considered-harmful/

http://arxiv.org/ pdf/1501.02967.pdf

Die Argumente in der letzten Untersuchung gelten meiner Meinung nach für KVM-Systeme analog und belegen, dass es wichtig ist, ebtables-Regeln zu etablieren!

Bridging und ebtables-Regeln sind in genereller Form hier diskutiert:

http://ebtables.netfilter.org/ misc/brnf-faq.html

http://ebtables.netfilter.org/ br_fw_ia/ br_fw_ia.html

http://ebtables.netfilter.org/ documentation/ bridge-nf.html

http://ebtables.netfilter.org/ misc/ brnf-faq.html

Ein kleines Fallbeispiel, dass erneut die Bedeutung von ebtables aufzeigt, ist hier besprochen:
http://serverfault.com/ questions/ 607224/ iptables-matching-packets-for-bridged-interface

Ich hoffe, ich habe mit diesen Lektüre-Hinweisen dem einen oder anderen
einen kleinen Fahrplan für das Erforschen der Tiefen und Untiefen virtueller Netze und Linux und speziell mit KVM/qemu an die Hand gegeben.