Network bridge

From Gentoo Wiki
Jump to:navigation Jump to:search

This article discusses how to setup a network bridge in order to connect two portions of a network together.

Introduction

A network bridge can be used to connect two independent network segments at layer 2 level (much like a network switch). Common applications include transparent proxying, transparent filtering (using iptables) and saving money on hardware as some mainboards come with two PHY interfaces. In this article, enp1s0 and enp2s0 will be the network interfaces used but of course they can be replaced by whatever interface names are present on a system (such as eth0 and eth1).

In order to create a bridge on Linux a special bridging device is created (brX) that contains at least two network devices as ports (e.g. ethX or pppX). As the bridge works on layer 2, no IP addresses are needed on the port devices — on a typical setup, the bridging device itself will receive the IP (e.g. via DHCP).

Kernel

KERNEL Enabling Ethernet Bridging
[*] Networking support  --->
   Networking options  --->
      <M> 802.1d Ethernet Bridging

Installation

Note
With net-misc/netifrc >=0.4.0, the installation of net-misc/bridge-utils has been deprecated. The network bridge is set up simply by configuring it in /etc/conf.d/net (cf. #See also).

With older versions of netifrc, or needs for some other reasons, install the net-misc/bridge-utils package to have access to the utilities needed to manage the bridge device:

root #emerge --ask bridge-utils

It is recommended to configure bridges with a console connection. SSH access is likely to be lost if working on one of the ports being adding to the bridge.

Make certain the physical Ethernet interfaces in the bridge are not in /etc/init.d/ as symbolic links as part of the original install:

root #rc-update delete net.enp1s0 boot
root #rc-update delete net.enp2s0 boot
root #rm /etc/init.d/net.enp2s0
root #rm /etc/init.d/net.enp1s0

It is always best to learn how to do things first by hand, then automate it. As this is a layer 2 connection being creating, IP addresses assigned to the physical ports are not needed. The bridged physical interfaces (enp1s0 and enp2s0 in the below example) are put into promiscuous mode, so they will not be able to receive an IP address (e.g. via dhcp). The bridge will also not function properly if static IP addresses are forced on the interfaces.

Now create a bridge with no interfaces assigned (yet):

root #ip link add br0 type bridge

Add the two interfaces to the bridge:

root #ip link set dev enp1s0 master br0
root #ip link set dev enp2s0 master br0

View the results:

root #ip link show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: enp1s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast master br0 state UP mode DEFAULT group default qlen 1000
    link/ether 00:00:00:00:00:00 brd ff:ff:ff:ff:ff:ff
3: enp2s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast master br0 state UP mode DEFAULT group default qlen 1000
    link/ether 00:00:00:00:00:00 brd ff:ff:ff:ff:ff:ff
4: br0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP mode DEFAULT group default qlen 1000
    link/ether 00:00:00:00:00:00 brd ff:ff:ff:ff:ff:ff

Note that stp does not get turned on unless specified.

Host configuration

OpenRC

First, the bridge device must be added to the /etc/conf.d/net file. As an example, bridge configuration with static addresses:

FILE /etc/conf.d/netAdd bridge device example
# Set up the initial layer 2 bridge interface
bridge_br0="enp1s0 enp2s0"

# Bridge static config
config_br0="192.168.26.199 netmask 255.255.255.0"
routes_br0="default via 192.168.26.254"

bridge_forward_delay_br0=0
bridge_hello_time_br0=1000

For dynamic address, use dhcp option:

FILE /etc/conf.d/netDHCP bridge config
# Set up the initial layer 2 bridge interface
bridge_br0="enp1s0 enp2s0"

# Bridge dynamic config
config_br0="dhcp"

bridge_forward_delay_br0=0
bridge_hello_time_br0=1000
Note
It is important to include bridge_forward_delay_br0=0 and bridge_hello_time_br0=1000 in the /etc/conf.d/net file in order to bring the bridge interface up quickly. Other values will cause network packets to be dropped for the first 30 seconds after the bridge has become active. This, in turn, could prevent DHCP from working as intended.

More documentation can be found by reading /usr/share/doc/netifrc-*/net.example.bz2, for example: less /usr/share/doc/netifrc-0.5.1/net.example.bz2

Next, create the init script by linking net.lo to net.br0 and start the interface as follows:

root #ln -s /etc/init.d/net.lo /etc/init.d/net.br0
root #rc-service net.br0 start

Finally, to make sure the bridge is automatically set up on subsequent boots add the newly generated init script to the system's default run level:

root #rc-update add net.br0 default

Single NIC bridge

There are cases when a bridge is needed even when only a single NIC is available on the system, such as a bridge for LXD, Podman, Xen or docker, so that containers can be easily exposed to the LAN. In such a scenario, it is possible to put a single interface in the bridge configuration:

FILE /etc/conf.d/netSingle interface DHCP bridge config
config_enp1s0="null"
bridge_br0="enp1s0"

# Bridge dynamic config
config_br0="dhcp"

bridge_forward_delay_br0=0
bridge_hello_time_br0=1000

The host machine will still have access to the network as the default route is now configured through the bridge interface. Now any containers using this bridge as the parent will be exposed to the LAN, which can be quite useful but also needs careful firewall protections as all ports are now exposed.

systemd

As of systemd 210 and up, a special service called systemd-networkd is available for network configuration. This service can handle bridge construction.

The basic procedure of creating a network configuration with systemd-networkd is creating several .network and .netdev files.

First, create a bridge. With systemd-networkd this is as simple as creating a new .netdev file:

FILE /etc/systemd/network/MyBridge.netdevSystemd-networkd example
[NetDev]
Name=br0
Kind=bridge

After the bridge definition is created, assign the interfaces to the bridge:

FILE /etc/systemd/network/MyEth.networkInterface assignment example
[Match]
Name=eth*

[Network]
Bridge=br0

Multiple interfaces can be matched and attached to the bridge.

Notice that this bridge is still not active. Activation can be achieved by creating a .network definition to use the bridge.

DHCP

FILE /etc/systemd/network/MyBridge.networkDHCP configuration
[Match]
Name=br0

[Network]
DHCP=ipv4

Static

FILE /etc/systemd/network/MyBridge.networkStatic configuration
[Match]
Name=br0

[Network]
DNS=192.168.1.1
Address=192.168.1.2/24
Gateway=192.168.1.1

Defining a gateway is only necessary if one intends to use the physical network interface as access to another network. When using the bridge as a private network, omit it as systemd-networkd will add the bridge as a default route when the Gateway option is set.

Do remember to enable and start the systemd-networkd service.

Using NetworkManager

An alternative way of setting up a bridge is to use net-misc/networkmanager package.

Please make sure the kernel has full support for Iptables before proceed.

Optionally install bridge management tools:

root #emerge -av bridge-utils ebtables

Next enable iptables support for networkmanager:

FILE /etc/portage/package.use/networkEnable iptables support
net-misc/networkmanager connection-sharing dhcpcd gnutls iwd resolvconf nftables -systemd -teamd iptables

Then create a bridge using networkmanager cli:

root #nmcli con add type bridge con-name br0 ifname br0 <ip4 10.0.0.3/24 gw4 10.0.0.1>
root #nmcli con add type bridge-slave con-name br0-slave0 ifname eth0 master br0
root #nmcli con add type bridge-slave con-name br0-slave1 ifname eth1 master br0
root #nmcli con mod br0 ipv4.dns 1.1.1.1 ipv4.method manual
root #nmcli con up br0

See also

External resources