Linux bridges – can iptables be used against MiM attacks based on ARP spoofing ? – II

In the last article
Linux bridges – can iptables be used against MiM attacks based on ARP spoofing ? – I
we saw that iptables rules with options like

-m physdev --physdev-in/out device

may help in addition to other netfilter tools, which work on network level 2, to block redirected traffic to a "man in the middle system" on a bridge.

Tools like FWbuilder support the creation of such "physdev"-related rules as soon as bridge devices are marked as bridged in the interface definition process for the firewall host. However, we have also seen that we need to bind IP addresses to certain bridge ports. This in turn requires knowledge about a predictable IP-to-port-configuration. Such a requirement may be an obstacle for using iptables in scenarios with many virtual guests on one or several Linux bridges of a virtualization host as it reduces flexibility for automated IP address assignment.

Before we discuss administrative aspects in a further article, let us expand our iptables rules to a more complex situation:
In this article we discuss a scenario with 2 linked Linux bridges "virbr4" and "virbr6" plus the host attached to "virbr4". This provides us with a virtual infrastructure for which we need to construct a more complex, but more general set of rules in comparison to what we discussed in the last article. We will look at the required rules and their order. Testing of the rules will be done in a forthcoming article.

Two coupled bridges and the host attached via veth devices

You see my virtual bridge setup in the following drawing.

(Note for those who read the article before: I have exchanged the picture to make it consistent with a forthcoming article. The port for kali2 has been renamed to "vk42").

bridge3

The small blue rectangles inside the bridges symbolize standard Linux tap devices - whereas the RJ45 like rectangles symbolize veth devices. veth pairs deliver a convenient way on a Linux system to link bridges and to attach the host to them in a controllable way. As a side effect one can avoid to assign the bridge itself an IP address. See:
Fun with veth devices, Linux virtual bridges, KVM, VMware – attach the host and connect bridges via veth

In the drawing you recognize our bridge "virbr6" and its guests from the last article. The new bridge "virbr4" is only equipped with one guest (kali2); this is sufficient for our test case purposes. Of course, you could have many more guests there in realistic scenarios. Note that attaching certain groups of guests to distinct bridges also occurs in physical reality for a variety of reasons.

Two types of ports

For the rest of this article we call ports as vethb2 on virbr6, vethb1 and vmh1 on virbr4 "border ports" of their respective bridges. Such border ports

  • connect a bridge to another bridges,
  • connect a bridge to the virtualization host
  • or connect the bridge to hosts on external real Ethernet segments.

We remind the reader that it always is the perspective of the bridge that decides about the INcoming or OUTgoing direction of an Ethernet packet via a specific port when we define IN/OUT iptables rules.

Therefore, packets crossing a border port in the IN direction always come from outside the bridge. Packets leaving the port OUTwards may however come from guests of the bridge itself AND from guests outside other border ports of the very same bridge.

In contrast to border ports we shall call a port of a bridge with just one defined guest behind it a "guest port". [In our test case the bridge connection of guests is realized with tap devices because this is required by KVM. In the case of LXC and docker containers we would rather see veth-pairs.]

Multiple bridges on one host - how are the iptables rules probed?

Just from looking at the sketch we see a logical conundrum, which has a significant impact on the setup of iptables rules on a host with multiple bridges in place:

A packet created at one of the ports may leave the bridge where it has been created and travel in and through a neighboring bridge via border ports. But when and how are port related rules tested as the packet travels - lets e.g. say from kali5 to the guest at "vnet0" or to the host at "vmh2"?

  • Bridge for bridge - IN-Port-rules, then OUT-port-rules on the same first bridge => afterwards IN-port-rules/OUT-port-rules again - but this time for the ports of the next entered bridge?
  • Or: iptables rules are checked only once, but globally and for all bridges - with some knowledge of port-MAC-relations of the different bridges included?

If the latter were true just one passed ACCEPT rule on one single bridge port would lead to an overall acceptance of a packet despite the fact that the packet possibly will cross further bridges afterward. Such a behavior would seem unreasonable - but who knows ...

So the basic question is:

After having been checked on a first bridge, having been accepted for leaving one border port of this first bridge and then having entered a second linked bridge via a corresponding border port - will the packet be checked again against all denial and acceptance rules of the second bridge? Will the packet with its transportation attributes be injected again into the whole set of iptables rules?

It is obvious that the answer would have an impact of how we need to define our rules. Especially during port flooding, which we already observed in the tests described in our first article.

Tests of the order of iptables rules probing for ports of multiple bridges on a packet's path

As a first test we do something very simple: we define some iptables rules for ICMP pings formally in the following logical order: We first deny a passage through vethb1 on virbr4 before we allow the packet to pass vethb2 on virbr6:

bridge vibr4 rule 15:  src 192.168.50.14, dest 192.168.50.1 - ICMP IN vethb1 => DENY
bridge vibr6 rule 16:  src 192.168.50.14, dest 192.168.50.1 - ICMP OUT vethb2 => ALLOW

 
and then we test the order of how these rules are passed by logging them.

To avoid any wrong or missing ARP information on the involved guest/host systems and missing MAC-port-relations in the "forward databases" [FWB] of the bridges we first clear any iptables rules and try some pings before sending ping packets. Then we activate the rules and get for ping packets sent from kali4 to the host:

2016-02-27T12:09:33.295145+01:00 mytux kernel: [ 5127.067043] RULE 16 -- ACCEPT IN=virbr6 OUT=virbr6 PHYSIN=vk64 PHYSOUT=vethb2 MAC=96:b0:a9:7c:73:7d:52:54:00:74:60:4a:08:00 SRC=192.168.50.14 DST=192.168.50.1 LEN=84 TOS=0x00 PREC=0x00 TTL=64 ID=22031 DF PROTO=ICMP TYPE=8 CODE=0 ID=1711 SEQ=1 
2016-02-27T12:09:33.295158+01:00 mytux kernel: [ 5127.067062] RULE 15 -- DENY IN=virbr4 OUT=virbr4 PHYSIN=vethb1 PHYSOUT=vmh1 MAC=96:b0:a9:7c:73:7d:52:54:00:74:60:4a:08:00 SRC=192.168.50.14 DST=192.168.50.1 LEN=84 TOS=0x00 PREC=0x00 TTL=64 ID=22031 DF PROTO=ICMP TYPE=8 CODE=0 ID=1711 SEQ=1 
2016-02-27T12:09:34.302140+01:00 mytux kernel: [ 5128.075040] RULE 16 -- ACCEPT IN=virbr6 OUT=virbr6 PHYSIN=vk64 PHYSOUT=vethb2 MAC=96:b0:a9:7c:73:7d:52:54:00:74:60:4a:08:00 SRC=192.168.50.14 DST=192.168.50.1 LEN=84 TOS=0x00 PREC=0x00 TTL=64 ID=22131 DF PROTO=ICMP TYPE=8 CODE=0 ID=1711 SEQ=2 
2016-02-27T12:09:34.302153+01:00 mytux kernel: [ 5128.075056] RULE 15 -- DENY IN=virbr4 OUT=virbr4 PHYSIN=vethb1 PHYSOUT=vmh1 MAC=96:b0:a9:7c:73:7d:52:54:00:74:60:4a:08:00 SRC=192.168.50.14 DST=192.168.50.1 LEN=84 TOS=0x00 PREC=0x00 TTL=64 ID=22131 DF PROTO=ICMP TYPE=8 CODE=0 ID=1711 SEQ=2

 
Now we do a reverse test: We allow the incoming direction over port vk64 of virbr6 before we deny the incoming package over vethb1 on virbr4:

bridge vibr6 rule :  src 192.168.50.14, dest 192.168.50.1 - IN vk64 => ALLOW
bridge vibr4 rule :  src 192.168.50.14, dest 192.168.50.1 - IN vethb1 => DENY

 
We get

2016-02-27T14:02:32.821286+01:00 mytux kernel: [11913.962828] RULE 15 -- ACCEPT IN=virbr6 OUT=virbr6 PHYSIN=vk64 PHYSOUT=vethb2 MAC=96:b0:a9:7c:73:7d:52:54:00:74:60:4a:08:00 SRC=192.168.50.14 DST=192.168.50.1 LEN=84 TOS=0x00 PREC=0x00 TTL=64 ID=21400 DF PROTO=ICMP TYPE=8 CODE=0 ID=2104 SEQ=1 
2016-02-27T14:02:32.821307+01:00 mytux kernel: [11913.962869] RULE 16 -- DENY IN=virbr4 OUT=virbr4 PHYSIN=vethb1 PHYSOUT=vmh1 MAC=96:b0:a9:7c:73:7d:52:54:00:74:60:4a:08:00 SRC=192.168.50.14 DST=192.168.50.1 LEN=84 TOS=0x00 PREC=0x00 TTL=64 ID=21400 DF PROTO=ICMP TYPE=8 CODE=0 ID=2104 SEQ=1 
2016-02-27T14:02:33.820257+01:00 mytux kernel: [11914.962965] RULE 15 -- ACCEPT IN=virbr6 OUT=virbr6 PHYSIN=vk64 PHYSOUT=vethb2 MAC=96:b0:a9:7c:73:7d:52:54:00:74:60:4a:08:00 SRC=192.168.50.14 DST=192.168.50.1 LEN=84 TOS=0x00 PREC=0x00 TTL=64 ID=21494 DF PROTO=ICMP TYPE=8 CODE=0 ID=2104 SEQ=2 
2016-02-27T14:02:33.820275+01:00 mytux kernel: [11914.962987] RULE 16 -- DENY IN=virbr4 OUT=virbr4 PHYSIN=vethb1 PHYSOUT=vmh1 MAC=96:b0:a9:7c:73:7d:52:54:00:74:60:4a:08:00 SRC=192.168.50.14 DST=192.168.50.1 LEN=84 TOS=0x00 PREC=0x00 TTL=64 ID=21494 DF PROTO=ICMP TYPE=8 CODE=0 ID=2104 SEQ=2 

 
So to our last test:

bridge vibr6 rule :  src 192.168.50.14, dest 192.168.50.1 - IN vk64 => ALLOW
bridge vibr6 rule :  src 192.168.50.14, dest 192.168.50.1 - IN vethb2 => DENY
bridge vibr4 rule :  src 192.168.50.14, dest 192.168.50.1 - IN vethb1 => DENY

 
We get:

2016-02-27T14:26:08.964616+01:00 mytux kernel: [13331.634200] RULE 15 -- ACCEPT IN=virbr6 OUT=virbr6 PHYSIN=vk64 PHYSOUT=vethb2 MAC=96:b0:a9:7c:73:7d:52:54:00:74:60:4a:08:00 SRC=192.168.50.14 DST=192.168.50.1 LEN=84 TOS=0x00 PREC=0x00 TTL=64 ID=27122 DF PROTO=ICMP TYPE=8 CODE=0 ID=2218 SEQ=1 
2016-02-27T14:26:08.964633+01:00 mytux kernel: [13331.634232] RULE 17 -- DENY IN=virbr4 OUT=virbr4 PHYSIN=vethb1 PHYSOUT=vmh1 MAC=96:b0:a9:7c:73:7d:52:54:00:74:60:4a:08:00 SRC=192.168.50.14 DST=192.168.50.1 LEN=84 TOS=0x00 PREC=0x00 TTL=64 ID=27122 DF PROTO=ICMP TYPE=8 CODE=0 ID=2218 SEQ=1 
2016-02-27T14:26:09.972621+01:00 mytux kernel: [13332.643587] RULE 15 -- ACCEPT IN=virbr6 OUT=virbr6 PHYSIN=vk64 PHYSOUT=vethb2 MAC=96:b0:a9:7c:73:7d:52:54:00:74:60:4a:08:00 SRC=192.168.50.14 DST=192.168.50.1 LEN=84 TOS=0x00 PREC=0x00 TTL=64 ID=27347 DF PROTO=ICMP TYPE=8 CODE=0 ID=2218 SEQ=2 
2016-02-27T14:26:09.972637+01:00 mytux kernel: [13332.643605] RULE 17 -- DENY IN=virbr4 OUT=virbr4 PHYSIN=vethb1 PHYSOUT=vmh1 MAC=96:b0:a9:7c:73:7d:52:54:00:74:60:4a:08:00 SRC=192.168.50.14 DST=192.168.50.1 LEN=84 TOS=0x00 PREC=0x00 TTL=64 ID=27347 DF PROTO=ICMP TYPE=8 CODE=0 ID=2218 SEQ=2 

 

Intermediate conclusions

We can conclude the following points :

  • A packet is probed per bridge - in the order of how multiple bridges of the host are passed by the packet.
  • An ALLOW rule for a port on one bridge does not overrule a DENY rule for a port on a second bridge which the package may pass on its way.
  • A packet is tested both for IN/OUT conditions of a FORWARD rule for each bridge it passes.
  • If we split IN and OUT rules on a bridge (as we need to do within some tools as FWbuilder) than we must probe the OUT rules first to guarantee the prevention of illegal packet transport.

For the rest of the article we shall follow the same rule we already used as a guide line in the previous article: Our general iptables policy is that a packet will be denied if it is not explicitly accepted by one of the tested rule.

Blocking of border ports in port flooding situations

During our tests in the last article we have seen that port flooding situations may occur - depending among other things on the "setaging" parameter of the bridge and the resulting deletion of stale entries in the "Forward Database" [FWD] of a bridge. Flooding of veth based border ports may be critical for packet transmission and may have to be blocked in some cases:

E.g. it would be unreasonable to transfer packets logically meant for hosts beyond port vmh1 of virbr4 over vethb1/2 to virbr6. We would stop such packets already via OUT DENY rules for vethb1:

bridge vibr4 rule :  src "guest of virbr4", dest "no guest of virbr6" - OUT vethb1 => DENY

 

Rules regarding packets just crossing and passing a bridge

Think about a bridge "virbrx" linked on its both sides to two other bridges "virbr_left" and "virbr_right". In such a scenario packets could arrive at virbrx from bridge virbr_right, enter the intermediate bridge virbrx and leave it at once again for the third bridge virbr_left - because it never was destined to any guest of bridge virbrx.

For such packets we need at least one ACCEPT rule om virbrx - either on the IN direction of the border port of virbrx against virbr_right or on the OUT direction at the border port to virbr_left.

Again, we cling to our policy of the last article:
We define DENY rules for outgoing packets at all ports - also for border ports - and put these DENY rules to the top of the iptables list; then we define DENY rules for ports which are passed in IN direction; only after that we define ACCEPT rules for incoming packets for all ports of a bridge - including border ports - and set these rules below/after the DENIAL rules. This should provide us with a consistent handling also of packets crossing and passing bridges.

Grouping of guests/hosts

From looking at the drawing above we also understand the following point: In order to handle packets at border ports connecting two bridges we have the choice to block packets at either border port - i.e. before the OUTgoing port passage on the first bridge OR before the INcoming port passage on the second. We shall do the blocking at the port in the packets OUTgoing direction. Actually, there would be no harm in setting up reasonable DENY rules for both ports. Then we would safely cover all types of situations.

Anyway - we also find that the rules for border ports require a certain grouping of the guests and hosts:

  • Group 1: Guests attached to the bridge of the border port.
  • Group 2: Guests on the IN side of the border port of a bridge - i.e. the internal side of the bridge. This group includes Group 1 plus external guests of further bridges beyond other border ports of the very same bridge.
  • Group 3:Guests on the outgoing side of a border port - i.e. the side to the next connected bridge. This group contains hosts of Group 1 for the next connected bridge and/or groups of external hosts on the OUT side of all other border ports of the connected bridge.

These groups can easily be formed per bridge by tools like FWbuilder. Without going into details: Note that FWbuilder handles the overall logical OR/AND switching during a negation of multiple groups of hosts correctly when compiling iptables rules.

Overall rules order in case of multiple and connected bridges

Taking into account the results of the first article in this series I suggest the following order of iptables rules:

  • We first define OUT DENY rules for all guest ports of all bridges - with ports grouped by bridges just to keep the overview. These rules are the most important ones to prevent ARP spoofing and a resulting packet redirection.
  • We then define all OUT DENY rules for border ports of all bridges - first grouped by bridges and then per bridge and ports grouped by hosts for the OUTgoing direction. These rules cover also port flooding situations with respect to neighboring linked bridges.
  • We then define IN DENY rules for incoming packets over border ports. These rules may in addition to the previous rules prevent implausible packet transport.
  • Now we apply OUT DENY and IN DENY rules for Ethernet devices on the virtualization host. Such rules must must not be forgotten and can be placed herein the rules' sequence.
  • We then define IN ACCEPT rules on individual guest ports - ports again grouped by bridges.
  • We eventually define IN ACCEPT rules on bridge border ports - note that such rules are required for packets just passing an intermediate bridge without being destined to a guest of the bridge.
  • IN ACCEPT rules for the virtualization hosts's Ethernet interfaces must not be forgotten and can be placed at the end.

How does that look like in FWbuilder?

Before looking at the pics note that we have defined the host groups

  • br6_grp to contain kali3, kali4, kali5,
  • br4_grp to contain only kali2,
  • ext_grp to contain the host and some external web server "lamp".

With this we get the following 7 groups of rules:

full_1

full_2

full_3

full_4

full_5

full_6

full_7

Despite the host grouping : this makes quite a bunch of rules! But yet not uncontrollable ...

Enough for today. I hope that tests being performed in a third article of this series will not proof me wrong. I am confident .... See
Linux bridges – can iptables be used against MiM attacks based on ARP spoofing ? – III

Fun with veth devices, Linux virtual bridges, KVM, VMware – attach the host and connect bridges via veth

Typically, virtual "veth" Ethernet devices are used for connecting virtual containers (as LXC) to virtual bridges like an OpenVswitch. But, due to their pair nature, veth" devices promise flexibility also in other, much simpler contexts of virtual network construction. Therefore, the objective of this article is to experiment a bit with "veth" devices as tools to attach the virtualization host itself or other (virtual) devices like a secondary Linux bridge or a VMware bridge to a standard Linux bridge - and thus enable communication with and between virtualized guest systems.

Motivation

I got interested in "veth"-devices when trying to gain flexibility for quickly rebuilding and rearranging different virtual network configurations in a pen-testing lab on Linux laptops. For example:

  • Sometimes you strongly wish to avoid giving a Linux bridge itself an IP. Assigning an IP to a Linux bridge normally enables host communication with KVM guests attached to the bridge. However, during attack simulations across the bridge the host gets very exposed. In my opinion the host can better and more efficiently be protected by packet filters if it communicates with the bridge guests over a special "veth" interface pair which is attached to the bridge. In other test or simulation scenarios one may rather wish to connect the host like an external physical system to the bridge - i.e. via a kind of uplink port.
  • There are scenarios for which you would like to couple two bridges, each with virtual guests, to each other - and make all guests communicate with each other and the host. Or establish communication from a guest of one Linux bridge to VMware guests of a VMware bridge attached to yet another Linux bridge. In all these situations all guests and the host itself may reside in the same logical IP network segment, but in segregated parts. In the physical reality admins may have used such a segregation for improving performance and avoiding an overload of switches.
  • In addition one can solve some problems with "veth" pairs which otherwise would get complicated. One example is avoiding the assignment of an IP address to a special enslaved ethernet device representing the bridge for the Linux system. Both libvirt's virt-manager and VMware WS's "network editor" automatically perform such an IP assignment when creating virtual host-only-networks. We shall come back to this point below.

As a preparation let us first briefly compare "veth" with "tap" devices and summarize some basic aspects of Linux bridges - all according to my yet limited understanding. Afterwards, we shall realize a simple network scenario as for training purposes.

vtap vs veth

A virtual "tap" device is a single point to point device which can be used by a program in user-space or a virtual machine to send Ethernet packets on layer 2 directly to the kernel or receive packets from it. A file descriptor (fd) is read/written during such a transmission. KVM/qemu virtualization uses "tap" devices to equip virtualized guest system with a virtual and configurable ethernet interface - which then interacts with the fd. A tap device can on the other side be attached to a virtual Linux bridge; the kernel handles the packet transfer as if it occurred over a virtual bridge port.

"veth" devices are instead created as pairs of connected virtual Ethernet interfaces. These 2 devices can be imagined as being connected by a network cable; each veth-device of a pair can be attached to different virtual entities as OpenVswitch bridges, LXC containers or Linux standard bridges. veth pairs are ideal to connect virtual devices to each other.

While not supporting veth directly, a KVM guest can bridge a veth device via macVtap/macVlan (see https://seravo.fi/2012/virtualized-bridged-networking-with-macvtap.

In addition, VMware's virtual networks can be bridged to a veth device - as we shall show below.

Aspects and properties of Linux bridges

Several basic aspects and limitations of standard Linux bridges are noteworthy:

  • A "tap" device attached to one Linux bridge cannot be attached to another Linux bridge.
  • All attached devices are switched into the promiscuous mode.
  • The bridge itself (not a tap device at a port!) can get an IP address and may work as a standard Ethernet device. The host can communicate via this address with other guests attached to the bridge.
  • You may attach several physical Ethernet devices (without IP !) of the host to a bridge - each as a kind of "uplink" to other physical switches/hubs and connected systems. With the spanning tree protocol activated all physical systems attached to the network behind each physical interface may communicate with physical or virtual guests linked to the bridge by other physical interfaces or virtual ports.
  • Properly configured the bridge transfers packets directly between two specific bridge ports related to the communication stream of 2 attached guests - without exposing the communication to other ports and other guests. The bridge may learn and update the relevant association of MAC addresses to bridge ports.
  • The virtual bridge device itself - in its role as an Ethernet device - does not work in promiscuous mode. However, packets arriving through one of its ports for (yet) unknown addresses may be flooded to all ports.
  • You cannot bridge a Linux bridge directly by or with another Linux bridge (no Linux bridge cascading). You can neither connect a Linux bride to another Linux bridge via a "tap" device.

In combination with VMware (on a Linux host) some additional aspects are interesting:

  • A virtual Linux bridge in its role as an Ethernet device can be bridged by non-native Linux bridges - e.g. by VMware bridges - and thereby be switched into promiscuous mode. The VMware (master) bridge then uses a Linux bridge as an attached (slave) device. This type of bridge cascading may have security impacts: packets arriving via a physical port at the Linux bridge and being destined to VMware guests connected to their VMware master bridge may become visible at the Linux bridge ports. See:
    VMware WS – bridging of Linux bridges and security implications
  • The "vmnet"-Ethernet device related to a VMware bridge on a Linux host can be attached (without an IP-address) to a Linux bridge thus enabling communication between VMware guests attached to a VMware bridge and KVM guests connected to the Linux bridge. However, as this is an uplink like situation we must get rid of any IP address assigned to the "vmnet"-Ethernet device.
  • A test scenario

    I want to realize the following test scenario with the help of veth-pairs:

    Our virtual network shall contain two coupled Linux bridges, each with a KVM guest. The host "mytux" shall be attached via a regular bridge port to only one of the bridges. In addition we want to connect a VMware bridge to one of the Linux bridges. All KVM/VMware guests shall belong to the same logical layer 3 network segment and be able to communicate with each other and the host (plus external systems via routing).

    veth6

    The RJ45 like connectors in the picture above represent veth-devices - which occur in pairs. The blue small rectangles on the Linux bridges instead represent ports associated with virtual tap-devices. I admit: This scenario of a virtual network inside a host is a bit academic. But it allows us to test what is possible with "veth"-pairs.

    Building the bridges

    On our Linux host we use virt-manager's "connection details >> virtual networks" to define 2 virtual host only networks with bridges "virbr4" and "virbr6".

    veth7

    Note: We do not allow for bridge specific "dhcp-services" and do not assign network addresses. We shall later configure addresses of the guests manually; you will find some remarks on a specific, network wide DHCP service at the end of the article.

    Then we implement and configure 2 KVM Linux guests (here Kali systems) - one with an Ethernet interface attached to "vibr4"; the other guest will be connected to "virbr6". The next picture shows the network settings for guest "kali3" which gets attached to "virbr6".

    veth8

    We activate the networks and boot our guests. Then on the guests (activate the right interface and deactivate other interfaces, if necessary) we need to set IP-addresses: The interfaces on kali2, kali3 must be configured manually - as we had not activated DHCP. kali2 gets the address "192.168.50.12", kali3 the address "192.168.50.13".

    veth9

    If we had defined several tap interfaces on our guest system kali3 we may have got a problem to identify the right interface associated with bridge. It can however be identified by its MAC and a comparison to the MACs of "vnet" devices in the output of the commands "ip link show" and "brctl show virbr6".

    Now let us look what information we get about the bridges on the host :

    mytux:~ # brctl show virbr4
    bridge name     bridge id               STP enabled     interfaces
    virbr4          8000.5254007e553d       yes             virbr4-nic
                                                            vnet6
    mytux:~ # ifconfig virbr4 
    virbr4    Link encap:Ethernet  HWaddr 52:54:00:7E:55:3D  
              UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
    mytux:~ # ifconfig vnet6
    vnet6     Link encap:Ethernet  HWaddr FE:54:00:F2:A4:8D  
              inet6 addr: fe80::fc54:ff:fef2:a48d/64 Scope:Link
    ....
    mytux:~ # brctl show virbr6
    bridge name     bridge id               STP enabled     interfaces
    virbr6          8000.525400c0b06f       yes             virbr6-nic
                                                            vnet2
    mytux:~ # ip addr show virbr6 
    22: virbr6: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
        link/ether 52:54:00:c0:b0:6f brd ff:ff:ff:ff:ff:ff
    mytux:~ # ifconfig vnet2
    vnet2     Link encap:Ethernet  HWaddr FE:54:00:B1:5D:1F  
              inet6 addr: fe80::fc54:ff:feb1:5d1f/64 Scope:Link
    .....
    mytux:~ # 
    

     
    Note that we do not see any IPv4-information on the "tap" devices vnet5 and vnet2 here. But note, too, that no IP-address has been assigned by the host to the bridges themselves.

    Ok, we have bridges virbr4 with guest "kali2" and a separate bridge virbr6 with KVM guest "kali3". The host has no role in this game, yet. We are going to change this in the next step.

    Note that virt-manager automatically started the bridges when we started the KVM guests. Alternatively, we could have manually set
    mytux:~ # ip link set virbr4 up
    mytux:~ # ip link set virbr6 up
    We may also configure the bridges with "virt-manager" to be automatically started at boot time.

    Attaching the host to a bridge via veth

    According to our example we shall attach the host now by the use of a veth-pair to virbr4 . We create such a pair and connect one of its Ethernet interfaces to "virbr4":

    mytux:~ # ip link add dev vmh1 type veth peer name vmh2       
    mytux:~ # brctl addif virbr4 vmh1
    mytux:~ # brctl show virbr4 
    bridge name     bridge id               STP enabled     interfaces
    virbr4          8000.5254007e553d       yes             virbr4-nic
                                                            vmh1
                                                            vnet6
    

     
    Now, we assign an IP address to interface vmh2 - which is not enslaved by any bridge:

    mytux:~ # ip addr add 192.168.50.1/24 broadcast 192.168.50.255 dev vmh2
    mytux:~ # ip addr show vmh2
    6: vmh2@vmh1: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN group default qlen 1000
        link/ether 42:79:e6:a7:fb:09 brd ff:ff:ff:ff:ff:ff
        inet 192.168.50.1/24 brd 192.168.50.255 scope global vmh2
           valid_lft forever preferred_lft forever
    

     
    We then activate vmh1 and vmh2. Next we need a route on the host to the bridge (and the guests at its ports) via vmh2 (!!) :

    mytux:~ # ip  link set vmh1 up
    mytux:~ # ip  link set vmh2 up
    mytux:~ # route add -net 192.168.50.0/24 dev vmh2
    mytux:~ # route
    Kernel IP routing table
    Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
    default         ufo             0.0.0.0         UG    0      0        0 br0
    192.168.10.0    *               255.255.255.0   U     0      0        0 br0
    ...
    192.168.50.0    *               255.255.255.0   U     0      0        0 vmh2
    ...
    

     
    Now we try whether we can reach guest "kali2" from the host and vice versa:

    mytux:~ # ping 192.168.50.12
    PING 192.168.50.12 (192.168.50.12) 56(84) bytes of data.
    64 bytes from 192.168.50.12: icmp_seq=1 ttl=64 time=0.291 ms
    64 bytes from 192.168.50.12: icmp_seq=2 ttl=64 time=0.316 ms
    64 bytes from 192.168.50.12: icmp_seq=3 ttl=64 time=0.322 ms
    ^C
    --- 192.168.50.12 ping statistics ---
    3 packets transmitted, 3 received, 0% packet loss, time 1999ms
    rtt min/avg/max/mdev = 0.291/0.309/0.322/0.024 ms
    
    root@kali2:~ # ping 192.168.50.1
    PING 192.168.50.1 (192.168.50.1) 56(84) bytes of data.
    64 bytes from 192.168.50.1: icmp_seq=1 ttl=64 time=0.196 ms
    64 bytes from 192.168.50.1: icmp_seq=2 ttl=64 time=0.340 ms
    64 bytes from 192.168.50.1: icmp_seq=3 ttl=64 time=0.255 ms
    ^C
    --- 192.168.50.1 ping statistics ---
    3 packets transmitted, 3 received, 0% packet loss, time 1998ms
    rtt min/avg/max/mdev = 0.196/0.263/0.340/0.062 ms
    

     
    So, we have learned that the host can easily be connected to a Linux bridge via an veth-pair - and that we do not need to assign an IP address to the bridge itself. Regarding the connection links the resulting situation is very similar to bridges where you use a physical "eth0" NIC as an uplink to external systems of a physical network.

    All in all I like this situation much better than having a bridge with an IP. During critical penetration tests we now can just plug vmh1 out of the bridge. And regarding packet-filters: We do not need to establish firewall-rules on the bridge itself - which has security implications if only done on level 3 - but on an "external" Ethernet device. Note also that the interface "vmh2" could directly be bridged by VMware (if you have more trust in VMware bridges) without producing guest isolation problems as described in a previous article (quoted above).

    Linking of two Linux bridges with each other

    Now, we try to create a link between our 2 Linux bridges. As Linux bridge cascading is forbidden, it is interesting to find out whether at least bridge linking is allowed. We use an additional veth-pair for this purpose:

    mytux:~ # ip link add dev vethb1 type veth peer name vethb2       
    mytux:~ # brctl addif virbr4 vethb1
    mytux:~ # brctl addif virbr4 vethb2
    mytux:~ # brctl show virbr4
    bridge name     bridge id               STP enabled     interfaces
    virbr4          8000.5254007e553d       yes             vethb1
                                                            virbr4-nic
                                                            vmh1
                                                            vnet6
    mytux:~ # brctl show virbr6
    bridge name     bridge id               STP enabled     interfaces
    virbr6          8000.2e424b32cb7d       yes             vethb2
                                                            virbr6-nic
                                                            vnet2
    
    
    mytux:~ # ip link set vethb1 up 
    mytux:~ # ip link set vethb2 up 
    

     
    Note, that the STP protocol is enabled on both bridges! (If you see something different you can manually activate STP via options of the brctl command.)

    Now, can we communicate from "kali3" at "virbr6" over the veth-pair and "virbr4" with the host?
    [Please, check the routes on all involved machines for reasonable entries first and correct if necessary; one never knows ...].

    veth10
    and
    veth11

    Yes, obviously we can - and also the host can reach the virtual guest kali3.

    mytux:~ # ping -c4 192.168.50.13
    PING 192.168.50.13 (192.168.50.13) 56(84) bytes of data.
    64 bytes from 192.168.50.13: icmp_seq=1 ttl=64 time=0.259 ms
    64 bytes from 192.168.50.13: icmp_seq=2 ttl=64 time=0.327 ms
    64 bytes from 192.168.50.13: icmp_seq=3 ttl=64 time=0.191 ms
    64 bytes from 192.168.50.13: icmp_seq=4 ttl=64 time=0.287 ms
    
    --- 192.168.50.13 ping statistics ---
    4 packets transmitted, 4 received, 0% packet loss, time 2998ms
    rtt min/avg/max/mdev = 0.191/0.266/0.327/0.049 ms
    

     
    and of course
    veth12

    This was just another example of how we can use veth-pairs. We can link Linux bridges together - and all guests at both bridges are able to communicate with each other and with the host. Good !

    Connecting a virtual VMware bridge to a Linux bridge via a veth-pair

    Our last experiment involves a VMware WS bridge. We could use the VMware Network Editor to define a regular "VMware Host Only Network". However, the bridge for such a network will automatically be created with an associated, enslaved Ethernet device for and on the host. And the bridge itself would automatically get an IP address - namely 192.168.50.1. There is no way known to me to avoid this - we would need to manually eliminate this address afterward.

    So, we take a different road:
    We first create a pair of veth devices - and then bridge (!) one of these veth devices by VMware:

    mytux:~ # ip link add dev vmw1 type veth peer name vmw2
    mytux:~ # brctl link virbr4 vmw1   
    mytux:~ # ip link set vmw1 up
    mytux:~ # ip link set vmw2 up
    mytux:~ # /etc/init.d/vmware restart
    

     
    To create the required VMware bridge to vmw2 we use VMware's Virtual Network Editor":

    veth13

    Note that by creating a specific bridge to one of the veth devices we have avoided any automatic IP address assignment (192.168.50.1) to the Ethernet device which would normally be created by VMware together with a host only bridge. Thus we avoid any conflicts with the already performed address assignment to "vmh2" (see above).

    In our VMware guest (hier a Win system) we configure the network device - e.g. with address 192.168.50.21 - and then try our luck:

    veth14

    Great! What we expected! Of course our other virtual clients and the host can also send packets to the VMware guest. I need not show this here explicitly.

    Summary

    veth-pairs are easy to create and to use. They are ideal tools to connect the host and other Linux or VMware bridges to a Linux bridge in a well defined way.

    A remark on DHCP

    Reasonable and precisely defined address assignment to the bridges and or virtual interfaces can become a problem with VMware as well as with KVM /virt-manager or virsh. Especially, when you want to avoid address assignment to the bridges themselves. Typically, when you define virtual networks in your virtualization environment a bridge is created together with an attached Ethernet interface for the host - which you may not really need. If you in addition enable DHCP functionality for the bridge/network the bridge itself (or the related device) will inevitably (!) and automatically get an address like 192.168.50.1. Furthermore related host routes are automatically set. This may lead to conflicts with what you really want to achieve.

    Therefore: If you want to work with DHCP I advise you to do this with a central DHCP service on the Linux host and not to use the DHCP services of the various virtualization environments. If you in addition want to avoid assigning IP addresses to the bridges themselves, you may need to work with DHCP pools and groups. This is beyond the scope of this article - though interesting in itself. An alternative would, of course, be to set up the whole virtual network with the help of a script, which may (with a little configuration work) be included as a unit into systemd.

    Make veth settings persistent

    Here we have a bit of a problem with Opensuse 13.2/Leap 42.1! The reason is that systemd in Leap and OS 13.2 is of version 210 and does not yet contain the service "systemd-networkd.service" - which actually would support the creation of virtual devices like "veth"-pairs during system startup. To my knowledge neither the "wicked" service used by Opensuse nor the "ifcfg-..." files allow for the definition of veth-pairs, yet. Bridge creation and address assignment to existing ethernet devices are, however, supported. So, what can we do to make things persistent?

    Of course, you can write a script that creates and configures all of your required veth-pairs. This script could be integrated in the boot process as a systemd-service to be started before the "wicked.service". In addition you may configure the afterward existing Ethernet devices with "ifcfg-..."-files. Such files can also be used to guarantee an automatic setup of Linux bridges and their enslavement of defined Ethernet devices.

    Another option is - if you dare to take some risks - to fetch systemd's version 224 from Opensuse's Tumbleweed repository. Then you may create a directory "/etc/systemd/network" and configure the creation of veth-pairs via corresponding "....netdev"-files in the directory. E.g.:

    mytux # cat veth1.netdev 
    [NetDev]
    Name=vmh1
    Kind=veth
    [Peer]
    Name=vmh2
    

     
    I tried it - it works. However, systemd version 224 has trouble with the rearrangement of Leap's apparmor startup. I have not looked at this in detail, yet.

    Nevertheless, have fun with veth devices in your virtual networks !

    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