Ubuntu 16.04 LXD Networking: Simple Bridge

lxd-bridge-472x150This configuration is used when your LXD containers need to exist on the same IP subnet as other devices on the local network. Furthermore, we want to be able to SSH into the Host and/or any of the Containers from within the local network. So, for this example:

Server install: Bare metal
Local Network: 192.168.0.0
Broadcast: 255.255.255.0
Gateway: 192.168.0.1

Host and Container Addresses:
– LXD Host (Server): 192.168.0.80
– Container #1: 192.168.0.81
– Container #2: 192.168.0.82
– Container #3: 192.168.0.83
– Container #4: 192.168.0.84


Install and Configure LXD

This assumes that you have Ubuntu-16.04 LTS installed and configured on your server.

On 16.04 LXD is installed (by default), however we’ll need the bridge-utils package.

$ sudo apt-get install bridge-utils

LXD Initialization – First-time:

Use this procedure if LXD has NOT been previously initialized (and no containers created).

For this example we’re keeping this simple and NOT using a ZFS storage backend, so we’ll use simple directories (dir) for the containers. We’ll also establish an LXD bridge except we will not initialize the default lxdbr0 bridge but rather use our own manually configured bridge (br0).

$ user01@lxdhost01:~$ sudo lxd init
Name of the storage backend to use (dir or zfs): dir
Would you like LXD to be available over the network (yes/no)? yes
Address to bind LXD to (not including port): 192.168.0.80   (IP address of LXD Host server)
Port to bind LXD to (8443 recommended): 8443  
Trust password for new clients: ohtrustmenot
Do you want to configure the LXD bridge (yes/no)? yes
Would you like to setup a network bridge for LXD containers now? no  
Do you want to use an existing bridge? yes  
Bridge interface name:  br0

Done.

Use this procedure if LXD has previously been initialized and there are container(s) that have been created.

$ sudo dpkg-reconfigure -p medium lxd

Would you like to setup a network bridge for LXD containers now?   [no]
Do you want to use an existing bridge? yes
Bridge interface name: br0

Done

LXD’s (lxdbr0) default networking scheme operates much differently that LXC’s (lxcbr0). The default configuration for LXD/lxdbr0 is ipv6 link local only, which means you have to manually configure (reconfigure) LXD for ipv4 and/or ipv6. This also means that you can’t SSH into your containers under the default lxdbr0 configuration.

Our LXD containers need to (initially) come up with a IP address from the local DHCP pool. We will assign static IP addresses to those containers that need to run permanently on the local network.

LXD Networking Configuration

First, we will also need to enable packet forwarding for IPv4 on the LXD host:

$ sudo nano /etc/sysctl.conf

Uncomment:

 net.ipv4.ip_forward=1

Then, enable the new setting:

$ sudo sysctl -p

Done.

Next modify the /etc/network/interfaces file so that we can define the LXD Host static IP address and the new bridge (br0).

$ sudo nano /etc/network/interfaces

Note that since 15.10 Ubuntu now uses a different network interface name scheme that generates stateless, persistent network interface names based on info from the BIOS. So in this example enp9s0 is the server’s eth0 under the old naming scheme.

# This file describes the network interfaces available on your system
# and how to activate them. For more information, see interfaces(5).
source /etc/network/interfaces.d/*

## The loopback network interface
auto lo
iface lo inet loopback

## The primary network interface
auto br0
iface br0 inet static
    address 192.168.0.80
    netmask 255.255.255.0
    network 192.168.0.0
    broadcast 192.168.0.255
    gateway 192.168.0.1
    dns-nameservers 8.8.8.8

##  bridge options
bridge_ports enp9s0  
## auto enp9s0
iface enp9s0 inet manual

Done. Restart the network.

$ sudo service networking reload

The reconfigured network interfaces should look like this:

user01@lxdhost01:~$ ifconfig
br0       Link encap:Ethernet  HWaddr 00:1c:23:15:5f:fd  
        inet addr:192.168.0.80  Bcast:192.168.0.255  Mask:255.255.255.0
        inet6 addr: fe80::21c:23ff:fe15:5ffd/64 Scope:Link
        UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
        RX packets:53 errors:0 dropped:0 overruns:0 frame:0
        TX packets:17 errors:0 dropped:0 overruns:0 carrier:0
        collisions:0 txqueuelen:1000 
        RX bytes:4468 (4.4 KB)  TX bytes:1882 (1.8 KB)

enp9s0    Link encap:Ethernet  HWaddr 00:1c:23:15:5f:fd  
        UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
        RX packets:38 errors:0 dropped:0 overruns:0 frame:0
        TX packets:7 errors:0 dropped:0 overruns:0 carrier:0
        collisions:0 txqueuelen:1000 
        RX bytes:4098 (4.0 KB)  TX bytes:982 (982.0 B)
        Interrupt:17

lo      Link encap:Local Loopback  
        inet addr:127.0.0.1  Mask:255.0.0.0
        inet6 addr: ::1/128 Scope:Host
        UP LOOPBACK RUNNING  MTU:65536  Metric:1
        RX packets:162 errors:0 dropped:0 overruns:0 frame:0
        TX packets:162 errors:0 dropped:0 overruns:0 carrier:0
        collisions:0 txqueuelen:1 
        RX bytes:12416 (12.4 KB)  TX bytes:12416 (12.4 KB)

Our modified LXD default profile:

$ lxc profile show default
name: default
config: {}
description: Default LXD profile
devices:
  eth0:
    name: eth0
    nictype: bridged
    parent: br0
    type: nic

Next: Launch LXD containers…

Launch a Xenial container named ct01.

$ sudo lxc launch ubuntu:xenial ct01

We can check our new LXD container

$ sudo lxc list

ct01| RUNNING 192.168.0.108 (eth0) | 2602:306:cf5b:e420:216:3eff:fe71:588 (eth0) |PERSISTENT | 0

The new container ct01 launched as expected, and picked up an available IP address from the local DHCP pool. Modify the /etc/network/interfaces file in ct01 and assign it a static IP.

Access the container ct01 through the host.

user01@lxdhost01:~$ sudo lxc exec ct01 bash
root@ct01:~$

First, update the container, then modify /etc/network/interfaces in the container

root@ct01:~$ apt-get update && apt-get -y dist-upgrade  
root@ct01:~$ nano /etc/network/interfaces

Modify the interfaces file and assign a static IP. Make sure the source /etc/network/interfaces.d/.cfg* is commented out. The default .cfg will make your container pick-up a DHCP address, which is not what we want.

# The loopback network interface
auto lo
iface lo inet loopback

# Source interfaces
# Please check /etc/network/interfaces.d before changing this file
# as interfaces may have been defined in /etc/network/interfaces.d
# See LP: #1262951
# source /etc/network/interfaces.d/*.cfg

# Assign static ip to container
auto eth0
iface eth0 inet static
address 192.168.0.81
network 192.168.0.0
broadcast 192.168.0.255
gateway 192.168.0.1
dns-nameservers 8.8.8.8

Save the file. You’ll need to exit the container and from the host, restart the networking on ct01. Restarting the container is the easiest.

root@ct01:~$ exit
user01@lxdhost01:~$ sudo lxc restart ct01

Check the modified interface settings of ct01.

user01@lxdhost01:~$ sudo lxc exec ct01 ifconfig

eth0      Link encap:Ethernet  HWaddr 00:16:3e:71:05:88  
        inet addr:192.168.0.81  Bcast:192.168.0.255  Mask:255.255.255.0
        inet6 addr: fe80::216:3eff:fe71:588/64 Scope:Link
        UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
        RX packets:72 errors:0 dropped:0 overruns:0 frame:0
        TX packets:10 errors:0 dropped:0 overruns:0 carrier:0
        collisions:0 txqueuelen:1000 
        RX bytes:4746 (4.7 KB)  TX bytes:732 (732.0 B)

lo        Link encap:Local Loopback  
        inet addr:127.0.0.1  Mask:255.0.0.0
        inet6 addr: ::1/128 Scope:Host
        UP LOOPBACK RUNNING  MTU:65536  Metric:1
        RX packets:4 errors:0 dropped:0 overruns:0 frame:0
        TX packets:4 errors:0 dropped:0 overruns:0 carrier:0
        collisions:0 txqueuelen:1 
        RX bytes:256 (256.0 B)  TX bytes:256 (256.0 B)

The container ct01 now sports a static IP address (192.168.0.81). Now we need to enable normal SSH access to container ct01.

Enable SSH access into container ct01.

The default config for sshd is to allow only Public Key Authentication access. Normal password access (PasswordAuthentication) is not configured. To enable normal password access:

$ user01@lxchost01:~$ sudo lxc exec ct01 bash
root@ct01:~$ nano /etc/ssh/sshd_config

Uncomment:

PasswordAuthentication yes

Save and reload SSH. Normal SSH access into the container is enabled. Repeat these steps to add additional containers.


Note: In SSH, Password Authentication password communication is protected by the SSH tunnel. Under normal circumstances this is secure. Of course this assumes that you connect to a trusted server and you verify the server signature.

It is possible to that you connect to a malicious server (MITM attack) and don’t verify the server signature. In this case a MITM attacker could easily sniff the SSH password.

Public Key authentication is an alternative to Password Authentication, because in this mode the key itself is never sent, and thus can’t be forged. However for normal use, Password Authentication is fine.


By: Michael Chinn

July 09 2016