Dec 30

IOS + Linux = Quagga

Posted by Alex Juncu

Cisco IOS’s shell is a popular interface for devices in the networking world. But also in the network world, there are a lot of Linux/Open Source fans. The Quagga open source project tries to bring together IOS and Linux, by providing an IOS-like interface for configuring Linux’s interfaces, routing table and firewall, along side its own implementations of RIP, OSPF and BGP daemons.

The Quagga Software Routing Suite comes as a set of daemos. The main one is the zerbra daemon (Zebra is the old name of the project). This core daemon does the interaction with the Linux kernel and, also, with other daemons like ripd (RIP daemon), ospfd (OSPF daemon), bgpd (BGP daoemon). Quagga is modular, so you can implement new protocols if needed via a standard API.

To configure Quagga, you first need to start the daemons (at least the core one), in the /etc/quagga/daemons file. Each daemon has its own configuration file (ex. /etc/quagga/zebra.conf, /etc/quagga/ripd.conf etc.). Accessing the IOS-like shell is done via the vtysh command. Once in this shell, most commands available in Cisco’s IOS are available.

Router / # cd
Router ~ # vtysh

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

Router# conf t
Router(config)# hostname  LinuxRouter
LinuxRouter(config)# exit
LinuxRouter# show ?
bgp             BGP information
clns            clns network information
daemons         Show list of running daemons
debugging       State of each debugging option

[...]

Keep in mind that some things are not 100% identical to a Cisco router (ex. the interface names). Here’s an example of how to configure an interface.

LinuxRouter# conf t
LinuxRouter(config)# interface  eth0
LinuxRouter(config-if)# ip address  141.85.42.1 ?
A.B.C.D/M  IP address (e.g. 10.0.0.1/8)
LinuxRouter(config-if)# ip address  141.85.42.1/24
LinuxRouter(config-if)# link-detect

Monitor output (show commands) are similar aside some Linux specific details (ex. Kernel routes are available in Linux, but not in IOS).

Router# sh ip route
Codes: K – kernel route, C – connected, S – static, R – RIP, O – OSPF,
I – ISIS, B – BGP, > – selected route, * – FIB route

K * 0.0.0.0/0 via 192.0.2.1, venet0 inactive
O 10.10.12.0/24 [110/10] is directly connected, eth0, 00:03:41
C>* 10.10.12.0/24 is directly connected, eth0
O 10.10.14.0/24 [110/10] is directly connected, eth1, 00:03:36
C>* 10.10.14.0/24 is directly connected, eth1
O>* 10.10.23.0/24 [110/20] via 10.10.12.2, eth0, 00:02:46
O>* 10.10.24.0/24 [110/20] via 10.10.12.2, eth0, 00:02:14
*via 10.10.14.4, eth1, 00:02:14
O>* 10.10.25.0/24 [110/20] via 10.10.12.2, eth0, 00:02:41
O>* 10.10.35.0/24 [110/30] via 10.10.12.2, eth0, 00:01:21
* via 10.10.14.4, eth1, 00:01:21
O>* 10.10.45.0/24 [110/20] via 10.10.14.4, eth1, 00:02:08
C>* 127.0.0.0/8 is directly connected, lo
C>* 127.0.0.1/32 is directly connected, venet0
C>* 172.10.10.0/32 is directly connected, venet0
K>* 192.0.2.1/32 is directly connected, venet0

Configuring a routing protocol instance is also similar:

LinuxRouter# conf t
LinuxRouter(config)# router ospf
LinuxRouter(config-router)# network  192.168.123.0/0 area 0

As you can see, coming from an IOS background, this tool is very easy to use on your Linux box. It is far from perfect since it doesn’t have the years in production like IOS or iproute2, but it is cool to test out.

Dec 13

Unlike Linux’s iptables, Cisco’s filtering via Access Control Lists sometimes has hidden behavior.

Let us test how ACL filtering works using the following topology. We assume that we have Layer 3 connectivity via static routes. We will apply ACLs on the outbound direction of F1/0 on R2 (we want it to be somewhere in the path from R1 to R3)

3r

With no ACLs applied anywhere, all traffic will flow.

R1#ping 3.3.3.3 source 1.1.1.1
Packet sent with a source address of 1.1.1.1
!!!!!
Success rate is 100 percent

Let’s start with the basics and make a classic standard access list that denies R1’s loopback.

R2(config)#access-list 42 deny host 1.1.1.1
R2(config)#int f1/0
R2(config-if)#ip access-group 42 out

The loopback on R1 is blocked…

R1#ping 3.3.3.3 source 1.1.1.1
U.U.U
Success rate is 0 percent (0/5)

… but so is any other traffic that goes out of R2’s F1/0.

R1#ping 3.3.3.3 source F0/0
U.U.U
Success rate is 0 percent (0/5)

The first rule of Cisco’s ACLs is that there is an implicit deny (ip) all (all) rule at the end of every ACL. But this is not visible anywhere. You have to know it.

R2#sh access-lists
Standard IP access list 42
10 deny   1.1.1.1 (8 matches)
Extended IP access list BLOCK_HTTP

But if that ACL is empty? What if you apply an access list that does not contain any rules (was not declared)?

R2(config)#int f1/0
R2(config-if)#ip access-group 28 out
R2(config-if)#do sh access-lists
Standard IP access list 42
10 deny   1.1.1.1 (8 matches)
Extended IP access list BLOCK_HTTP

R1#ping 3.3.3.3 source 1.1.1.1

Type escape sequence to abort.
!!!!!
Success rate is 100 percent

Traffic passes. The inexistent ACL applied on an interface is ignored. But this is because you can’t have an empty classical (numbered) ACL. What if you do the same thing with a named ACL?

R2(config)#ip access-list standard EMPTY_ACL
R2(config-std-nacl)#exit
R2(config)#do sh ip access-list
Standard IP access list 42
10 deny   1.1.1.1 (8 matches)
Standard IP access list EMPTY_ACL
Extended IP access list BLOCK_HTTP
R2(config)#int f1/0
R2(config-if)#ip access-group EMPTY_ACL out

R1#ping 3.3.3.3 source 1.1.1.1

Type escape sequence to abort.
!!!!!
Success rate is 100 percent

Traffic is still not filtered. So, the rule is that a empty (inexistant or deleted)  ACL is ignored by the interface filter.

One more ACL applied on R2 with a deny all rule (no traffic should pass out of F1/0).

R2(config)#ip access-list standard DENY_ALL_ACL
R2(config-std-nacl)#deny any
R2(config-std-nacl)#do sh ip access
Standard IP access list 42
10 deny   1.1.1.1 (8 matches)
Standard IP access list DENY_ALL_ACL
10 deny   any (8 matches)
Standard IP access list EMPTY_ACL
10 deny   any (8 matches)
Extended IP access list BLOCK_HTTP
R2(config-std-nacl)#int f1/0
R2(config-if)#ip access-group DENY_ALL_ACL out

Ping form R1 is filtered.

R1#ping 3.3.3.3 source 1.1.1.1
Packet sent with a source address of 1.1.1.1
U.U.U
Success rate is 0 percent (0/5)

Since no traffic should go out the interface, a ping from R2 to R3 should also fail, yet it doesn’t.

R2#ping 3.3.3.3
!!!!!
Success rate is 100 percent (5/5), round-trip min/avg/max = 8/20/44 ms

As a final rule, traffic generated by a router is never filtered by an ACL applied any interface of that router.