Please consider donating: https://www.corelan.be/index.php/donate/


15,370 views

Using Fedora 9 as an OSPF / BGP router (Quagga / Zebra) and set up BGP between Linux and Juniper ScreenOS

In this post, I’m going to show you how to set up a Linux host (Fedora Core 9) and use it as a BGP enabled router. 

In order to fully understand the setup & configuration, please have a look at this blog post first, because I’ll use the setup in that post as a foundation for this explanation.

Initial setup : basic Fedora 9 install, 2 network cards recognized by Fedora

eth0 : 192.168.100.100, mask 255.255.255.0 – no default gateway

eth1 : 192.168.3.1, mask 255.255.255.0 – no default gateway

This is what we will build  :

bgp_with_linux1

( click to enlarge )

If you compare this drawing with the drawing in my post on BGP with ScreenOS, you’ll notice that I have simply added a linux host to the 192.168.100.0/24 network, and added a new network behind the linux host.  The idea is to set up the Linux host to become part of BGP AS 65000 (IBGP).  In a second phase, we’ll give the Linux host it’s own AS and we’ll form EBGP peers between the Linux host and one of the screenOS devices and see what the impact is. (I’ll write this procedure when I have more time in the next couple of days.  We’ll start with IBGP first)

 

Set up Quagga Routing Suite

1. Install Quagga Routing Suite

[root@router-3 /]# yum install quagga
Loaded plugins: refresh-packagekit
fedora                                                   | 2.4 kB     00:00    
updates                                                  | 2.6 kB     00:00    
Setting up Install Process
Parsing package install arguments
Resolving Dependencies
--> Running transaction check
---> Package quagga.i386 0:0.99.9-6.fc9 set to be updated
--> Finished Dependency Resolution

Dependencies Resolved

=============================================================================
 Package                 Arch       Version          Repository        Size 
=============================================================================
Installing:
 quagga                  i386       0.99.9-6.fc9     fedora            1.2 M

Transaction Summary
=============================================================================
Install      1 Package(s)         
Update       0 Package(s)         
Remove       0 Package(s)         

Total download size: 1.2 M
Is this ok [y/N]: y
Downloading Packages:
(1/1): quagga-0.99.9-6.fc9.i386.rpm                      | 1.2 MB     00:06     
Running rpm_check_debug
Running Transaction Test
Finished Transaction Test
Transaction Test Succeeded
Running Transaction
  Installing: quagga                       ######################### [1/1] 

Installed: quagga.i386 0:0.99.9-6.fc9
Complete!

2. Open /etc/services and see if the following entries are present. (On Fedora Core 9, most of these entries are present, except for ospfapi and isisd)

zebrasrv      2600/tcp          # zebra service
zebra         2601/tcp          # zebra vty
ripd          2602/tcp          # RIPd vty
ripngd        2603/tcp          # RIPngd vty
ospfd         2604/tcp          # OSPFd vty
bgpd          2605/tcp          # BGPd vty
ospf6d        2606/tcp          # OSPF6d vty
ospfapi       2607/tcp          # ospfapi
isisd         2608/tcp          # ISISd vty

3. Set quagga global configuration options

The quagga configuration files can be found at /etc/quagga

We are interested in the OSPF / BGP components of quagga, which are provided by zebra.  Thus we need to look at /etc/quagga/zebra.conf

After installing quagga, the only entry in the configuration file is the hostname. We need to add a password, otherwise the daemon will not allow us to connect to the configuration console. You can set an enable password as well, configure logging, etc

[root@router-3 quagga]# cat zebra.conf
hostname router-3
password MyBadPassword
enable password MyBadEnablePassword
log file /var/log/quagga/zebra.log informational
log stdout

You can now start the zebra daemon by running  ‘service zebra start’. You can set the daemon to start at boot time by running ‘chkconfig zebra on’

[root@router-3 quagga]# chkconfig zebra on
[root@router-3 quagga]# service zebra start
Starting zebra: Nothing to flush.
[  OK  ]
[root@router-3 quagga]# 

Verify that the daemon is running :

[root@router-3 quagga]# netstat -vantu | grep 2601
tcp        0      0 127.0.0.1:2601              0.0.0.0:*                   LISTEN 

 

4. Test if you can connect to the Quagga configuration console

[root@router-3 quagga]# telnet localhost 2601
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.

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


User Access Verification

Password: 
router-3> enable
Password: 
router-3# conf t
router-3(config)# sh 
  history         Display the session command history
  running-config  running configuration
router-3(config)# sh r

Current configuration:
!
hostname router-3
password MyBadPassword
enable password MyBadEnablePassword
log file /var/log/quagga/zebra.log informational
log stdout
!
interface eth0
 ipv6 nd suppress-ra
!
interface eth1
 ipv6 nd suppress-ra
!
interface lo
!
interface pan0
 ipv6 nd suppress-ra
!
interface sit0
 ipv6 nd suppress-ra
!
ip forwarding
!
!
line vty
!
end

 

Configure Zebra BGP to form an IBGP peer with Juniper ScreenOS (and set up full mesh with ssg5-1 and ssg5-2)

First of all, we need to look at the connectivity between the Linux host and Juniper screenOS. The Linux host is not in the same IP subnet as the 2 screenOS devices, and if you look at the previous post, you can see that connectivity between the screenOS devices and the 192.168.100.0 network is handled via OSPF.  This is fine, as long as you can make sure that connectivity between all hosts that need to become peers will work before you enable BGP. So you cannot rely on BGP to create routing between these hosts, because the routing needs to work before we can use BGP.

On ssg5-1, we can see that the route towards 192.168.100.0 is injected via OSPF (E2), which is ok. But on ssg5-2, the route is added via BGP (iB), and this may cause problems. Think about it : If you disable BGP and reenable BGP, the route will disappear, which will make the Linux host unreachable for ssg5-2, so it will not be able to reach the host again in order to become peers.

ssg5-1-> get route | incl 192.168.100.0
*      1057   192.168.100.0/24         eth0/1     192.168.0.7  E2  200     10     Root

ss5-2-> get route | incl 192.168.100.0
*        28   192.168.100.0/24         eth0/1     192.168.0.7  iB  250      0     Root

So on ssg5-2, we need to add a static route to 192.168.100.0/24, and on the Linux host, we also need to set up some routing.

ss5-2-> set route 192.168.100.0/24 gate 192.168.0.7
ss5-2-> get route | incl 192.168.100.0             
*        29   192.168.100.0/24         eth0/1     192.168.0.7   S   20      1     Root
         28   192.168.100.0/24         eth0/1     192.168.0.7  iB  250      0     Root

This will ensure that, even if BGP is down, the static route will ensure that ssg5-2 can reach the 192.168.100.0/24 network. So while the active route is the one that is distributed via BGP, the static route will take over the moment BGP goes away, ensuring connectivity at all times.

On Linux, we can either count on a default gateway that points to 192.168.100.2 in order to be able to route to the 192.168.0.0/24 network, or you can simply add a route towards the 192.168.0.0/24 network. Either way, we will need some kind of route, because this is required for the Linux host to be able to talk to the other 2 IBGP hosts (ssg5-1 : 192.168.0.8 and ssg5-2 : 192.168.0.30). We won’t use a default gateway, we’ll just do direct routing :

Edit /etc/rc.d/rc.local and add the following line to the file :

/sbin/route add -net 192.168.0.0/24 gw 192.168.100.2

After making the change, the file should look like this :

[root@router-3 /]# cat /etc/rc.d/rc.local 
#!/bin/sh
#
# This script will be executed *after* all the other init scripts.
# You can put your own initialization stuff in here if you don't
# want to do the full Sys V style init stuff.

touch /var/lock/subsys/local
/sbin/route add -net 192.168.0.0/24 gw 192.168.100.2

This will make sure the static route is available when the Linux machine boots. (a.k.a. making the route permanent)

In order to add the route to the routing table right away, simply run the command from the command prompt :

[root@router-3 /] #/sbin/route add -net 192.168.0.0/24 gw 192.168.100.2

Look at the routing table, you should see this :

[root@router-3 ~]# route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
192.168.100.0   0.0.0.0         255.255.255.0   U     0      0        0 eth0
192.168.3.0     0.0.0.0         255.255.255.0   U     0      0        0 eth1
192.168.0.0     192.168.100.2   255.255.255.0   UG    0      0        0 eth0

Or, verify the routing via the zebra daemon :

[root@router-3 ~]# telnet localhost 2601
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.

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


User Access Verification

Password: 
router-3> enable
Password: 
router-3# sh ip route
Codes: K - kernel route, C - connected, S - static, R - RIP, O - OSPF,
       I - ISIS, B - BGP, > - selected route, * - FIB route

C>* 127.0.0.0/8 is directly connected, lo
K>* 192.168.0.0/24 via 192.168.100.2, eth0
C>* 192.168.3.0/24 is directly connected, eth1
C>* 192.168.100.0/24 is directly connected, eth0

 

Furthermore, this linux host should now be able to connect to 192.168.0.8 and 192.168.0.30 :

[root@router-3 /]# ping 192.168.0.8
PING 192.168.0.8 (192.168.0.8) 56(84) bytes of data.
64 bytes from 192.168.0.8: icmp_seq=1 ttl=64 time=6.07 ms
64 bytes from 192.168.0.8: icmp_seq=2 ttl=64 time=1.75 ms
64 bytes from 192.168.0.8: icmp_seq=3 ttl=64 time=1.92 ms
^C
--- 192.168.0.8 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2160ms
rtt min/avg/max/mdev = 1.757/3.251/6.073/1.996 ms

[root@router-3 /]# ping 192.168.0.30
PING 192.168.0.30 (192.168.0.30) 56(84) bytes of data.
64 bytes from 192.168.0.30: icmp_seq=1 ttl=64 time=4.95 ms
64 bytes from 192.168.0.30: icmp_seq=2 ttl=64 time=1.91 ms
64 bytes from 192.168.0.30: icmp_seq=3 ttl=64 time=1.45 ms
^C
--- 192.168.0.30 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2406ms
rtt min/avg/max/mdev = 1.452/2.772/4.954/1.554 ms

 

Next, we need to configure the Zebra based BGP daemon on the Linux host to become an IBGP peer of AS 65000

First, let’s set all IP properties of the Linux host using the Zebra daemon :

[root@router-3 /]# telnet localhost 2601
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.

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


User Access Verification

Password: 
router-3> enable
Password: 
router-3# conf t
router-3(config)# int eth0
router-3(config-if)# ip address 192.168.100.100/24
router-3(config-if)# exit
router-3(config)# int eth1
router-3(config-if)# ip address 192.168.3.8/24
router-3(config-if)# exit
router-3(config)# exit
router-3# write
Configuration saved to /etc/quagga/zebra.conf
router-3# 

Now start the bgp daemon, so we can connect to it and set up the configuration.

[root@router-3 quagga]# service bgpd start
Starting bgpd: [  OK  ]
[root@router-3 quagga]# netstat -vantu | grep 2605
tcp        0      0 127.0.0.1:2605              0.0.0.0:*                   LISTEN
 
In order to make sure the daemon will start when the system boots, use the ‘chkconfig bgpd on’ command.
Now we are ready to set up BGP
 
[root@router-3 quagga]# telnet localhost 2605
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.

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


User Access Verification

Password: 
router-3> enable
Password: 
router-3# conf t
router-3(config)# router bgp 65000
router-3(config-router)# network 192.168.3.0/24
router-3(config-router)# neighbor 192.168.0.8 remote-as 65000
router-3(config-router)# exit                 
router-3(config)# write
Configuration saved to /etc/quagga/bgpd.conf
router-3(config)# exit
router-3# exit

At this point, the 192.168.3.0/24 network will be redistributed into BGP

There is another way of doing this, using the redistribute command, which may be more generic (but less specific if you want to) :

[root@router-3 ~]# telnet localhost 2605
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.

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


User Access Verification

Password: 
router-3> enable
Password: 
router-3# conf t
router-3(config)# router bgp 65000
router-3(config-router)# no network 192.168.3.0/24
router-3(config-router)# exit
router-3(config)# write
Configuration saved to /etc/quagga/bgpd.conf

#At this point, the 192.168.3.0 network is not being redistributed anymore. On ssg5-1 and ssg5-2, the network will be gone

#Since this is a connected net, we can redistribute this network using the redistribute command :

router-3(config-router)# redistribute connected
router-3(config-router)# exit
router-3(config)# write
Configuration saved to /etc/quagga/bgpd.conf
router-3(config)# 

 

 

Set up ScreenOS to complete the peer with the Linux router

On ssg5-1 (192.168.0.8), set up the peer as well :

ssg5-1-> set vrouter trust-vr proto bgp neighbor 192.168.100.100 remote-as 65000
ssg5-1-> set vrouter trust-vr proto bgp neighbor 192.168.100.100 enable 
ssg5-1-> get vrouter trust-vr proto bgp neighbor 
Peer AS Remote IP       Local IP          Wt Status   State     ConnID Up/Down
--------------------------------------------------------------------------------
  65000 192.168.0.30    192.168.0.8      100 Enabled  ESTABLISH      3 20:40:49
  65000 192.168.100.100 192.168.0.8      100 Enabled  ESTABLISH     38 00:01:28
ssg5-1-> get route proto bgp


IPv4 Dest-Routes for <untrust-vr> (0 entries)
--------------------------------------------------------------------------------------
H: Host C: Connected S: Static A: Auto-Exported
I: Imported R: RIP P: Permanent D: Auto-Discovered
N: NHRP
iB: IBGP eB: EBGP O: OSPF E1: OSPF external type 1
E2: OSPF external type 2 trailing B: backup route


IPv4 Dest-Routes for <trust-vr> (36 entries)
--------------------------------------------------------------------------------------
         ID          IP-Prefix      Interface         Gateway   P Pref    Mtr     Vsys
--------------------------------------------------------------------------------------
*      1072     192.168.3.0/24         eth0/1     192.168.0.7  iB  250      0     Root
*      1044     192.168.2.0/24         eth0/1    192.168.0.30  iB  250      0     Root

So the route from router-3 (Linux) has now been added into the routing table of ssg5-1, which is what we have expected

 

Verify that everyting works

On Linux, the routing table looks fine :

[root@router-3 quagga]# telnet localhost 2601
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.

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


User Access Verification

Password: 
router-3> enable
Password: 
router-3# sh ip route
Codes: K - kernel route, C - connected, S - static, R - RIP, O - OSPF,
       I - ISIS, B - BGP, > - selected route, * - FIB route

B>* 10.2.0.0/24 [200/0] via 192.168.0.8 (recursive via 192.168.100.2), 00:03:42
C>* 127.0.0.0/8 is directly connected, lo
K>* 192.168.0.0/24 via 192.168.100.2, eth0
B>* 192.168.1.0/24 [200/0] via 192.168.0.8 (recursive via 192.168.100.2), 00:03:42
C>* 192.168.3.0/24 is directly connected, eth1
B   192.168.100.0/24 [200/0] via 192.168.0.7, 00:03:42
C>* 192.168.100.0/24 is directly connected, eth0
B>* 192.168.132.0/24 [200/0] via 192.168.0.1 (recursive via 192.168.100.2), 00:03:42

As you can see, despite the fact that the linux host and ssg5-1 are not directly connected, the routes table still looks fine. Network 192.168.1.0/24, which is a connected network behind ssg5-1, shows up in the routing table as reachable via 192.168.0.8, but recursive via 192.168.100.2 – BGP has ensured that the path towards the 192.168.1.0/24 network works and figured out the next hop itself.

Now you can use the same procedure to set up more peers (peer linux with ssg5-2). This should make the 192.168.2.0/24 network visible as well

 

Ok, so the routing tables on ssg5-1, ssg5-2 and router-3 are correct. But if you try to route from ssg5-1 towards 192.168.3.8, it doesn’t seem to work !

ssg5-1-> trace-route 192.168.3.8 
Type escape sequence to escape

Send ICMP echos to 192.168.3.8, timeout is 2 seconds,  maximum hops are 32, 
1       3ms     2ms     2ms     192.168.0.7
2       *       *       *
3       *       *       *
4       *       *       *
5       *       *       *
6       Trace aborted

 

This is normal. We did not redistribute the new route (towards the 192.168.3.0/24 network) to OSPF, so router-1 doesn’t know about this new network yet

On ssg5-1, we need to create a new ACL (or edit the existing ACL) and route-map, and add this new network, so it can be redistributed from BGP into OSPF

ssg5-1-> get vrouter trust-vr route-map RedistBGPintoOSPF
Route-map (RedistBGPintoOSPF)
----------------------
        Entry (10) - Action (permit)
        ----------------------------
                Match Fields
                ------------
                ip-address:              5 (access-list)

                Set Fields
                ----------


ssg5-1-> get vrouter trust-vr route-map RedistBGPintoOSPF config
set route-map name "RedistBGPintoOSPF" permit 10
set match ip 5
exit
 
Ok, so we need to edit access-list 5
 
ssg5-1-> set vrouter trust-vr
ssg5-1(trust-vr)-> get access-list
IPv4 Access Lists
------------------------------------------------
Access list (1)
----------------
        Sequence 10: 0.0.0.0/0          -> Permit
Access list (5)
----------------
        Sequence 10: 192.168.2.0/24             -> Permit
IPv6 Access Lists
------------------------------------------------

#edit the existing access-list that was used to redistribute from BGP into OSPF

ssg5-1(trust-vr)-> set access-list 5 permit ip 192.168.3.0/24 20
ssg5-1(trust-vr)-> exit

On router-1 and router-2, the new route should be visible in the OSPF routing table. Furtmore, the trace-route from ssg5-1 towards 192.168.3.8 should now work :

ssg5-1-> trace-route 192.168.3.8                                
Type escape sequence to escape

Send ICMP echos to 192.168.3.8, timeout is 2 seconds,  maximum hops are 32, 
1       3ms     2ms     1ms     192.168.0.7
2       3ms     2ms     3ms     192.168.3.8

 

Everything works…

… but hosts on the 192.168.3.0/24 network cannot access the internet

Reason : router-3 does not have a default gateway.  ssg5-1 has a connection to the internet (not shown on diagram), so the only thing you need to do is to distribute the default route on ssg5-1 into bgp

ssg5-1-> set vrouter trust-vr proto bgp network 0.0.0.0/0
ssg5-1> get vrouter trust-vr proto bgp network

network            weight check reachable-prefix   rib-in route-map
--------------------------------------------------------------------------------
10.2.0.0/24         32768 yes   10.2.0.0/24        yes    null
192.168.1.0/24      32768 yes   192.168.1.0/24     yes    null
0.0.0.0/0           32768 yes   0.0.0.0/0          yes    null

Check routing table on router-3, you should now see the default route. If not, make sure router-3 does not have an access list/setting to reject incoming default route

By default, bgpd itself does not advertise a default route, even if it is in the local routing table. You can change this behaviour using the no neighbor default-originat

 

 

Notes : 

No Sync

In my first post about BGP, I discussed the “unset vrouter trust-vr proto bgp sync” command, that will ensure new routes are not being checked in IGP routing tables.  In quagga, you can set the same behaviour with the following procedure :

[root@router-3 ~]# telnet localhost 2605
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.

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


User Access Verification

Password: 
router-3> enable
Password: 
Password: 
router-3# conf t
router-3(config)# router bgp 65000
router-3(config-router)# no bgp network import-check 
router-3(config-router)# exit
router-3(config)# exit
router-3# write
Configuration saved to /etc/quagga/bgpd.conf

© 2008 – 2021, Peter Van Eeckhoutte (corelanc0d3r). All rights reserved.

Comments are closed.

Corelan Training

We have been teaching our win32 exploit dev classes at various security cons and private companies & organizations since 2011

Check out our schedules page here and sign up for one of our classes now!

Donate

Want to support the Corelan Team community ? Click here to go to our donations page.

Want to donate BTC to Corelan Team?



Your donation will help funding server hosting.

Corelan Team Merchandise

You can support Corelan Team by donating or purchasing items from the official Corelan Team merchandising store.

Protected by Copyscape Web Plagiarism Tool

Corelan on Slack

You can chat with us and our friends on our Slack workspace:

  • Go to our facebook page
  • Browse through the posts and find the invite to Slack
  • Use the invite to access our Slack workspace
  • Categories