Installing GNS3 server on LXC container.

In this lab we will install gns3 server not directly on linux host, but on a virtualized linux OS environment running inside an LXC container.

Usually hypervisors like VMware, VirtualBox, KVM,… virtualize machines running a guest OS, but they rely on the additional layer of the hypervisor to do that.

That’s not the case of LXC. It uses the underlying linux Kernel capabilities. An LXC container runs directly on the host OS.

This reminds me of type-1 native virtualization type.

The picture below illustrates the differences and the similarities between the traditional hypervisor-based virtualizationand container-based virtualization.

Often, the terms LXC and LXD are used interchangeably, but to be more accurate:

  • LXD is the CLI client application used to manage the containers.
  • LXC is the low level daemon used to access the kernel cgroups/namespaces capabilities.

Note:

LXC or LXC/LXD sometimes spelled individually “el ex see”, “el ex dee” or  “lexy lexdy”

Differences and advantages of LXC over Docker containers:

The main difference between the two container technologies is that LXC containerizes an entire OS environement with independent file system where Docker is oriented to virtualize micro-services (single processes & applications).

For the other differences, here is a self-explanatory summary table: 

The topology

This is how things will be connected:

Installation of LXC/LXD on the server host

sudo apt update && sudo apt-get install lxd lxd-client

After the first installation, we need to initialize LXC to set the storage and networking parameters:

sudo lxd init
Do you want to configure a new storage pool (yes/no) [default=yes]? no
Would you like LXD to be available over the network (yes/no) [default=no]? yes
Address to bind LXD to (not including port) [default=all]:
Port to bind LXD to [default=8443]:
Trust password for new clients:
Again:

Note:

If you are not prompted to configure lxc networking (bridge, ipv4, ipv6 addresses…), explicitly call the networking package configurator.

sudo dpkg-reconfigure -p medium lxd

Now, we need to install a remote image repository from which we will download the container OS image:

sudo lxc remote add rimages images.linuxcontainers.org
Generating a client certificate. This may take a minute...
If this is your first time using LXD, you should also run: sudo lxd init
To start your first container, try: lxc launch ubuntu:16.04

List all available repositories

sudo lxc remote list
+-----------------+------------------------------------------+---------------+--------+--------+
|      NAME       |                   URL                    |   PROTOCOL    | PUBLIC | STATIC |
+-----------------+------------------------------------------+---------------+--------+--------+
| images          | https://images.linuxcontainers.org       | simplestreams | YES    | NO     |
+-----------------+------------------------------------------+---------------+--------+--------+
| local (default) | unix://                                  | lxd           | NO     | YES    |
+-----------------+------------------------------------------+---------------+--------+--------+
| rimages         | https://images.linuxcontainers.org:8443  | lxd           | YES    | NO     |
+-----------------+------------------------------------------+---------------+--------+--------+
| ubuntu          | https://cloud-images.ubuntu.com/releases | simplestreams | YES    | YES    |
+-----------------+------------------------------------------+---------------+--------+--------+
| ubuntu-daily    | https://cloud-images.ubuntu.com/daily    | simplestreams | YES    | YES    |
+-----------------+------------------------------------------+---------------+--------+--------+

 Creating LXC container for GNS3 server

Start a new ubuntu container container named “gns3-server1”

sudo lxc launch ubuntu:16.04 gns3-server1
Creating gns3-server1
Starting gns3-server1

List the created container

sudo lxc list
+--------------+---------+----------------------+-----------------------------------------------+------------+-----------+
|     NAME     |  STATE  |         IPV4         |                     IPV6                      |    TYPE    | SNAPSHOTS |
+--------------+---------+----------------------+-----------------------------------------------+------------+-----------+
| gns3-server1 | RUNNING | 10.230.44.115 (eth0) | fd1f:3af1:2cd0:c175:216:3eff:fe21:4fe0 (eth0) | PERSISTENT | 0         |
+--------------+---------+----------------------+-----------------------------------------------+------------+-----------+


For more information about the created container, use the “info” option

sudo lxc info gns3-server1
Name: gns3-server1
Remote: unix://
Architecture: x86_64
Created: 2017/12/05 09:50 UTC
Status: Running
Type: persistent
Profiles: default
Pid: 6870
Ips:
  eth0: inet 10.230.44.115 veth2IO309
  eth0: inet6 fd1f:3af1:2cd0:c175:216:3eff:fe21:4fe0 veth2IO309
  eth0: inet6 fe80::216:3eff:fe21:4fe0 veth2IO309
  lo: inet 127.0.0.1
  lo: inet6 ::1
Resources:
  Processes: 27
  Memory usage:
    Memory (current): 42.09MB
    Memory (peak): 164.54MB
  Network usage:
    eth0:
      Bytes received: 4.73kB
      Bytes sent: 2.21kB
      Packets received: 42
      Packets sent: 19
    lo:
      Bytes received: 0B
      Bytes sent: 0B
      Packets received: 0
      Packets sent: 0


Ping the container IP address:

ping -c 5 10.230.44.115
PING 10.230.44.115 (10.230.44.115) 56(84) bytes of data.
64 bytes from 10.230.44.115: icmp_seq=1 ttl=64 time=0.080 ms
64 bytes from 10.230.44.115: icmp_seq=2 ttl=64 time=0.044 ms
64 bytes from 10.230.44.115: icmp_seq=3 ttl=64 time=0.043 ms
64 bytes from 10.230.44.115: icmp_seq=4 ttl=64 time=0.039 ms
64 bytes from 10.230.44.115: icmp_seq=5 ttl=64 time=0.036 ms

--- 10.230.44.115 ping statistics ---
5 packets transmitted, 5 received, 0% packet loss, time 4091ms
rtt min/avg/max/mdev = 0.036/0.048/0.080/0.017 ms

You can execute a command inside the container and exit right after:

sudo lxc exec gns3-server1 -- ip a
[sudo] password for ajn:
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
12: eth0@if13: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
   link/ether 00:16:3e:21:4f:e0 brd ff:ff:ff:ff:ff:ff link-netnsid 0
   inet 10.230.44.115/24 brd 10.230.44.255 scope global eth0
      valid_lft forever preferred_lft forever
   inet6 fd1f:3af1:2cd0:c175:216:3eff:fe21:4fe0/64 scope global mngtmpaddr dynamic
      valid_lft 3148sec preferred_lft 3148sec
   inet6 fe80::216:3eff:fe21:4fe0/64 scope link
      valid_lft forever preferred_lft forever

Installing GNS3 server inside the LXC container:

To open a shell in the container:

sudo lxc exec gns3-server1 /bin/bash

Now you are inside the container environment

Let’s now check the connectivity with the outside world:

ping -c 5 google.fr
PING google.fr (216.58.219.227) 56(84) bytes of data.
64 bytes from lga25s41-in-f3.1e100.net (216.58.219.227): icmp_seq=1 ttl=56 time=2.08 ms
64 bytes from lga25s41-in-f3.1e100.net (216.58.219.227): icmp_seq=2 ttl=56 time=2.07 ms
64 bytes from lga25s41-in-f3.1e100.net (216.58.219.227): icmp_seq=3 ttl=56 time=2.06 ms
64 bytes from lga25s41-in-f3.1e100.net (216.58.219.227): icmp_seq=4 ttl=56 time=2.05 ms
64 bytes from lga25s41-in-f3.1e100.net (216.58.219.227): icmp_seq=5 ttl=56 time=2.03 ms
 
--- google.fr ping statistics ---
5 packets transmitted, 5 received, 0% packet loss, time 4005ms
rtt min/avg/max/mdev = 2.038/2.063/2.084/0.059 ms



Download the install script and install gns3 server without VPN option

cd /tmp
curl https://raw.githubusercontent.com/GNS3/gns3-server/master/scripts/remote-install.sh > gns3-remote-install.sh

Install the server without openvpn options

bash gns3-remote-install.sh --with-iou --with-i386-repository

You need to login to your docker hub account

docker login
Login with your Docker ID to push and pull images from Docker Hub. If you don't have a Docker ID, head over to https://hub.docker.com to create one.
Username: ajnouri
Password:
Login Succeeded

After the successful installation of GNS3 server, exit the lxc container

exit

On the server host, install OpenVPN package

apt-get install openvpn

Generate the static secret key

openvpn --genkey --secret secret.key

Start an OpenVPN server as deamon with the generated static key

openvpn \
--ifconfig  172.16.253.1  172.16.253.2  \
--dev tun \
--secret secret.key \
--daemon \
--log /tmp/openvpnserver.log \
--route 192.168.0.0 255.255.255.0

172.16.253.1 and 172.16.253.2 are the tunnel private ip addresses in the server and client. They need to be mirrored on the client side.

192.168.0.0/24 is the private subnet on the client that need to be reachaed from the server. 

Copy the static secret key to the client

scp secret.key ajn@X.X.143.38:/openvpn/secret.key
The authenticity of host 'X.X.143.38 (X.X.143.38)' can't be established.
ECDSA key fingerprint is SHA256:6H74AI6ei4yhhNNl7OuFxNcRtOq3Ha0KHSTaFsLffIw.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added 'X.X.143.38' (ECDSA) to the list of known hosts.
ajn@X.X.143.38's password:
 

secret.key                                                                 100%  636     0.6KB/s   00:00    

Client host configuration

In this case the client can be a baremetal or a traditional hypervisor-based VM on which OS and GNS3 GUI are installed.

Inside the client directory where the secret static key is copied, start openvpn session to the server

openvpn \
--ifconfig  172.16.253.2  172.16.253.1  \
--dev tun \
--remote X.X.72.185 \
--secret secret.key \
--daemon \
--log /tmp/openvpnclient.log
--route 10.97.46.0 255.255.255.0

X.X.72.185 is the server host Public IP.

10.97.46.0/24 is the private subnet used by the LXC container on the server host.

Check the state of the OpenVPN session

sudo cat /tmp/openvpnclient.log
Fri Dec 29 14:39:10 2017 OpenVPN 2.3.4 x86_64-pc-linux-gnu [SSL (OpenSSL)] [LZO] [EPOLL] [PKCS11] [MH] [IPv6] built on Jun 26 2017
Fri Dec 29 14:39:10 2017 library versions: OpenSSL 1.0.1k 8 Jan 2015, LZO 2.08
Fri Dec 29 14:39:10 2017 TUN/TAP device tun0 opened
Fri Dec 29 14:39:10 2017 do_ifconfig, tt->ipv6=0, tt->did_ifconfig_ipv6_setup=0
Fri Dec 29 14:39:10 2017 /sbin/ip link set dev tun0 up mtu 1500
Fri Dec 29 14:39:10 2017 /sbin/ip addr add dev tun0 local 172.16.253.2 peer 172.16.253.1
Fri Dec 29 14:39:10 2017 UDPv4 link local (bound): [undef]
Fri Dec 29 14:39:10 2017 UDPv4 link remote: [AF_INET]X.X.72.185:1194
Fri Dec 29 14:39:20 2017 Peer Connection Initiated with [AF_INET]X.X.72.185:1194
Fri Dec 29 14:39:21 2017 Initialization Sequence Completed

Notice in the log file, the session with the server is established

From the client host, check the routing table for the subnet used by LXC container on the remote server. 

ip r
default via 192.168.0.254 dev ovsbr0
10.20.20.0/24 dev vmnet1  proto kernel  scope link  src 10.20.20.1
10.97.46.0/24 via 172.16.253.1 dev tun0

Let’s ping the remote server lxc container IP where GNS3 server is installed:

$ ping 10.97.46.15
PING 10.97.46.15 (10.97.46.15) 56(84) bytes of data.
64 bytes from 10.97.46.15: icmp_seq=1 ttl=63 time=85.1 ms
64 bytes from 10.97.46.15: icmp_seq=2 ttl=63 time=84.8 ms
64 bytes from 10.97.46.15: icmp_seq=3 ttl=63 time=84.8 ms
64 bytes from 10.97.46.15: icmp_seq=4 ttl=63 time=84.5 ms
64 bytes from 10.97.46.15: icmp_seq=5 ttl=63 time=84.9 ms
^C

--- 10.97.46.15 ping statistics ---
5 packets transmitted, 5 received, 0% packet loss, time 4006ms
rtt min/avg/max/mdev = 84.566/84.866/85.114/0.318 ms

Bingo!

Now that the remote GNS3 server IP is reacheable from the client host, we need to configure GNS3 GUI with the server IP




The remote server should appear in the list of servers:

Caveat:

When trying to drop one of the installed container in the remote LXC server you might encouter this error:

I just had to try a couple of times for it to work.

Install and drop into the canvas a couple of containers and configure them with static IPs.

Start the lab and check the connectivity.

That’s all folks!!

I hope you find it useful.

References: