It is sometimes useful to divide one physical network, such as an Ethernet segment, into two separate network segments without having to create IP subnets and use a router to connect the segments together. A device that connects two networks together in this fashion is called a “bridge”. A FreeBSD system with two network interface cards can act as a bridge.
The bridge works by learning the MAC layer (Ethernet) addresses of the devices on each of its network interfaces. It forwards traffic between two networks only when the source and destination are on different networks.
In many respects, a bridge is like an Ethernet switch with very few ports.
There are many common situations in which a bridge is used today.
The basic operation of a bridge is to join two or more network segments together. There are many reasons to use a host based bridge over plain networking equipment such as cabling constraints, firewalling, or connecting pseudo networks such as a virtual machine interface. A bridge can also connect a wireless interface running in hostap mode to a wired network and act as an access point.
A common situation is where firewall functionality is needed without routing or Network Address Translation (NAT).
An example is a small company that is connected via DSL or ISDN to an ISP. There are thirteen globally-accessible IP addresses from the ISP and ten computers on the network. In this situation, using a router-based firewall is difficult because of subnetting issues.
A bridge-based firewall can be configured and dropped into the path just downstream of the DSL or ISDN router without any IP numbering issues.
A bridge can join two network segments and be used to inspect all Ethernet frames that pass between them using bpf(4) and tcpdump(1) on the bridge interface or by sending a copy of all frames out an additional interface known as a span port.
Two Ethernet networks can be joined across an IP link by bridging the networks to an EtherIP tunnel or a tap(4) based solution such as OpenVPN.
A network can be connected together with multiple links and use the Spanning Tree Protocol STP to block redundant paths. For an Ethernet network to function properly, only one active path can exist between two devices. STP will detect loops and put the redundant links into a blocked state. Should one of the active links fail, STP will calculate a different tree and enable one of the blocked paths to restore connectivity to all points in the network.
This section covers the if_bridge(4) implementation. A netgraph bridging driver is also available, and is described in ng_bridge(4).
In FreeBSD, if_bridge(4) is a kernel module which is
automatically loaded by ifconfig(8) when creating a
bridge interface. It is also possible to compile the bridge
in to the kernel by adding device if_bridge
to a custom kernel configuration file.
Packet filtering can be used with any firewall package that hooks in via the pfil(9) framework. The firewall can be loaded as a module or compiled into the kernel.
The bridge can be used as a traffic shaper with altq(4) or dummynet(4).
The bridge is created using interface cloning. To create a bridge use ifconfig(8):
#
ifconfig bridge create
bridge0
#
ifconfig bridge0
bridge0: flags=8802<BROADCAST,SIMPLEX,MULTICAST> metric 0 mtu 1500
ether 96:3d:4b:f1:79:7a
id 00:00:00:00:00:00 priority 32768 hellotime 2 fwddelay 15
maxage 20 holdcnt 6 proto rstp maxaddr 100 timeout 1200
root id 00:00:00:00:00:00 priority 0 ifcost 0 port 0When a bridge interface is created, it is automatically
assigned a randomly generated Ethernet address. The
maxaddr
and timeout
parameters control how many MAC addresses
the bridge will keep in its forwarding table and how many
seconds before each entry is removed after it is last seen.
The other parameters control how STP
operates.
Next, add the member network interfaces to the bridge. For the bridge to forward packets, all member interfaces and the bridge need to be up:
#
ifconfig bridge0 addm fxp0 addm fxp1 up
#
ifconfig fxp0 up
#
ifconfig fxp1 up
The bridge is now forwarding Ethernet frames between
fxp0
and
fxp1
. Add the following lines to
/etc/rc.conf
so the bridge is created
at startup:
If the bridge host needs an IP address, the correct place to set this is on the bridge interface itself rather than one of the member interfaces. This can be set statically or via DHCP:
#
ifconfig bridge0 inet 192.168.0.1/24
It is also possible to assign an IPv6 address to a bridge interface.
When packet filtering is enabled, bridged packets will pass through the filter inbound on the originating interface on the bridge interface, and outbound on the appropriate interfaces. Either stage can be disabled. When direction of the packet flow is important, it is best to firewall on the member interfaces rather than the bridge itself.
The bridge has several configurable settings for passing non-IP and IP packets, and layer2 firewalling with ipfw(8). See if_bridge(4) for more information.
The bridge driver implements the Rapid Spanning Tree Protocol (RSTP or 802.1w) with backwards compatibility with legacy STP. STP is used to detect and remove loops in a network topology. RSTP provides faster convergence than legacy STP, the protocol will exchange information with neighboring switches to quickly transition to forwarding without creating loops. FreeBSD supports RSTP and STP as operating modes, with RSTP being the default mode.
STP can be enabled on member interfaces
using ifconfig(8). For a bridge with
fxp0
and
fxp1
as the current interfaces,
enable STP with:
#
ifconfig bridge0 stp fxp0 stp fxp1
bridge0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> metric 0 mtu 1500
ether d6:cf:d5:a0:94:6d
id 00:01:02:4b:d4:50 priority 32768 hellotime 2 fwddelay 15
maxage 20 holdcnt 6 proto rstp maxaddr 100 timeout 1200
root id 00:01:02:4b:d4:50 priority 32768 ifcost 0 port 0
member: fxp0 flags=1c7<LEARNING,DISCOVER,STP,AUTOEDGE,PTP,AUTOPTP>
port 3 priority 128 path cost 200000 proto rstp
role designated state forwarding
member: fxp1 flags=1c7<LEARNING,DISCOVER,STP,AUTOEDGE,PTP,AUTOPTP>
port 4 priority 128 path cost 200000 proto rstp
role designated state forwardingThis bridge has a spanning tree ID of
00:01:02:4b:d4:50
and a priority of
32768
. As the root id
is the same, it indicates that this is the root bridge for the
tree.
Another bridge on the network also has STP enabled:
The line root id 00:01:02:4b:d4:50 priority 32768
ifcost 400000 port 4
shows that the root bridge is
00:01:02:4b:d4:50
and has a path cost of
400000
from this bridge. The path to the
root bridge is via port 4
which is
fxp0
.
The bridge supports monitor mode, where the packets are discarded after bpf(4) processing and are not processed or forwarded further. This can be used to multiplex the input of two or more interfaces into a single bpf(4) stream. This is useful for reconstructing the traffic for network taps that transmit the RX/TX signals out through two separate interfaces.
To read the input from four network interfaces as one stream:
#
ifconfig bridge0 addm fxp0 addm fxp1 addm fxp2 addm fxp3 monitor up
#
tcpdump -i bridge0
A copy of every Ethernet frame received by the bridge will be transmitted out a designated span port. The number of span ports configured on a bridge is unlimited, but if an interface is designated as a span port, it cannot also be used as a regular bridge port. This is most useful for snooping a bridged network passively on another host connected to one of the span ports of the bridge.
To send a copy of all frames out the interface named
fxp4
:
#
ifconfig bridge0 span fxp4
A private interface does not forward any traffic to any other port that is also a private interface. The traffic is blocked unconditionally so no Ethernet frames will be forwarded, including ARP. If traffic needs to be selectively blocked, a firewall should be used instead.
If a bridge member interface is marked as sticky, dynamically learned address entries are treated at static once entered into the forwarding cache. Sticky entries are never aged out of the cache or replaced, even if the address is seen on a different interface. This gives the benefit of static address entries without the need to pre-populate the forwarding table. Clients learned on a particular segment of the bridge can not roam to another segment.
Another example of using sticky addresses is to
combine the bridge with VLANs to create
a router where customer networks are isolated without
wasting IP address space. Consider that
CustomerA
is on
vlan100
and CustomerB
is on
vlan101
. The bridge has the address
192.168.0.1
and is also an
Internet router.
#
ifconfig bridge0 addm vlan100 sticky vlan100 addm vlan101 sticky vlan101
#
ifconfig bridge0 inet 192.168.0.1/24
In this example, both clients see 192.168.0.1
as their default
gateway. Since the bridge cache is sticky, one host can not
spoof the MAC address of the other
customer in order to intercept their traffic.
Any communication between the VLANs can be blocked using a firewall or, as seen in this example, private interfaces:
#
ifconfig bridge0 private vlan100 private vlan101
The customers are completely isolated from each other
and the full /24
address
range can be allocated without subnetting.
The number of unique source MAC addresses behind an interface can be limited. Once the limit is reached, packets with unknown source addresses are dropped until an existing host cache entry expires or is removed.
The following example sets the maximum number of
Ethernet devices for CustomerA
on
vlan100
to 10:
#
ifconfig bridge0 ifmaxaddr vlan100 10
The bridge interface and STP parameters can be monitored via bsnmpd(1) which is included in the FreeBSD base system. The exported bridge MIBs conform to the IETF standards so any SNMP client or monitoring package can be used to retrieve the data.
On the bridge, uncomment the
begemotSnmpdModulePath."bridge" =
"/usr/lib/snmp_bridge.so"
line from
/etc/snmp.config
and start
bsnmpd(1). Other configuration, such as community
names and access lists, may need to be modified. See
bsnmpd(1) and snmp_bridge(3) for more
information.
The following examples use the
Net-SNMP software (net-mgmt/net-snmp
) to query a
bridge from a client system. The net-mgmt/bsnmptools
port can
also be used. From the SNMP client
which is running Net-SNMP, add
the following lines to
$HOME/.snmp/snmp.conf
in order to
import the bridge MIB definitions:
To monitor a single bridge using the IETF BRIDGE-MIB (RFC4188):
%
snmpwalk -v 2c -c public bridge1.example.com mib-2.dot1dBridge
BRIDGE-MIB::dot1dBaseBridgeAddress.0 = STRING: 66:fb:9b:6e:5c:44
BRIDGE-MIB::dot1dBaseNumPorts.0 = INTEGER: 1 ports
BRIDGE-MIB::dot1dStpTimeSinceTopologyChange.0 = Timeticks: (189959) 0:31:39.59 centi-seconds
BRIDGE-MIB::dot1dStpTopChanges.0 = Counter32: 2
BRIDGE-MIB::dot1dStpDesignatedRoot.0 = Hex-STRING: 80 00 00 01 02 4B D4 50
...
BRIDGE-MIB::dot1dStpPortState.3 = INTEGER: forwarding(5)
BRIDGE-MIB::dot1dStpPortEnable.3 = INTEGER: enabled(1)
BRIDGE-MIB::dot1dStpPortPathCost.3 = INTEGER: 200000
BRIDGE-MIB::dot1dStpPortDesignatedRoot.3 = Hex-STRING: 80 00 00 01 02 4B D4 50
BRIDGE-MIB::dot1dStpPortDesignatedCost.3 = INTEGER: 0
BRIDGE-MIB::dot1dStpPortDesignatedBridge.3 = Hex-STRING: 80 00 00 01 02 4B D4 50
BRIDGE-MIB::dot1dStpPortDesignatedPort.3 = Hex-STRING: 03 80
BRIDGE-MIB::dot1dStpPortForwardTransitions.3 = Counter32: 1
RSTP-MIB::dot1dStpVersion.0 = INTEGER: rstp(2)The dot1dStpTopChanges.0
value is
two, indicating that the STP bridge
topology has changed twice. A topology change means that
one or more links in the network have changed or failed
and a new tree has been calculated. The
dot1dStpTimeSinceTopologyChange.0
value
will show when this happened.
To monitor multiple bridge interfaces, the private BEGEMOT-BRIDGE-MIB can be used:
%
snmpwalk -v 2c -c public bridge1.example.com
enterprises.fokus.begemot.begemotBridge
BEGEMOT-BRIDGE-MIB::begemotBridgeBaseName."bridge0" = STRING: bridge0
BEGEMOT-BRIDGE-MIB::begemotBridgeBaseName."bridge2" = STRING: bridge2
BEGEMOT-BRIDGE-MIB::begemotBridgeBaseAddress."bridge0" = STRING: e:ce:3b:5a:9e:13
BEGEMOT-BRIDGE-MIB::begemotBridgeBaseAddress."bridge2" = STRING: 12:5e:4d:74:d:fc
BEGEMOT-BRIDGE-MIB::begemotBridgeBaseNumPorts."bridge0" = INTEGER: 1
BEGEMOT-BRIDGE-MIB::begemotBridgeBaseNumPorts."bridge2" = INTEGER: 1
...
BEGEMOT-BRIDGE-MIB::begemotBridgeStpTimeSinceTopologyChange."bridge0" = Timeticks: (116927) 0:19:29.27 centi-seconds
BEGEMOT-BRIDGE-MIB::begemotBridgeStpTimeSinceTopologyChange."bridge2" = Timeticks: (82773) 0:13:47.73 centi-seconds
BEGEMOT-BRIDGE-MIB::begemotBridgeStpTopChanges."bridge0" = Counter32: 1
BEGEMOT-BRIDGE-MIB::begemotBridgeStpTopChanges."bridge2" = Counter32: 1
BEGEMOT-BRIDGE-MIB::begemotBridgeStpDesignatedRoot."bridge0" = Hex-STRING: 80 00 00 40 95 30 5E 31
BEGEMOT-BRIDGE-MIB::begemotBridgeStpDesignatedRoot."bridge2" = Hex-STRING: 80 00 00 50 8B B8 C6 A9To change the bridge interface being monitored via the
mib-2.dot1dBridge
subtree:
%
snmpset -v 2c -c private bridge1.example.com
BEGEMOT-BRIDGE-MIB::begemotBridgeDefaultBridgeIf.0 s bridge2All FreeBSD documents are available for download at http://ftp.FreeBSD.org/pub/FreeBSD/doc/
Questions that are not answered by the
documentation may be
sent to <freebsd-questions@FreeBSD.org>.
Send questions about this document to <freebsd-doc@FreeBSD.org>.