Creating Dynamic Routers in Linux

In this post we will create two Virtual Machines that will act as Routers running OSPF using FRRouting which is a fork of the older Quagga package. The Routers will have one NIC acting as a gateway for PC1 and PC2 and another that connects the two together.

FRRouting (FRR) is an IP routing protocol suite for Linux and Unix platforms which includes protocol daemons for BGP, IS-IS, LDP, OSPF, PIM, and RIP.

In this Lab the software will be installed on a pair of Virtual Machines acting as Routers. They will be set up as OSPF neighbors and distribute the networks that the two other Virtual Machines, PC1 and PC2 are sat on within a single OSPF area.

Setting Static Routes

As the Virtual Machines have been created using Vagrant they have another interface for management which serves as a NAT interface to the wider internet and for ssh management from the Host. For this reason a static route will be created on both to send all traffic for the 192.168.0.0/16 range of addresses via the Host only interface.

The static route is created as a new entry in the netplan configuration within /etc/netplan/50-vagrant.yaml

vagrant@PC2:~$ cat /etc/netplan/50-vagrant.yaml 
---
network:
  version: 2
  renderer: networkd
  ethernets:
    enp0s8:
      addresses:
      - 192.168.201.1/24
      routes:
      - to: 192.168.0.0/16
        via: 192.168.201.254
        
        
vagrant@PC1:/etc/netplan$ cat /etc/netplan/50-vagrant.yaml 
---
network:
  version: 2
  renderer: networkd
  ethernets:
    enp0s8:
      addresses:
      - 192.168.200.1/24
      routes:
      - to: 192.168.0.0/16
        via: 192.168.200.254

It can be seen that the route set is slightly different on each PC but this will result in all traffic destined for any address in the 192.168.0.0/16 range being sent via the enp0s8 interface and using the enp0s9 interface on the Router Virtual Machines as their gateways.

vagrant@PC1:$ ip route
default via 10.0.2.2 dev enp0s3 proto dhcp src 10.0.2.15 metric 100 
10.0.2.0/24 dev enp0s3 proto kernel scope link src 10.0.2.15 
10.0.2.2 dev enp0s3 proto dhcp scope link src 10.0.2.15 metric 100 
192.168.0.0/16 via 192.168.200.254 dev enp0s8 proto static 
192.168.200.0/24 dev enp0s8 proto kernel scope link src 192.168.200.1 


vagrant@PC2:~$ ip route
default via 10.0.2.2 dev enp0s3 proto dhcp src 10.0.2.15 metric 100 
10.0.2.0/24 dev enp0s3 proto kernel scope link src 10.0.2.15 
10.0.2.2 dev enp0s3 proto dhcp scope link src 10.0.2.15 metric 100 
192.168.0.0/16 via 192.168.201.254 dev enp0s8 proto static 
192.168.201.0/24 dev enp0s8 proto kernel scope link src 192.168.201.1 

The routes on the two Virtual Machines confirm that all the traffic is correct and it can also be seen that the two Virtual Machines can no longer communicate because they are sat on different networks.

This can be confirmed by running tracepath to check the next-hop address and the fact there is no connection.

vagrant@PC1:~$ tracepath -n 192.168.201.1
 1?: [LOCALHOST]                      pmtu 1500
 1:  192.168.200.254                                       0.667ms 
 1:  192.168.200.254                                       0.613ms 
 2:  no reply
 3:  no reply
 4:  no reply

This is as expected and we must now set the other two Virtual Machines to allow routing between the 192.168.200.0/24 and 192.168.201.0/24 networks that will allow communication between the two end Virtual Machines.

Installation of FRR Routing

There are numerous ways of installing FRRouting but in the case of this Lab we will install the snap version of the application. This is done using a simple snap command on each of the Virtual Machines that will be acting as our routers.

sudo snap install frr

Once the snap has been installed it is necessary to run the following to link the snap to the Virtual Machine to allow it the necessary control.

sudo snap connect frr:network-control core:network-control

Once this is done then we also need to enable the forwarding of packets within the kernel.

This is done by un-commenting the following line in /etc/sysctl.cnf

# Uncomment the next line to enable packet forwarding for IPv4
net.ipv4.ip_forward=1

# Uncomment the next line to enable packet forwarding for IPv6
#  Enabling this option disables Stateless Address Autoconfiguration
#  based on Router Advertisements for this host
net.ipv6.conf.all.forwarding=1

The configuration for setting up FRRouting is very similar to a Cisco IOS Router and a vty session can be started by running

vagrant@R1:~$ sudo frr.vtysh 

Hello, this is FRRouting (version 7.2.1).
Copyright 1996-2005 Kunihiro Ishiguro, et al.

R1# 
R1# 
R1# 
R1# configure terminal 
R1(config)# router ospf
R1(config-router)# network 192.168.100.0/24 area 0
R1(config-router)# network 192.168.200.0/24 area 0
R1(config-router)# 

vagrant@R2:~$ sudo frr.vtysh 

Hello, this is FRRouting (version 7.2.1).
Copyright 1996-2005 Kunihiro Ishiguro, et al.

R2# configure terminal 
R2(config)# router ospf
R2(config-router)# network 192.168.100.0/24 area 0
R2(config-router)# network 192.168.201.0/24 area 0

The code above allows OSPF to be setup and both interfaces to be placed into OSPF area 0.

After this is run and the equivalent on R1 the creation of an adjacency can be confirmed.

R2# show ip ospf neighbor 

Neighbor ID     Pri State           Dead Time Address         Interface            RXmtL RqstL DBsmL
1.1.1.1           1 Full/DR           36.825s 192.168.100.1   enp0s8:192.168.100.2     0     0     0

We can also check the routing table within FRRouting.

R2# show ip route 
Codes: K - kernel route, C - connected, S - static, R - RIP,
       O - OSPF, I - IS-IS, B - BGP, E - EIGRP, N - NHRP,
       T - Table, v - VNC, V - VNC-Direct, A - Babel, D - SHARP,
       F - PBR, f - OpenFabric,
       > - selected route, * - FIB route, q - queued route, r - rejected route

K>* 0.0.0.0/0 [0/100] via 10.0.2.2, enp0s3, src 10.0.2.15, 09:16:02
C>* 10.0.2.0/24 is directly connected, enp0s3, 09:16:02
K>* 10.0.2.2/32 [0/100] is directly connected, enp0s3, 09:16:02
O   192.168.100.0/24 [110/100] is directly connected, enp0s8, 00:09:44
C>* 192.168.100.0/24 is directly connected, enp0s8, 09:16:06
O>* 192.168.200.0/24 [110/200] via 192.168.100.1, enp0s8, 00:09:34
O   192.168.201.0/24 [110/100] is directly connected, enp0s9, 09:15:55
C>* 192.168.201.0/24 is directly connected, enp0s9, 09:16:06

Like Cisco IOS we can determine that the Router has had routes for the remote network injected into the Routing table by OSPF and they are via the correct next-hop address.

We can also confirm the routing table directly running on the Virtual Machine.

vagrant@R2:~$ ip route
default via 10.0.2.2 dev enp0s3 proto dhcp src 10.0.2.15 metric 100 
10.0.2.0/24 dev enp0s3 proto kernel scope link src 10.0.2.15 
10.0.2.2 dev enp0s3 proto dhcp scope link src 10.0.2.15 metric 100 
192.168.100.0/24 dev enp0s8 proto kernel scope link src 192.168.100.2 
192.168.200.0/24 via 192.168.100.1 dev enp0s8 proto 188 metric 20 
192.168.201.0/24 dev enp0s9 proto kernel scope link src 192.168.201.254 

This corresponds to the information displayed within FRRouting.

End to End Testing

We can now confirm the End to End connectivity via a combination of checking routing tables on PC1 and PC2 as well as running the tracepath command to confirm the exact path the traffic takes.

vagrant@PC1:~$ ip route
default via 10.0.2.2 dev enp0s3 proto dhcp src 10.0.2.15 metric 100 
10.0.2.0/24 dev enp0s3 proto kernel scope link src 10.0.2.15 
10.0.2.2 dev enp0s3 proto dhcp scope link src 10.0.2.15 metric 100 
192.168.0.0/16 via 192.168.200.254 dev enp0s8 proto static 
192.168.200.0/24 dev enp0s8 proto kernel scope link src 192.168.200.1 
vagrant@PC2:~$ ip route
default via 10.0.2.2 dev enp0s3 proto dhcp src 10.0.2.15 metric 100 
10.0.2.0/24 dev enp0s3 proto kernel scope link src 10.0.2.15 
10.0.2.2 dev enp0s3 proto dhcp scope link src 10.0.2.15 metric 100 
192.168.0.0/16 via 192.168.201.254 dev enp0s8 proto static 
192.168.201.0/24 dev enp0s8 proto kernel scope link src 192.168.201.1

Tracepath can also be run on PC1 and PC2.

vagrant@PC1:~$ tracepath -n 192.168.201.1
 1?: [LOCALHOST]                      pmtu 1500
 1:  192.168.200.254                                       0.500ms 
 1:  192.168.200.254                                       0.385ms 
 2:  192.168.100.2                                         0.945ms 
 3:  192.168.201.1                                         1.313ms reached
     Resume: pmtu 1500 hops 3 back 3 
vagrant@PC2:~$ tracepath -n 192.168.200.1
 1?: [LOCALHOST]                      pmtu 1500
 1:  192.168.201.254                                       0.543ms 
 1:  192.168.201.254                                       0.442ms 
 2:  192.168.100.1                                         0.850ms 
 3:  192.168.200.1                                         1.262ms reached
     Resume: pmtu 1500 hops 3 back 3 

This confirms PC1 and PC2 have full connectivity via R1 and R2, which are acting as Routers by forwarding the packets to the correct interfaces.

Removing OSPF Adjacency

The final test to prove that R1 and R2 have the correct routes injected into their routing tables via OSPF is to remove the adjacency. This is easily done by removing one of the interfaces from OSPF on one of the Routers causing the adjacency to be dropped.

This will be done on R1 by a suitable config change with FRRouting.

R1# configure terminal 
R1(config)# router ospf
R1(config-router)# no network 192.168.100.0/24 area 0
R1(config-router)# exit
R1(config)# exit
R1# show ip ospf neighbor 

Neighbor ID     Pri State           Dead Time Address         Interface            RXmtL RqstL DBsmL

R1# show ip route
Codes: K - kernel route, C - connected, S - static, R - RIP,
       O - OSPF, I - IS-IS, B - BGP, E - EIGRP, N - NHRP,
       T - Table, v - VNC, V - VNC-Direct, A - Babel, D - SHARP,
       F - PBR, f - OpenFabric,
       > - selected route, * - FIB route, q - queued route, r - rejected route

K>* 0.0.0.0/0 [0/100] via 10.0.2.2, enp0s3, src 10.0.2.15, 00:31:38
C>* 10.0.2.0/24 is directly connected, enp0s3, 00:31:38
K>* 10.0.2.2/32 [0/100] is directly connected, enp0s3, 00:31:38
C>* 192.168.100.0/24 is directly connected, enp0s8, 00:31:43
O   192.168.200.0/24 [110/100] is directly connected, enp0s9, 00:31:43
C>* 192.168.200.0/24 is directly connected, enp0s9, 00:31:43

It can be seen that removing the enp0s8 interface from OSPF causes the adjacency to be lost and the route to the remote network to be lost.

This can also be seen as a change in the Routing Table within the Virtual Machine itself.

vagrant@R1:~$ ip route
default via 10.0.2.2 dev enp0s3 proto dhcp src 10.0.2.15 metric 100 
10.0.2.0/24 dev enp0s3 proto kernel scope link src 10.0.2.15 
10.0.2.2 dev enp0s3 proto dhcp scope link src 10.0.2.15 metric 100 
192.168.100.0/24 dev enp0s8 proto kernel scope link src 192.168.100.1 
192.168.200.0/24 dev enp0s9 proto kernel scope link src 192.168.200.254 

We can also confirm the loss of the End to End connection on PC1 and PC2.

vagrant@PC1:~$ tracepath -n 192.168.201.1
 1?: [LOCALHOST]                      pmtu 1500
 1:  192.168.200.254                                       0.679ms 
 1:  192.168.200.254                                       0.643ms 
 2:  no reply
 3:  no reply
 4:  no reply
 5:  no reply
vagrant@PC2:~$ tracepath -n 192.168.200.1
 1?: [LOCALHOST]                      pmtu 1500
 1:  192.168.201.254                                       0.637ms 
 1:  192.168.201.254                                       0.630ms 
 2:  no reply
 3:  no reply
 4:  no reply

This shows there is no longer a route over the 192.168.100.0/24 network linking R1 and R2.

Conclusions

In this Lab we have set up a pair of Virtual Machines with multiple NICs running Ubuntu 18.04 that have had FRRouting installed. These machines have had IP forwarding configured allowing them to act as Routers forwarding IP packets between different IP networks.

OSPF was run as a dynamic routing protocol which allowed the discovery of the 192.168.200.0/24 and 192.168.201.0/24 on both Routers. This allowed the two end machines PC1 and PC2 to communicate via their enp0s8 interfaces.

By removing the adjacency between R1 and R2 it was proven that these routes were indeed exchanged via OSPF.

The actual configuration of FRRouting is very similar to standard Cisco IOS and is fairly easy to setup, once the IP forwarding has been configured within the Linux kernel on these machines.

While this is a simple example and not really taking advantage of a dynamic routing protocol there would be no reason that alternative routes for the traffic could not be implemented.

The lab shows the flexibility that open source and Linux can bring as it is very possible to use a machine with multiple NICs to act as a router.