Remote Triggered Black Hole is a very useful Security Tool that can be extremely helpful during DDoS Attacks, it leverages on BGP Communities and help us drop tarffic before it reaches our Infrastructure.
Many could (understandably) argue that by blackholing it mens that the DDoS was successful and you lose, but thats not entirely true, there are many situations where its worth sacrificing one of your services in order to save all of the others, or perhaps the target of the attack is an IP that is not even in use, nonetheless, traffic still reaches your network and exhaust your resources, this would be another perfect candidate to be Blackholed.
Ideally you would implement RTBH with your ISP, most of the big players Support Blackhole Communities, if that is not an option, you could still implement it at your own Edge. Implementing it with your ISP means that traffic will be dropped all together before reaching your network, applying it at your Edge would protect the Backend Infrastructure, but could still Impact your Edge (eg: Volumetric attack).
On this example we will be spinning up 4 VMs: RTBH, Edge, ISP and Internet. The RTBH Instance will act as a BGP OOB Speaker, it will be running Ubuntu and BIRD as the BGP Daemon. The EDGE and ISP will be running JunOS, the “Internet” instance will be used to test the result of the Blackhole. More detail on each one to come.
VAGRANT
On this example I will be using Vagrant to spin up JunOS Routers and Ubuntu Instances. Vagrant is an interesting tool that helps you manage, build, destroy VMs, its is extremely powerful, you can spin up entirely Labs in minutes, its worth a look. I won’t be getting in details on how it works, but here’s a quick and very simple guide of how this Lab was setup:
vagrant plugin install vagrant-host-shell vagrant-junos vagrant box add juniper/ffp-12.1X47-D15.4-packetmode vagrant init
Considering that you already have Vagrant installed, this will add the Plugins needed to run the JunOS Instances, it will then download a vSRX in packet-mode (Meaning that Stateful is disabled, making it pretty much a pure Router). With that done, vagrant init should have added a Vagrantfile to your currently directory, by editing it and replacing the code by the following we should be good to go:
# -*- mode: ruby -*- # vi: set ft=ruby : Vagrant.configure("2") do |config| config.vm.define "edge" do |edge| edge.vm.box = "juniper/ffp-12.1X47-D15.4-packetmode" edge.vm.network "private_network", virtualbox__intnet: "edge_isp", auto_config: false edge.vm.network "private_network", virtualbox__intnet: "edge_rtbh", auto_config: false end config.vm.define "isp" do |isp| isp.vm.box = "juniper/ffp-12.1X47-D15.4-packetmode" isp.vm.network "private_network", virtualbox__intnet: "edge_isp", auto_config: false isp.vm.network "private_network", virtualbox__intnet: "isp_internet", auto_config: false end config.vm.define "rtbh" do |rtbh| rtbh.vm.box = "ubuntu/trusty64" rtbh.vm.network "private_network", virtualbox__intnet: "edge_rtbh", auto_config: false end config.vm.define "internet" do |internet| internet.vm.box = "ubuntu/trusty64" internet.vm.network "private_network", virtualbox__intnet: "isp_internet", auto_config: false end end
All right, all we need to do now is run vagrant up and this will bring the 4 VMs up with the proper defined Network Interfaces.
BIRD
BIRD is a Linux Routing Daemon, as a RTBH Station, we will set it up as a OOB BGP Speaker, it will peer with our Edge Router, and its goal will be to Inject /32 Routes that we’d like to Blackhole.
Modern versions of the Linux Kernel let us create Multiple Routing Tables, we will use that feature and will create a RT dedicated to the Blackholed Routes, BIRD will then Sync its BGP Table with the RT that we created, whenever it see a new route it will Inject into BGP and advertise to Edge (Given that it match our Filter). Here’s a configuration example with comments. Using a dedicated RT for the Blackholed IPs helps with Management, Operation, Automation, etc. Checking what IPs you have blackholed is a matter of listing the RTBH Route Table.
# Setup eth1 IP address on same segment as our Edge Router ifconfig eth1 10.0.0.100 netmask 255.255.255.0 #Create a new Route Table, call it RTBH with ID 100 echo "100 rtbh" >> /etc/iproute2/rt_tables # Install BIRD apt-get update apt-get install bird #Apply the BGP Configurations cd /etc/bird cp -p bird.conf bird.conf.bkp
BIRD will read the configuration from file /etc/bird/bird.conf, here’s the full configurations used with comments:
# Configure logging | |
#log "/var/log/bird-rtbh.log" all; | |
log syslog { debug, trace, info, remote, warning, error, auth, fatal, bug }; | |
define local_asn = 65001; | |
# Override router ID | |
router id 10.0.0.100; | |
# This pseudo-protocol performs synchronization between BIRD's routing | |
# tables and the kernel. If your kernel supports multiple routing tables | |
# (as Linux 2.2.x does), you can run multiple instances of the kernel | |
# protocol and synchronize different kernel tables with different BIRD tables. | |
protocol kernel { | |
learn; # Learn all alien routes from the kernel | |
persist; # Don't remove routes on bird shutdown | |
scan time 20; # Scan kernel routing table every 20 seconds | |
import none; # Default is import all | |
export none; # Default is export none | |
kernel table 5; # Kernel table to synchronize with (default: main) | |
} | |
table RTBH; | |
protocol kernel rtbh { | |
learn; | |
persist; | |
scan time 20; | |
import all; | |
export all; | |
table RTBH; | |
kernel table 100; # Kernel table to synchronize with (rtbh: 100) | |
} | |
# This pseudo-protocol watches all interface up/down events. | |
protocol device { | |
scan time 10; # Scan interfaces every 10 seconds | |
} | |
# Allow only /32 part of a specific prefix | |
# This function will only pass if the prefix is a /32 and part of the allowed_prefix list | |
function check_prefix() | |
prefix set allowed_prefix; | |
{ | |
allowed_prefix = [ 203.0.113.128/25+, 1.1.1.0/24+ ]; | |
if ! (net ~ allowed_prefix) then return false; | |
if net.len != 32 then return false; | |
return true; | |
} | |
#This Filter will be applied to BGP Export, it will check if check_prefix() is True and then set the Blackhole Community | |
filter EXPORT_BLACKHOLED_32 | |
{ | |
if ! (check_prefix()) then | |
reject; | |
bgp_community = -empty-; | |
bgp_community.add((local_asn,666)); | |
accept; | |
} | |
#Peer BGP Settings. We explicity select table RTBH, which makes this BGP Peer sync with the Kernel Table RTBH Only. | |
protocol bgp EDGE { | |
table RTBH; | |
description "Peer with Edge Router to announce /32 Prefixes to be Blackholed"; | |
local as local_asn; | |
neighbor 10.0.0.1 as local_asn; | |
import all; | |
export filter EXPORT_BLACKHOLED_32; | |
} |
Here’s with will happen. we define a function called check_prefix(), we add to the function a List of the prefixes which we own and that contains IP that we may want to Blackhole at some point, we then make sure that only /32 IPs are advertised. This function will be called on our filter named EXPORT_BLACKHOLED_32. This filter will advertise only what is True from check_prefix(), and it will add a Community AS:666.
EDGE
Here at the Edge of our Network we will be running JunOS. This router will iBGP peer with our RTBH Instance, and will eBGP with our ISP. Here’s a simple configuration to illustrate our example:
#Interface configuration set interfaces ge-0/0/1 unit 0 family inet address 203.0.113.1/25 set interfaces ge-0/0/2 unit 0 family inet address 10.0.0.1/24 #Each one of these IP will be used to illustrate the Blackhole in operation set interfaces lo0 unit 0 family inet address 203.0.113.130/32 set interfaces lo0 unit 0 family inet address 203.0.113.131/32 set interfaces lo0 unit 0 family inet address 203.0.113.132/32 #BGP Configuration set protocols bgp advertise-inactive set routing-options router-id 203.0.113.1 set routing-options autonomous-system 65001 #iBGP to BIRD (RTBH) set protocols bgp group IBGP type internal set protocols bgp group IBGP local-address 10.0.0.1 set protocols bgp group IBGP neighbor 10.0.0.100 set protocols bgp group IBGP import IMPORT-FROM-RTBH # This import filter rule is to make sure that we don't receive anything other than /32 + blackhole community from the RTBH Station set policy-options policy-statement IMPORT-FROM-RTBH term 1 from route-filter 0.0.0.0/0 prefix-length-range /32-/32 set policy-options policy-statement IMPORT-FROM-RTBH term 1 from community BLACKHOLE set policy-options policy-statement IMPORT-FROM-RTBH term 1 then accept set policy-options policy-statement IMPORT-FROM-RTBH term 20 then reject #EBGP to ISP set protocols bgp group EBGP type external set protocols bgp group EBGP local-address 203.0.113.1 set protocols bgp group EBGP neighbor 203.0.113.2 peer-as 65002 set protocols bgp group EBGP export EXPORT-TO-ISP set policy-options community BLACKHOLE members 65001:666 #Define the Export Filter. Only our /25 prefix and the prefixes announced from BIRD, with the proper Community, will # be advertised to our ISP. set policy-options policy-statement EXPORT-TO-ISP term 1 from protocol static set policy-options policy-statement EXPORT-TO-ISP term 1 from route-filter 203.0.113.128/25 exact set policy-options policy-statement EXPORT-TO-ISP term 1 then accept set policy-options policy-statement EXPORT-TO-ISP term 5 from community BLACKHOLE set policy-options policy-statement EXPORT-TO-ISP term 5 then accept set policy-options policy-statement EXPORT-TO-ISP term 20 then reject set routing-options static route 203.0.113.128/25 reject
This configuration should be pretty straight forward. We should receive the routes advertised from the RTHB Station via BGP, the Import Filter will make sure that we only receive /32s that have the proper defined Blackhole Community set, this is to avoid a mistake on the BIRD Configuration and end-up announcing what it shouldn’t, which could be really bad :ˆ) The Edge Router will Advertise to the Internet our Service Prefix Range (203.0.113.128/25 in this example) + The Blackholed prefixes, anything else that we try to advertise to ISP will be dropped.
Note: In this example we are setting up RTBH with an Upstream ISP, and letting them drop the traffic. If your ISP does not support RTBH you can still use it on your own Edge Router, saving resources of your Backend Infrastructure, to do so it should be a matter of adapting the below ISP Configuration Section and apply it to your Edge Router.
ISP
Here we will simulate what the ISP would do with your traffic, each ISP will implement it on a different way, but the idea is the same, based on the Blackhole Community they should Drop traffic to the specified prefix/ip. Here’s an example of how I did it on our lab:
set interfaces ge-0/0/1 unit 0 family inet address 203.0.113.2/25 set routing-options router-id 203.0.113.2 set routing-options autonomous-system 65002 set protocols bgp group EBGP type external set protocols bgp group EBGP local-address 203.0.113.2 set protocols bgp group EBGP neighbor 203.0.113.1 peer-as 65001 set protocols bgp group EBGP import IMPORT-FROM-AS65001 set policy-options community BLACKHOLE members 65001:666 set policy-options community NO-EXPORT members no-export set policy-options community NO-ADVERTISE members no-advertise set policy-options policy-statement IMPORT-FROM-AS65001 term 1 from route-filter 203.0.113.128/25 exact set policy-options policy-statement IMPORT-FROM-AS65001 term 1 then accept set policy-options policy-statement IMPORT-FROM-AS65001 term 5 from community BLACKHOLE set policy-options policy-statement IMPORT-FROM-AS65001 term 5 then community add NO-EXPORT set policy-options policy-statement IMPORT-FROM-AS65001 term 5 then community add NO-ADVERTISE set policy-options policy-statement IMPORT-FROM-AS65001 term 5 then next-hop reject set policy-options policy-statement IMPORT-FROM-AS65001 term 5 then accept set policy-options policy-statement IMPORT-FROM-AS65001 term 20 then reject
It should only accept our /25 prefix or the /32 with Blackhole Community, if the community 65001:666 is set, the Router will add the /32 with a next-hop Reject, meaning traffic to this IP will be dropped at the ISP Level, outside of your network, saving your network resources. The NO-EXPORT and NO-ADVERTISE communities is important to make sure that it won’t export the prefixes to be blackholed to any peer/upstream.
RESULT
Lets check it in practice. We will first show that we can reach all of our Service IPs (The ones on our Loopback interface). For that I will use the “Internet” instance, which is just an instance connected behind the ISP Router.
Now, lets go ahead and Trigger a Blackhole:
As you can see, 203.0.113.130/32 was added to the rtbh table, and to show as an example, I also added 203.0.113.131/32 into the Main Route Table, which should not be advertised Upstream as our configuration plan is to keep all blackholed IPs into a single rtbh namespace.
On the EDGE we can see that, as expected, we are learning a single /32 from BIRD, and it has the community 65001:666 set. So far so good. Now to the ISP Router:
We have our ISP Receiving our Service Prefix (/25), but also our Blackholed /32, which in turn it add a Next-Hop Type Reject, which will drop traffic to that IP before it reach us. Back to the Test Instance, lets check the results:
And Voilà. It works. Traceroute show traffic getting dropped at our ISP Router (198.51.100.1).
SUMMARY
I hope this can help someone looking to Implement a RTBH Solution in their Network, or even someone that’s trying to start with BIRD, which is a very powerful Solution. Bear in mind that this Post can be used as an example/idea, but each ISP implements RTBH in a different way, different Community Numbers, Single or Split BGP Sessions, etc..
RFC7999 tries to Standardise the Blackhole Community but not all ISP follows it yet, so Make sure to contact your ISP and see if they Support Blackhole and what kind of Setup they have.
Até a Proxima!