BGP Workshop

From Haxogreen 2024 Wiki
Revision as of 15:36, 26 July 2024 by R3boot (talk | contribs)

Introduction

Ever wondered how to use the protocol that binds the internet together? This workshop will help you understand the basics of BGP, by performing a number of tasks with BGP on a small-scale. We will work with the following subjects:

  • Routing theory
  • Setting up a peering
  • Route leaks
  • Aggregation
  • Hijacking
  • Anycast
  • DDoS migitation (s/RTBH)

Assumed is that you have an understanding of Linux and the basics of networking (what is an ip, what is a subnet, what is a router, what is a switch).

Expectations

This workshop will NOT be about internet routing. It will discuss the BGP protocol using a bunch of examples that can be applied to anything that runs BGP. These techniques can be applied on your LAN and over VPN tunnels.

Requirements

In order to participate in this workshop, you need to have the following:

  • A working Debian system (either virtualized or bare-metal). Other distros will also work.
  • A direct connection to the network (no nat, no routed connections)
  • BIRD version 2.x, bash, netcat, ping, iproute2

Registration

Every participant of the workshop needs their own AS number and a prefix. Either add your details to the sheet below, or ask r3boot to add you.

https://docs.nurd.space/sheet/#/2/sheet/edit/IacR4-gLFoetuyrli3JBhIMB/

Workshop

Setting up your local networks

Create the two networks using iproute2:

ip link add type dummy
ip link add type dummy

ip addr add 192.168.0.1/24 dev dummy0
ip addr add 192.168.1.1/24 dev dummy1

ip link set dummy0 up
ip link set dummy1 up

Enable ip forwarding

sysctl -w net.ipv4.ip_forward=1


Setup initial configuration of BIRD

Configure BIRD to read network prefixes from all dummy devices. Do this by editing `/etc/bird/bird.conf`. Replace the current content with the content below. Be sure to replace X.X.X.X with your ip address.

router id X.X.X.X;

protocol device { }

protocol direct {
	ipv4;
	interface "dummy*";
}

protocol kernel {
	ipv4 {
	      export all;
	};
}


Load and check setup

birdc configure
birdc show route

A correctly configured BIRD will show a routing table that looks like the one below:

BIRD 2.0.12 ready.
Table master4:
192.168.0.0/24       unicast [direct1 13:48:13.162] * (240)
	dev dummy0
192.168.1.0/24       unicast [direct1 13:48:18.015] * (240)
	dev dummy1


Doublecheck that BIRD is exporting routes to the kernel using ip route show protocol bird. It should look like the following:

192.168.0.0/24 dev dummy0 proto bird scope link metric 32
192.168.1.0/24 dev dummy1 proto bird scope link metric 32

1) Basic BGP operations

1.1) Setting up your first BGP peering(s)

For each participant you want to setup a peering for, configure a block like below. Replace X.X.X.X and AAAAA with your own details. Replace Y.Y.Y.Y and BBBBB with the details that are used by your peer. Add a descriptive name for PEERNAME.

protocol bgp PEERNAME {
	local X.X.X.X as AAAAA;
	neighbor Y.Y.Y.Y as BBBBB;

	ipv4 {
		import all;
		export all;
	};
}


Once the peer configuration is added, load the configuration, and doublecheck if the peering is established.

birdc configure
birdc show protocols
birdc show route
ip route show protocol bird

1.2) Filtering

Modify the configuration and add an export filter for each peer.

filter export_to_PEERNAME {
        if net ~ [ 192.168.0.0/23{23,24} ] then accept;
        reject;
}


Next, configure the peer to use the filters for both importing and exporting routes:

protocol bgp alita {
        [...]

        ipv4 {
                import all;
                export filter export_to_alita;
        };
}

Once you are done, reload the configuration and check your routes again

birdc configure
birdc show route
ip route show protocol bird

1.3) Aggregation

Setup a static route which contains both your subnets. Configure the subnet to send host unreachables whenever an ip does not respond to ARP requests.

protocol static my_network {
        ipv4;
        route 192.168.0.0/23 unreachable;
}


Tighten your export filter for all your peerings so that you only send your aggregated network:

filter export_to_alita {
        if net ~ [ 192.168.0.0/23 ] then accept;
        reject;
}


1.4) BGP hijacking

Configure an extra dummy interface that is configured with an IP address belonging to some peer:

ip link add type dummy
ip addr add 192.168.2.66/32 dev dummy2
ip link set dummy2 up


Modify your export filters to send the hijacked prefix:

filter export_to_alita {
        if net ~ [ 192.168.0.0/23 ] then accept;
        if net ~ [ 192.168.2.66/32 ] then accept;
        reject;
}


Reload the configuration, and validate that the new route is set:

birdc configure
birdc show route
ip route show protocol bgp

1.4.1) Preventing BGP hijacking

Modify the import filter for your peer to only accept prefixes that belong to your peer, and use this filter to select routes imported from your peer:

filter import_from_alita {
        if net ~ [ 192.168.6.0/23 ] then accept;
        reject;
}

protocol bgp alita {
        [...]

        ipv4 {
                import filter import_from_alita;
                export filter export_to_alita;
        };
}

Next, reload the configuration, restart the BGP peering and check the routing tables:

birdc configure
birdc restart alita
birdc show route


Once you are done with this excercise, remove the dummy interface you used for hijacking.

ip link del dummy2

2) Advanced BGP tricks

2.1) BGP Anycast

Configure a loopback interface for your service

ip link add type dummy


Configure a health check which manages the anycast ip.


#!/usr/bin/env bash

INTERFACE='dummy2'
IP='192.168.0.42'

while :; do
    if nc -w1 -nz 127.0.0.1 22; then
        ip addr add ${IP}/32 dev ${INTERFACE} 2>/dev/null
    else
        ip addr flush dev ${INTERFACE}
    fi
    sleep 1
done

Now start or stop your service. Notice that bird will advertise the service once second after the service starts listening on its port, and stops advertising the address as soon as you stop the service.

Be sure to tear down the dummy2 interface once you are done, since the next example is incompatible with it.

ip link del dummy2

2.2) DDoS migitation using s/RTBH

Modify your export filter(s) so that a BGP community gets added whenever BIRD finds a single ip address belonging to your ip space:

filter export_to_alita {
   if net ~ [ 192.168.0.0/23{32,32} ] then
        bgp_community.add((65000,42));
        accept;
    fi

    if net ~ [ 192.168.0.0/23 ] then accept;

    reject;
}


Modify the import filter of your peers to reject a prefix as soon as it finds the migitation community

filter import_from_alita {
    if ( net ~ [ 192.168.6.0/23{32,32} ] && (65003,42) ~ bgp_community) then {
        dest = RTD_UNREACHABLE;
        accept;
   }

    if net ~ [ 192.168.6.0/23 ] then accept;

    reject;
}

Reload your configuration. Notice that nothing will change, since you have not tagged any prefix with the migitation community.

Now, pick an ip address within your range, and ask one of your peers to run a ping towards this ip.

To activate the migitation, add a static route for an ip address you want to protect, and reload your configuration:

protocol static my_network {
        [...]

        route 192.168.1.1/32 blackhole;
}

To deactivate the migitation, remove the static route and reload your configuration.