We have touched on several areas in which Cisco routers, switches and Linux machines can work together to make a heterogeneous network. In this article we’ll look at an obvious part of the integration: dynamic routing. It’s not a big surprise that there exists routing software for Linux, and maybe the most known is Quagga (formerly Zebra), which provides all of the routing protocols mentioned in CCNA except EIGRP. Quagga is modular: each protocol is controlled by a separate daemon (for example ripd or ospfd) and they have separate configuration files. We can use a handy tool called vtysh which provides access to the configuration of them, moreover its syntax is very close to Cisco CLI.
We’ll use three Debian PCs in our labs, so the first thing is to install Quagga in VirtualBox on a Debian virtual machine, then another necessary package called uml-utilities which provides a tool (tunctl) to simulate physical NICs. Then clone this VM twice. I made linked clones as this type requires less space on disk. Then we can build our topology in GNS3:
I used the feature of GNS3 of inserting pictures to include cloud images. The VMs have regular NICs, but to simulate other networks (for example the RIP domain) we’ll use special interfaces also which can be made by the tunctl utility. Configure the IP addressing – on every segment the Cisco devices has the first useable address, on the 10.3.3.0/24 network the Debian1 node. As can be deducted from the image, we’ll use mostly OSPF in the network, with multiple areas, but we have a RIP segment also.
Our first task is to set up quagga for the first time. After installing the package we can find configuration files in the /etc/quagga directory. In the daemons file we have to enable zebra (the main daemon), ripd and ospfd. These daemons require a configuration file, which can be copied from /usr/share/doc/quagga/examples directory: for example, copy the zebra.conf.sample from here to /etc/quagga/zebra.conf. After this we need to change the ownership of these files from root to quagga user (we cannot save the running configuration without this):
chown quagga zebra.conf
Now we can start them by service quagga restart – we should see the three daemons starting. After this we can already access them by telnetting to the proper port, which can be determined by the following command:
Try to access the zebra daemon (we can use the name or the port instead its number):
So far we don’t see too much difference from a Cisco router in the command syntax. The first main difference is that we cannot configure routing protocols from here, because each protocol has its own daemon. But this is not the only method to configure. We have the vtysh tool, which provides the familiar method to configure the whole router. In order to use it, create the /etc/quagga/vtysh.conf with the following content:
The service integrated-vtysh-config setting is commented out in order to use separate configuration files to every routing daemon. Save this file then put the following line at the end of the .bashrc file at our home directory (without this you have to hit “Q” after issuing any command):
Now start a new terminal and issue the vtysh command. If everything went well, we can access all configuration options from one place as it’s common in a Cisco router.
After a quick ping-test of reachability among the neighbors we can start basic routing configuration. Let’s start with RIP on R2. Let’s create a loopback interface with an IP address of 192.168.1.1/24 then advertise the connected networks by RIPv2. Now go to Debian1 and configure RIP:
Some differences can be seen here with Cisco syntax: we have to provide the netmask in CIDR notation. Moreover, we don’t have the no auto-summary command: quagga advertises the correct subnet information without this. Check the result on Debian1:
The network simulated by the Loopback0 interface appeared – good! We can issue the show ip rip command on quagga to get more information.
Now go on with OSPF on Debian1:
As can be seen, we don’t need to specify OSPF process ID, and instead of wildcard mask we use netmasks. Let’s continue on our router R1:
I advertised all connected networks with one command, and soon the adjacency came up. If we list the routing table, we should see the 10.3.3.0/24 network advertised by Debian1.
Next redistribute the RIP network into OSPF on Debian1:
As we can see, the metric and metric type (external type 1 or 2) can be tuned also. If we don’t add any options, OSPF redistributes the RIP networks as E2 type routes with the metric of 20. Experiment with the other settings also!
OK, now continue on to Debian2 with OSPF. Because we don’t have real network connection in area 51, we’ll simulate one with a so-called TAP interface: it’s a logical interface just like loopbacks on Cisco routers and can be created by the tunctl command. If we use the syntax tunctl –t iface_name, then we can create interfaces with fancy names, anyway we’ll get interface names with the prefix of “tap.” Create an interface and give it the address 172.16.0.1/24, then configure OSPF:
On the R1 router we can immediately see if the adjacency comes up, and we can use the familiar commands on quagga to check OPSF neighbors, database, interfaces and the routing table – of course, the output is not exactly the same as on Cisco routers. For example, quagga doesn’t indicate inter-area routes in the routing table like Cisco by the “IA” flag. Moreover, the same routes advertised by OSPF and that are connected all appear in the show ip route output, but if we issue the standard ip route list command from Linux CLI, only the network entries with best metric appears.
Now we have enough working devices to do some ping tests, for example start with pinging 172.16.0.1 from R2. This won’t succeed in this stage, because we didn’t redistribute the OSPF routes into RIP on Debian1. Issue the redistribute ospf command in RIP router configuration mode then check the routing table on R2: the routes should be there, but pinging is still not workin. Its reason is that IP forwarding is disabled within quagga by default: a significant difference from a Cisco router. Issue the ip forwarding command on all quagga instances, and try pinging again. Maybe the ping still doesn’t wor, but if we do an extended ping with 192.168.1.1 as source address, it should succeed. What can be the problem? The solution is that R2 sends ICMP packets from the source address of 192.168.0.1 by default, and this network is missing from the routing table of Debian2. Why? It’s because we didn’t advertise it by OSPF nor as a connected network by redistribution. So if we issue the redistribute connected command on Debian1 in OSPF configuration mode, this ping should succeed also. Let’s finish the configuration with Debian3 and check the results with show commands on every device!
Some word about logging inside quagga: we can use several logging methods (using the log command). I recommend the file method. For example, I put the following line into the .conf files:
log file /var/log/quagga/daemon_name.log
This way we can see the events from all routing daemons in separate log files.
Our next task is to manipulate the OSPF cost. First check the interface cost values in quagga, for example on Debian2:
We can discover a strange thing: the bandwidth is 0 Kbit; despite this the OSPF cost is 10. We can modify this of course:
Before we continue, set the bandwidth of all Ethernet interfaces to 100 Mbit on the Linux routers.
We can set the reference bandwidth also. On Cisco routers this is 100 Mbit/s, so set this value on the Linux nodes also:
Now all of our devices are in sync regarding the OSPF cost calculation.
If we check the routing table on Debian1, we can see that the 172.16.0.0/24 network can be reached via Debian2. Let’s modify this! Physically we can reach that network via R1 also, so let’s configure our system to do some load balancing: let this route appear in the routing table of Debian1. The reason is the route via R1 is not in the routing table is that its cost is higher than the actual best cost. How much is that? If we leave Debian1 via eth0 and reach R1, we have the cost of 1; when we continue our trip towards Debian2, we leave R1 via Fa0/1 and our cost is now increased by 1, so it’s 2 now; and finally we arrive at Debian2 and leave it via loop1 to enter the 172.16.0.0/24 network: it means plus 1, so the summary of the cost is 3. If we can achieve that the cost via eth1 equals to the cost via eth0 on Debian1, than these routes both will be in the routing table. So we need to increase the current cost of 2 to 3 on eth1, then check the routing table:
As can be seen, both routes appeared in the routing table.
In the next part let’s intervene to the DR/BDR election. As our connections are all broadcast type, the election occurs and we can check the outcome, for example on Debian1:
Try to achieve that Debian1 is the DR on all connected segment. We have several methods: to modify the interface priorities or set the router ID to a higher value than the neighbors. The simplest method can be the setting of the OSPF router ID:
We’re not ready yet – we need to restart the OSPF process on the neighbors also to restart the election process from the beginning. We don’t have the clear ip ospf process command on quagga, so we have to save the configuration first then exit from vtysh and issue the service quagga restart command. When all devices come back online, check the neighbors again on Debian1: both of them are in “Backup” state now which means that Debian1 is the DR.
To increase security it’s always a good practice to set up authentication in routing protocols. OSPF supports 3 types of authentication (although one of them is NULL authentication). Let’s configure our network in the following way: configure Type2 (or MD5) authentication between R1 and Debian3, and Type1 (or simple password) authentication between the other routers. Start with R1 and configure MD5 authentication:
Now go to Debian3 and enter the following:
The syntax is almost the same. If we type quickly, maybe the adjacency remains intact, but soon the others on R1 (with Debian1 and Debian2) will go down as the dead timer expires. Let’s continue on R1 with Type1 authentication:
The configuration on the Linux neighbors is the following:
As we can see the configuration of authentication configuration commands are quite similar. On Debian2 we didn’t configure authentication in area 51 but there’s no real connection.
Our example shows that we can mix the authentication types in the network. Another feature that increases security and reduces traffic is passive interface. On passive interfaces the routing protocols doesn’t send out updates and hellos, so for example OSPF cannot form an adjacency through such interfaces, but still advertises networks connected to them. In our topology there’s not too many places where we can use this, only loop1 interface on Debian2. Make it passive and observe that other routers still know about the connected 172.16.0.0/24 network:
OSPF uses some timers in the “hello” protocol; the most important ones are hello and dead timers. We can check their values by the show ip ospf interface command, and if for some reason we want to adjust them, we can do this also. One very important thing: the hello and dead timer values are included in the hello packets and if they don’t match, the adjacency cannot be established. Let’s modify the hello and dead timers on eth0 in Debian1 to 20 and 40 seconds respectively:
If we wait we can see that R1 drops the adjacency, but when we set the same timer values on Fa0/0 it’ll come back again.
Last but not least let’s configure a default route on Debian3 and advertise it by OSPF. In order to do this we need to create a TAP interface on Debian3 by tunctl. In quagga give the IP address of 192.0.2.1/24 and set up the default route via this interface. Then advertise this within OSPF:
Now check the results on Debian1 (partial output):
In the end we can say that using quagga is not so difficult if someone is already familiar with Cisco CLI syntax (although there are minor differences). This little article is not enough to show all the features, so I encourage everybody to get to know and experiment with this useful software.
A very good tutorial on Quagga:http://openmaniak.com/quagga_tutorial.php
Thorough description of the software:http://www.nongnu.org/quagga/docs/docs-info.html