Create bridge and add TUN/TAP device using NetworkManager nmcli under CentOS 8

This article shows how to create a network bridge device and a TUN/TAP device, which then is added to the bridge. The CentOS 8 Stream is used along with the console NetworkManager program nmcli.
TUN/TAP devices are often used in the virtualization world as a link device between the host machine and the virtual machine.

This article is for the case when the bridge does not include the main network interface (Internet network interface and so on) of the server but is an additional device, which MAC and virtual machine MACs would not be exposed through the server’s main network interface.

If the server’s main network interface should be included in the bridge device, i.e. replace the main network interface with the bridge there is another article on the subject – Replace current interface configuration with a bridge device using nmcli (NetworkManager)

Device name are as follow:

  • br0 is the name of the network bridge.
  • 10.10.10.1 with mask /24 is the IP of the bridge device with name br0. Because the idea is to use the bridge only locally, a local interface is used. The IP is set manually.
  • tap0 is the name of TUN/TAP device.
  • enp0s3is the server’s main network connection. Not used in this howto.

Here are all the commands to create a bridge, create a TUN/TAP device and add it to the bridge, and then activate the bridge‘s link.

nmcli connection add type bridge ifname br0 con-name br0 ipv4.method manual ipv4.addresses "10.10.10.1/24"
nmcli con up br0
nmcli connection add type tun ifname tap0 con-name tap0 mode tap owner 0 ip4 0.0.0.0/24
nmcli con add type bridge-slave ifname tap0 master br0

Here are the steps with much more details and information including all the command output.
The networking before any reconfiguration:

[root@srv ~]# nmcli
enp0s3: connected to enp0s3
        "Intel 82540EM"
        ethernet (e1000), 08:00:27:03:C9:2E, hw, mtu 1500
        ip4 default
        inet4 192.168.0.20/24
        route4 192.168.0.0/24 metric 100
        route4 0.0.0.0/0 via 192.168.0.1 metric 100
        inet6 fe80::a00:27ff:fe03:c92e/64
        route6 fe80::/64 metric 100

lo: unmanaged
        "lo"
        loopback (unknown), 00:00:00:00:00:00, sw, mtu 65536

DNS configuration:
        servers: 8.8.8.8 1.1.1.1
        interface: enp0s3

Use "nmcli device show" to get complete information about known devices and
"nmcli connection show" to get an overview on active connection profiles.

Consult nmcli(1) and nmcli-examples(7) manual pages for complete usage details.
[root@srv ~]# nmcli con
NAME    UUID                                  TYPE      DEVICE 
enp0s3  09497bbf-da59-42b7-a72c-d69369760b36  ethernet  enp0s3 

STEP 1) Create the bridge and set the IP manually.

The bridge device has name br0 and the network IP 10.10.10.1/24 should be manually set. If the IP part is skipped, the bridge would have IP configuration set to auto and it would expect to receive DHCP configuration.

[root@srv ~]# nmcli connection add type bridge ifname br0 con-name br0 ipv4.method manual ipv4.addresses "10.10.10.1/24"
Connection 'br0' (89e26fba-57a8-4bb8-b46f-d85f3a1e0cd0) successfully added.
[root@srv ~]# nmcli con up br0
Connection successfully activated (master waiting for slaves) (D-Bus active path: /org/freedesktop/NetworkManager/ActiveConnection/3)
[root@srv ~]# nmcli con
NAME    UUID                                  TYPE      DEVICE 
enp0s3  09497bbf-da59-42b7-a72c-d69369760b36  ethernet  enp0s3 
br0     89e26fba-57a8-4bb8-b46f-d85f3a1e0cd0  bridge    br0    
[root@srv ~]# nmcli
enp0s3: connected to enp0s3
        "Intel 82540EM"
        ethernet (e1000), 08:00:27:03:C9:2E, hw, mtu 1500
        ip4 default
        inet4 192.168.0.20/24
        route4 192.168.0.0/24 metric 100
        route4 0.0.0.0/0 via 192.168.0.1 metric 100
        inet6 fe80::a00:27ff:fe03:c92e/64
        route6 fe80::/64 metric 100

br0: connected to br0
        "br0"
        bridge, AA:FC:78:45:51:82, sw, mtu 1500
        inet4 10.10.10.1/24
        route4 10.10.10.0/24 metric 425

lo: unmanaged
        "lo"
        loopback (unknown), 00:00:00:00:00:00, sw, mtu 65536

DNS configuration:
        servers: 8.8.8.8 1.1.1.1
        interface: enp0s3

Use "nmcli device show" to get complete information about known devices and
"nmcli connection show" to get an overview on active connection profiles.

Consult nmcli(1) and nmcli-examples(7) manual pages for complete usage details.
[root@srv ~]# nmcli con
NAME    UUID                                  TYPE      DEVICE 
enp0s3  09497bbf-da59-42b7-a72c-d69369760b36  ethernet  enp0s3 
br0     89e26fba-57a8-4bb8-b46f-d85f3a1e0cd0  bridge    br0

STEP 2) Create the TUN/TAP network interface.

The TUN/TAP device name is tap0. The owner is 0, i.e. root. If the TUN/TAP device is planed to be used with different user, the UID of the user should be used instead 0.

[root@srv ~]# nmcli connection add type tun ifname tap0 con-name tap0 mode tap owner 0 ip4 0.0.0.0/24
Connection 'tap0' (9ddc1cce-7c4d-4af1-b042-d7a92a7a5084) successfully added.
[root@srv ~]# nmcli 
enp0s3: connected to enp0s3
        "Intel 82540EM"
        ethernet (e1000), 08:00:27:03:C9:2E, hw, mtu 1500
        ip4 default
        inet4 192.168.0.20/24
        route4 192.168.0.0/24 metric 100
        route4 0.0.0.0/0 via 192.168.0.1 metric 100
        inet6 fe80::a00:27ff:fe03:c92e/64
        route6 fe80::/64 metric 100

tap0: connected to tap0
        "tap0"
        tun, 26:55:7A:66:95:71, sw, mtu 1500
        inet4 0.0.0.0/24
        inet6 fe80::c312:f1a5:6f32:9f10/64
        route6 fe80::/64 metric 450

br0: connected to br0
        "br0"
        bridge, AA:FC:78:45:51:82, sw, mtu 1500
        inet4 10.10.10.1/24
        route4 10.10.10.0/24 metric 425

lo: unmanaged
        "lo"
        loopback (unknown), 00:00:00:00:00:00, sw, mtu 65536

DNS configuration:
        servers: 8.8.8.8 1.1.1.1
        interface: enp0s3

Use "nmcli device show" to get complete information about known devices and
"nmcli connection show" to get an overview on active connection profiles.

Consult nmcli(1) and nmcli-examples(7) manual pages for complete usage details.
[root@srv ~]# nmcli con
NAME    UUID                                  TYPE      DEVICE 
enp0s3  09497bbf-da59-42b7-a72c-d69369760b36  ethernet  enp0s3 
tap0    5cb465f7-2b29-42dd-858a-ed141b0686b8  tun       tap0   
br0     89e26fba-57a8-4bb8-b46f-d85f3a1e0cd0  bridge    br0

There are three connections the server’s main network connection through enp0s3 and two additional br0 and tap0.

STEP 3) Add the TUN/TAP device to the bridge.

Add the TUN/TAP device tap0 to the bridge br0. A new link with the name bridge-slave-tap0 is established.

[root@srv ~]# nmcli con add type bridge-slave ifname tap0 master br0
Connection 'bridge-slave-tap0' (446beb1d-af26-4e5f-9efd-9404ee23106c) successfully added.
[root@srv ~]# nmcli 
enp0s3: connected to enp0s3
        "Intel 82540EM"
        ethernet (e1000), 08:00:27:03:C9:2E, hw, mtu 1500
        ip4 default
        inet4 192.168.0.20/24
        route4 192.168.0.0/24 metric 100
        route4 0.0.0.0/0 via 192.168.0.1 metric 100
        inet6 fe80::a00:27ff:fe03:c92e/64
        route6 fe80::/64 metric 100

tap0: connected to tap0
        "tap0"
        tun, 26:55:7A:66:95:71, sw, mtu 1500
        inet4 0.0.0.0/24
        inet6 fe80::c312:f1a5:6f32:9f10/64
        route6 fe80::/64 metric 450

br0: connected to br0
        "br0"
        bridge, AA:FC:78:45:51:82, sw, mtu 1500
        inet4 10.10.10.1/24
        route4 10.10.10.0/24 metric 425

lo: unmanaged
        "lo"
        loopback (unknown), 00:00:00:00:00:00, sw, mtu 65536

DNS configuration:
        servers: 8.8.8.8 1.1.1.1
        interface: enp0s3

Use "nmcli device show" to get complete information about known devices and
"nmcli connection show" to get an overview on active connection profiles.

Consult nmcli(1) and nmcli-examples(7) manual pages for complete usage details.
[root@srv ~]# nmcli con
NAME               UUID                                  TYPE      DEVICE 
enp0s3             09497bbf-da59-42b7-a72c-d69369760b36  ethernet  enp0s3 
tap0               5cb465f7-2b29-42dd-858a-ed141b0686b8  tun       tap0   
br0                89e26fba-57a8-4bb8-b46f-d85f3a1e0cd0  bridge    br0    
bridge-slave-tap0  446beb1d-af26-4e5f-9efd-9404ee23106c  ethernet  -- 

Now the tap0 may be used in QEMU to link the virtual machine network card with the host one, for example.

Here is the networking information using ip command form iproute2:

[root@srv ~]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: enp0s3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 08:00:27:03:c9:2e brd ff:ff:ff:ff:ff:ff
    inet 192.168.0.20/24 brd 192.168.0.255 scope global noprefixroute enp0s3
       valid_lft forever preferred_lft forever
    inet6 fe80::a00:27ff:fe03:c92e/64 scope link noprefixroute 
       valid_lft forever preferred_lft forever
3: br0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default qlen 1000
    link/ether aa:fc:78:45:51:82 brd ff:ff:ff:ff:ff:ff
    inet 10.10.10.1/24 brd 10.10.10.255 scope global noprefixroute br0
       valid_lft forever preferred_lft forever
4: tap0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc fq_codel state DOWN group default qlen 1000
    link/ether 26:55:7a:66:95:71 brd ff:ff:ff:ff:ff:ff
    inet6 fe80::c312:f1a5:6f32:9f10/64 scope link tentative noprefixroute 
       valid_lft forever preferred_lft forever

[root@srv ~]# ping -c 4 10.10.10.1
PING 10.10.10.1 (10.10.10.1) 56(84) bytes of data.
64 bytes from 10.10.10.1: icmp_seq=1 ttl=64 time=0.059 ms
64 bytes from 10.10.10.1: icmp_seq=2 ttl=64 time=0.052 ms
64 bytes from 10.10.10.1: icmp_seq=3 ttl=64 time=0.063 ms
64 bytes from 10.10.10.1: icmp_seq=4 ttl=64 time=0.052 ms

--- 10.10.10.1 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3347ms
rtt min/avg/max/mdev = 0.052/0.056/0.063/0.008 ms
[root@srv ~]#

Bonus – network configuration files.

NetowrkManager created two additional network configurations under /etc/sysconfig/network-scripts/ with names ifcfg-br0 and ifcfg-bridge-slave-tap0.

[root@srv ~]# cat /etc/sysconfig/network-scripts/ifcfg-br0 
STP=yes
BRIDGING_OPTS=priority=32768
TYPE=Bridge
PROXY_METHOD=none
BROWSER_ONLY=no
BOOTPROTO=none
IPADDR=10.10.10.1
PREFIX=24
DEFROUTE=yes
IPV4_FAILURE_FATAL=no
IPV6INIT=yes
IPV6_AUTOCONF=yes
IPV6_DEFROUTE=yes
IPV6_FAILURE_FATAL=no
IPV6_ADDR_GEN_MODE=stable-privacy
NAME=br0
UUID=89e26fba-57a8-4bb8-b46f-d85f3a1e0cd0
DEVICE=br0
ONBOOT=yes
[root@srv ~]# cat /etc/sysconfig/network-scripts/ifcfg-bridge-slave-tap0
TYPE=Ethernet
NAME=bridge-slave-tap0
UUID=446beb1d-af26-4e5f-9efd-9404ee23106c
DEVICE=tap0
ONBOOT=yes
BRIDGE=br0

Bonus 2 – Internet to the bridge.

To enable the bridge to have Internet access just configure the firewall and activate masquerade mode.

[root@srv ~]# firewall-cmd --list-all
public (active)
  target: default
  icmp-block-inversion: no
  interfaces: br0 enp0s3 tap0
  sources: 
  services: cockpit dhcpv6-client ssh
  ports: 
  protocols: 
  forward: no
  masquerade: no
  forward-ports: 
  source-ports: 
  icmp-blocks: 
  rich rules: 
[root@srv ~]# firewall-cmd --permanent --add-masquerade
success
[root@srv ~]# firewall-cmd --reload
success
[root@srv ~]# firewall-cmd --list-all
public (active)
  target: default
  icmp-block-inversion: no
  interfaces: br0 enp0s3 tap0
  sources: 
  services: cockpit dhcpv6-client ssh
  ports: 
  protocols: 
  forward: no
  masquerade: yes
  forward-ports: 
  source-ports: 
  icmp-blocks: 
  rich rules:

Leave a Reply

Your email address will not be published. Required fields are marked *