Intro to BGP and OSPF
We wanted to create a bgp setup with ospf
This looks roughly like this:
Target description
This post might be relevant for you if you have the following problem to solve:
Given:
- public ipv4 address or subnet
- uplink host which talks BGP to us (created in this tutorial)
Target: announce our network prefix to our internal OSPF network, through a backbone router, which talks BGP to uplink (bgp-test01).
Intermediate steps:
- This means, we need to create a separated network with routing for our internal nodes (here represented by bgp-test02 and bgp-test03).
- This network is called 192.168.17.0/24 in our example
- Setup a OSPF session between the bgp-test02 and bgp-test03 (our actual client which will be exposed by our ipv4)
- Setup a BGP session between bgp-test01 and bgp-test02
- The peering ips are 10.100.0.10 and 10.100.0.20 in our example
- fix import and exports of bird config
- profit
Create network
- bgp-test01 has two interfaces
- public ipv4
- bgp communication 10.100.0.10/24
- bgp-test02 has two interfaces
- bgp communication 10.100.0.20/24
- OSPF communication 192.168.17.2/24
- bgp-test03 hast one interface:
- OSPF communication 192.168.17.2/24
OSPF
First we need to set up a the OSPF session using bird on the hosts.
We therefore write the following sketch into each /etc/bird/bird.conf
:
router id 10.100.0.10; # <- can be any unique ID per VM
protocol ospf {
import all;
export all;
# Define OSPF areas
area 0 {
interface "eth1" {
cost 10;
type broadcast;
hello 5; retransmit 2; wait 10; dead 20;
authentication simple;
password "pass";
# manual costs
};
};
};
BGP
bgp-test01
For BGP we add a filter and a peer:
protocol kernel {
metric 00;
scan time 60;
import all;
learn;
export all; # Actually insert routes into the kernel routing table
}
filter is_picopeer {
# if net ~ 192.168.17.0/24 then accept; # for debugging
if net ~ 5.145.135.156/32 then accept;
reject;
};
protocol bgp peer2 {
local as 64512;
neighbor 10.100.0.20 as 64513;
import filter is_picopeer;
export all;
}
protocol static {
# ipv4;
route 5.145.135.128/27 via 10.100.0.10;
export all;
}
We import the announced routes from the other peer, if the announcment is part of the allowed public ipv4 subnet. Therefore, we create a filter to check if the announcement is part of the subnet. On the other hand we need to announce a route from our peering node to our side. We therefore create a static route, which routes our whole subnet via our BGP peering address.
bgp-test02
On the other node, we also add the bgp peering to bgp-test01. We import all routes from the upstream bgp-test01 router (except the blocks we manage - but this is not done yet). And export the routes of our public ip block.
filter export_subnets {
if net ~ [ 5.145.135.156/32 ] then {
accept;
}
reject;
}
protocol bgp peer1 {
local as 64513;
neighbor 10.100.0.10 as 64512;
export filter export_subnets;
import all; # todo only !export_subnets
}
Fix Exports
You might need to tweak som export and imports of the kernel on your nodes.
You can do this using birdc show route
and ip r
.
For OSPF birdc show ospf topology
is also very helpful.
To see the current state of BGP there is only birdc show proto
?
Final configuration
This shows the three final configurations for our setup.
bird.conf of bgp-test01
router id 10.100.0.10;
protocol kernel {
metric 00;
scan time 60;
import all;
learn;
export all; # Actually insert routes into the kernel routing table
}
# The Device protocol is not a real routing protocol. It doesn't generate any
# routes and it only serves as a module for getting information about network
# interfaces from the kernel.
protocol device {
scan time 60;
}
filter is_picopeer {
if net ~ 192.168.17.0/24 then accept;
if net ~ 5.145.135.156/32 then accept;
reject;
};
protocol bgp peer2 {
local as 64512;
neighbor 10.100.0.20 as 64513;
import filter is_picopeer;
export all;
}
protocol static {
route 5.145.135.128/27 via 10.100.0.10;
export all;
}
bird.conf of bgp-test02
router id 10.100.0.20;
protocol kernel {
metric 0;
scan time 60;
import all;
export all; # Actually insert routes into the kernel routing table
}
# The Device protocol is not a real routing protocol. It doesn't generate any
# routes and it only serves as a module for getting information about network
# interfaces from the kernel.
protocol device {
scan time 60;
}
protocol direct {
interface "lo";
}
filter export_subnets {
if net ~ [ 5.145.135.156/32 ] then {
accept;
}
reject;
}
protocol bgp peer1 {
local as 64513;
neighbor 10.100.0.10 as 64512;
export filter export_subnets;
import all;
}
# Enable OSPF protocol
protocol ospf {
# Define OSPF areas
import all;
export all;
area 0 {
interface "eth1" {
cost 10;
type broadcast;
hello 5; retransmit 2; wait 10; dead 20;
authentication simple;
password "pass";
# manual costs
};
};
};
bird.conf of bgp-test03
router id 10.100.0.30;
# The Kernel protocol is not a real routing protocol. Instead of communicating
# with other routers in the network, it performs synchronization of BIRD's
# routing tables with the OS kernel.
protocol kernel {
metric 0;
scan time 60;
import none;
export all; # Actually insert routes into the kernel routing table
}
# The Device protocol is not a real routing protocol. It doesn't generate any
# routes and it only serves as a module for getting information about network
# interfaces from the kernel.
protocol device {
scan time 60;
}
protocol direct {
interface "lo";
}
# Enable OSPF protocol
protocol ospf {
# Define OSPF areas
import all;
export all;
area 0 {
interface "eth1" {
cost 10;
type broadcast;
hello 5; retransmit 2; wait 10; dead 20;
authentication simple;
password "pass";
# manual costs
};
};
};