I have a KVM virtualization server which serves up a br0 bridge, mapped to eth0. I want to add eth2 as a bridge to br2 for a IDS virtual machine I’m testing, but the guest OS doesn’t see either br2 or eth2 as a valid interface. I ran tcpdump on eth2 and can verify it’s seeing packets, so I know I have a valid source and that interface has the PROMISC option using
ifconfig eth2 promisc up. Here’s my /etc/network/interfaces file:
auto lo iface lo inet loopback auto eth0 iface eth0 inet manual auto br0 iface br0 inet static address 126.96.36.199 netmask 255.255.255.0 gateway 188.8.131.52 bridge_ports eth0 bridge_fd 9 bridge_hello 2 bridge_maxage 12 bridge_stp off auto eth2 iface eth2 inet manual auto br2 iface br2 inet static up ifconfig br2 promisc up down ifconfig br2 promisc down bridge_ports eth2 bridge_fd 9 bridge_hello 2 bridge_maxage 12 bridge_stp off
What am I missing?
The Linux bridge is a basic layer 2 switch. In order for it to send traffic to an interface connected to it, the traffic must be appropriate for that interface (i.e. the destination MAC address is reachable via that port).
While layer 2 switches often have a port mirroring feature which forwards all traffic crossing the switch to a designated port, the Linux bridge has no such functionality.
However, you can fake it with Linux’s traffic control (tc). I do this to forward traffic to a KVM virtual machine running suricata. The limitation of this method is that you can only mirror traffic on a single physical port.
In this script, the
MONITOR_PORT is the port to be monitored, which must be a physical port, and
MIRROR_PORT is the interface to which the traffic will be sent (which can be a virtual port or a bridge). The monitored port does not need to be in promiscuous mode with this method. And the mirror port does not need to be bridged to the monitored port.
In my case, the host has a bridge br0, bridged to eno1 and to which all the virtual machines have a virtual NIC. I have created a host-only virtual network (as virbr2) for this VM and added a second NIC in the suricata VM on this network in addition to its regular NIC, and directed the traffic to it.
[error@hypervisor ~]$ cat /etc/rc.d/rc.local #!/bin/bash # Mirror all packets from one port to another (for suricata) MONITOR_PORT=eno1 MIRROR_PORT=virbr2 # Ingress tc qdisc add dev $MONITOR_PORT ingress tc filter add dev $MONITOR_PORT parent ffff: protocol all u32 match u8 0 0 action mirred egress mirror dev $MIRROR_PORT # Egress tc qdisc add dev $MONITOR_PORT handle 1: root prio tc filter add dev $MONITOR_PORT parent 1: protocol all u32 match u8 0 0 action mirred egress mirror dev $MIRROR_PORT
Note that I didn’t create this myself; I shamelessly ripped it off from Port mirroring with Linux bridges, which has a detailed explanation of how it works and an alternative using Open vSwitch which is a lot more flexible (and a lot more complex).
This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.