Quagga is a set of tools that allow implementing OSPF, RIP, and BGP routing protocols on a Linux system, managing the routing table of the system kernel. It uses an interface and syntax similar to that used in CISCO routers, so if we are familiar with them, configuring Quagga will be very easy.
In this mini how-to, we will assume that we have the following scenario: three independent networks with internal addressing and access to the outside, each network communicates through an exit router with a single WAN IP address. Additionally, in each network, we will have a server that will act as an interconnection nexus between internal networks through tunnels created with vtun. In each internal network where there is a server acting as a server-vtun, we must redirect the port used by vtun to that server. In my case, in kr0m and zoiber.
In the tunnel network, we will publish the routes through OSPF, achieving high availability. That is, if an interconnection server fails, the traffic will be carried by the other with the consequent delay. On the other hand, in the internal networks, we will publish the remote routes through RIP and install quagga on client PCs to “assimilate” the routes learned by RIP.
The final result will be that all internal networks will be able to communicate with each other transparently for the PCs, and in case of problems with any interconnection server, the traffic will be sent through the alternative route. We could say that we will achieve a VPN with redundancy.
In the diagram, we can see the names of the client PCs of each internal network as well as the network configuration. On the other hand, in the interconnection nodes, we see their names, the tunnel interface IPs, and the configuration of the interfaces belonging to each of the internal networks.
On the right, the internal structure of Quagga can be seen, where we can see that each daemon is responsible for a specific routing protocol, which informs Zebra, and it is this that pushes the routes into the operating system’s routing table.
Let’s start at the beginning, installing the necessary software:
Kr0m
options {
port 9000; # Listen on this port.
# Syslog facility
syslog daemon;
# Path to various programs
ifconfig /bin/ifconfig;
route /bin/route;
firewall /sbin/iptables;
ip /bin/ip;
}
# Default session options
default {
compress no; # Compression is off by default
encrypt no;
speed 0; # By default maximum speed, NO shaping
}
zoiber_kr0m {
passwd 4lf43xp10it;
type ether;
device vtap0;
proto tcp;
keepalive yes;
persist yes;
compress no;
encrypt yes;
up {
ip "link set %% up multicast on";
ip "-family inet addr add 10.10.0.1/30 dev %%";
};
down {
ifconfig "%% down";
};
}
m4s4cr3_kr0m {
passwd 4lf43xp10it;
type ether;
device vtap1;
proto tcp;
keepalive yes;
persist yes;
compress no;
encrypt yes;
up {
ip "link set %% up multicast on";
ip "-family inet addr add 10.10.1.1/30 dev %%";
};
down {
ifconfig "%% down";
};
}
--server-- 9000
rc-update add vtun default
Zoiber
options {
port 9000; # Listen on this port.
# Syslog facility
syslog daemon;
# Path to various programs
ifconfig /bin/ifconfig;
route /bin/route;
firewall /sbin/iptables;
ip /bin/ip;
}
# Default session options
default {
compress no; # Compression is off by default
encrypt no;
speed 0; # By default maximum speed, NO shaping
}
zoiber_kr0m {
passwd 4lf43xp10it;
type ether;
device vtap0;
proto tcp;
keepalive yes;
persist yes;
compress no;
encrypt yes;
up {
ip "link set %% up multicast on";
ip "-family inet addr add 10.10.0.2/30 dev %%";
};
down {
ifconfig "%% down";
};
}
m4s4cr3_zoiber {
passwd 4lf43xp10it;
type ether;
device vtap1;
proto tcp;
keepalive yes;
persist yes;
compress no;
encrypt yes;
up {
ip "link set %% up multicast on";
ip "-family inet addr add 10.10.2.1/30 dev %%";
};
down {
ifconfig "%% down";
};
}
--server-- 9000
zoiber_kr0m WANIP_KR0M
rc-update add vtun default
M4s4cr3
options {
port 9000; # Listen on this port.
# Syslog facility
syslog daemon;
# Path to various programs
ifconfig /bin/ifconfig;
route /bin/route;
firewall /sbin/iptables;
ip /bin/ip;
}
# Default session options
default {
compress no; # Compression is off by default
encrypt no;
speed 0; # By default maximum speed, NO shaping
}
m4s4cr3_kr0m {
passwd 4lf43xp10it;
type ether;
device vtap0;
proto tcp;
keepalive yes;
persist yes;
compress no;
encrypt yes;
up {
ip "link set %% up multicast on";
ip "-family inet addr add 10.10.1.2/30 dev %%";
};
down {
ifconfig "%% down";
};
}
m4s4cr3_zoiber {
passwd 4lf43xp10it;
type ether;
device vtap1;
proto tcp;
keepalive yes;
persist yes;
compress no;
encrypt yes;
up {
ip "link set %% up multicast on";
ip "-family inet addr add 10.10.2.2/30 dev %%";
};
down {
ifconfig "%% down";
};
}
m4s4cr3_kr0m WANIP_KR0M
m4s4cr3_zoiber WANIP_ZOIBER
rc-update add vtun default
We move on to the OSPF configuration, we must configure a router-id, this should be the IP address of an interface that never fails, a loopback interface is ideal.
We must have routing enabled at the kernel level on all interconnection nodes.
net.ipv4.ip_forward = 1
Kr0m
cp /usr/share/doc/quagga-0.99.23.1/samples/ospfd.conf.sample.bz2 /etc/quagga/
cp /usr/share/doc/quagga-0.99.23.1/samples/ripd.conf.sample.bz2 /etc/quagga/
cd /etc/quagga/
bzip2 -dc zebra.conf.sample.bz2 > zebra.con
bzip2 -dc ospfd.conf.sample.bz2 > ospfd.conf
bzip2 -dc ripd.conf.sample.bz2 > ripd.conf
rm *.bz2
chown quagga:quagga .conf
chmod 640 /etc/quagga/.conf
/etc/init.d/zebra restart
hostname Kr0m-Zebra
password 4lf43xp10it
enable password 4lf43xp10it
interface lo
ip address 10.255.255.1/32
rc-update add zebra default
hostname Kr0m-Zebra
password 4lf43xp10it
key chain ripauth
key 11
key-string 4lf43xp10it
interface lxcbr0
ip rip send version 2
ip rip receive version 2
ip rip authentication mode md5 auth-length rfc
ip rip authentication key-chain ripauth
router rip
version 2
! Habilito RIP en la interfaz LAN
network lxcbr0
! Publico por rip las redes aprendidas por OSPF, pero las redes deben ser de las indicadas en zoiber_m4s4cr3_net -> zoiber_m4s4cr3_acl
redistribute ospf route-map zoiber_m4s4cr3_net
! Filtro el trafico de salida en la LAN, esto se hace por si alguien publica rutas en la LAN que sean ignoradas, las redes deben ser de las indicadas en zoiber_m4s4cr3_acl
distribute-list zoiber_m4s4cr3-acl out lxcbr0
! Defino las ACLs:
access-list zoiber_m4s4cr3-acl permit 192.168.69.0/24
access-list zoiber_m4s4cr3-acl permit 192.168.1.0/24
access-list zoiber_m4s4cr3-acl deny any
! Defino grupos de ACLs que forma route-maps:
route-map zoiber_m4s4cr3_net permit 10
match ip address zoiber_m4s4cr3-acl
log stdout
hostname Kr0m-Zebra
password 4lf43xp10it
enable password 4lf43xp10it
interface vtap0
ip ospf cost 1
interface vtap1
ip ospf cost 2
router ospf
ospf router-id 10.255.255.1
network 10.255.255.1/32 area 0
network 10.10.0.0/30 area 0
network 10.10.1.0/30 area 0
network 192.168.40.0/24 area 0
log stdout
/etc/init.d/ripd restart
Zoiber
cp /usr/share/doc/quagga-0.99.23.1/samples/ospfd.conf.sample.bz2 /etc/quagga/
cp /usr/share/doc/quagga-0.99.23.1/samples/ripd.conf.sample.bz2 /etc/quagga/
cd /etc/quagga/
bzip2 -dc zebra.conf.sample.bz2 > zebra.conf
bzip2 -dc ospfd.conf.sample.bz2 > ospfd.conf
bzip2 -dc ripd.conf.sample.bz2 > ripd.conf
rm *.bz2
chown quagga:quagga .conf
chmod 640 /etc/quagga/.conf
/etc/init.d/zebra restart
hostname Zoiber-Zebra
password 4lf43xp10it
enable password 4lf43xp10it
interface lo
ip address 10.255.255.2/32
rc-update add zebra default
hostname Zoiber-Zebra
password 4lf43xp10it
key chain ripauth
key 11
key-string 4lf43xp10it
interface eth0
ip rip send version 2
ip rip receive version 2
ip rip authentication mode md5 auth-length rfc
ip rip authentication key-chain ripauth
router rip
version 2
! Habilito RIP en la interfaz LAN
network eth0
! Publico por rip las redes aprendidas por OSPF, pero las redes deben ser de las indicadas en kr0m_m4s4cr3_net -> kr0m_m4s4cr3_acl
redistribute ospf route-map kr0m_m4s4cr3_net
! Filtro el trafico de salida en la LAN, esto se hace por si alguien publica rutas en la LAN que sean ignoradas, las redes deben ser de las indicadas en kr0m_m4s4cr3_acl
distribute-list kr0m_m4s4cr3-acl out eth0
! Defino las ACLs:
access-list kr0m_m4s4cr3-acl permit 192.168.40.0/24
access-list kr0m_m4s4cr3-acl permit 192.168.1.0/24
access-list kr0m_m4s4cr3-acl deny any
! Defino grupos de ACLs que forma route-maps:
route-map kr0m_m4s4cr3_net permit 10
match ip address kr0m_m4s4cr3-acl
log stdout
hostname Zoiber-Zebra
password 4lf43xp10it
enable password 4lf43xp10it
interface vtap0
ip ospf cost 1
interface vtap1
ip ospf cost 2
router ospf
! Habilito OSPF en la interfaz TUNEL
ospf router-id 10.255.255.2
network 10.255.255.2/32 area 0
network 10.10.0.0/30 area 0
network 10.10.2.0/30 area 0
network 192.168.69.0/24 area 0
log stdout
/etc/init.d/ripd restart
M4s4cr3
cp /usr/share/doc/quagga-0.99.23.1/samples/ospfd.conf.sample.bz2 /etc/quagga/
cp /usr/share/doc/quagga-0.99.23.1/samples/ripd.conf.sample.bz2 /etc/quagga/
cd /etc/quagga/
bzip2 -dc zebra.conf.sample.bz2 > zebra.conf
bzip2 -dc ospfd.conf.sample.bz2 > ospfd.conf
bzip2 -dc ripd.conf.sample.bz2 > ripd.conf
rm *.bz2
chown quagga:quagga .conf
chmod 640 /etc/quagga/.conf
/etc/init.d/zebra restart
hostname M4s4cr3-Zebra
password 4lf43xp10it
enable password 4lf43xp10it
interface lo
ip address 10.255.255.3/32
rc-update add zebra default
hostname M4s4cr3-Zebra
password 4lf43xp10it
key chain ripauth
key 11
key-string 4lf43xp10it
interface enp5s2
ip rip send version 2
ip rip receive version 2
ip rip authentication mode md5 auth-length rfc
ip rip authentication key-chain ripauth
router rip
version 2
! Habilito RIP en la interfaz LAN
network enp5s2
! Publico por rip las redes aprendidas por OSPF, pero las redes deben ser de las indicadas en kr0m_zoiber_net -> kr0m_zoiber_acl
redistribute ospf route-map kr0m_zoiber_net
! Filtro el trafico de salida en la LAN, esto se hace por si alguien publica rutas en la LAN que sean ignoradas, las redes deben ser de las indicadas en kr0m_zoiber_acl
distribute-list kr0m_zoiber-acl out enp5s2
! Defino las ACLs:
access-list kr0m_zoiber-acl permit 192.168.40.0/24
access-list kr0m_zoiber-acl permit 192.168.69.0/24
access-list kr0m_zoiber-acl deny any
! Defino grupos de ACLs que forma route-maps:
route-map kr0m_zoiber_net permit 10
match ip address kr0m_zoiber-acl
log stdout
hostname M4s4cr3-Zebra
password 4lf43xp10it
enable password 4lf43xp10it
interface vtap0
ip ospf cost 1
interface vtap1
ip ospf cost 2
router ospf
! Habilito OSPF en la interfaz TUNEL
ospf router-id 10.255.255.3
network 10.255.255.3/32 area 0
network 10.10.1.0/30 area 0
network 10.10.2.0/30 area 0
network 192.168.1.0/24 area 0
log stdout
/etc/init.d/ripd restart
NOC
hostname NOC-Zebra
password 4lf43xp10it
enable password 4lf43xp10it
hostname NOC-Zebra
password 4lf43xp10it
key chain ripauth
key 11
key-string 4lf43xp10it
interface enp0s18
ip rip authentication mode md5 auth-length rfc
ip rip authentication key-chain ripauth
router rip
version 2
network enp0s18
log stdout
chown quagga:quagga .conf
chmod 640 /etc/quagga/.conf
/etc/init.d/zebra restart
/etc/init.d/ripd restart
rc-update add zebra default
rc-update add ripd default
Skynet
hostname Skynet-Zebra
password 4lf43xp10it
enable password 4lf43xp10it
hostname Skynet-Zebra
password 4lf43xp10it
key chain ripauth
key 11
key-string 4lf43xp10it
interface eth0
ip rip authentication mode md5 auth-length rfc
ip rip authentication key-chain ripauth
router rip
version 2
network eth0
log stdout
chown quagga:quagga .conf
chmod 640 /etc/quagga/.conf
/etc/init.d/zebra restart
/etc/init.d/ripd restart
rc-update add zebra default
rc-update add ripd default
Moria
hostname Moria-Zebra
password 4lf43xp10it
enable password 4lf43xp10it
hostname Moria-Zebra
password 4lf43xp10it
key chain ripauth
key 11
key-string 4lf43xp10it
interface enp5s1
ip rip authentication mode md5 auth-length rfc
ip rip authentication key-chain ripauth
router rip
version 2
network enp5s1
log stdout
chown quagga:quagga .conf
chmod 640 /etc/quagga/.conf
/etc/init.d/zebra restart
/etc/init.d/ripd restart
rc-update add zebra default
rc-update add ripd default
Now, from any internal computer within the LAN, we can transparently access the equipment of the other two lanes :)
In addition, if we cut communication in any of the interconnection nodes, the traffic will be transparently rerouted for the client.
TROUBLESHOOTING
If we want to debug RIP, we connect to the daemon as follows:
telnet localhost 2602
4lf43xp10it
show ip rip
show ip rip status
show ip protocols
debug rip events
debug rip packet
debug rip zebra
show debugging rip
On the other hand, if we want to debug OSPF:
telnet localhost 2604
4lf43xp10it
enable
4lf43xp10it
show ip ospf
show ip ospf interface IFACE
show ip ospf neighbor
show ip ospf neighbor detail
show ip ospf neighbor IFACE
show ip ospf route