Simple script to add route to exaBGP

Continuing to play around with the very fine exaBGP. This time adding my own little script to announce a new route and reload the exaBGP config to announce the new prefix :) Please note this script makes use of another script that I posted about [here] and I have the script named "exabgp_reload"

First off this script is quite basic but is used so that anyone can jump on run RTBH and do what needs to be done with no further knowledge. The script is a perl script and has some dependencies to make it easier for me you will need installed (if you dont already?)

It works by finding a line with "INSERT_NEW" and then adding the announcement to the next line. So we need to add that line to our static section of the exaBGP config file like so:

    static {
          # The next line is used to match do not edit it!
          # INSERT_NEW
    }

Next save the following script somewhere e.g. /usr/bin/RTBH

# This script will prompt for and IP to be blackholed.
#
# It will check the IP is valid
# It will blackhole traffic to this IP upsteams too by announcing transit
# provider communities too. 
#
# It will also mail the NOC team when a prefix is announced and exabgp
# has been restarted.
#
#  Blackhole Communities:
#  m00nie co - 65001:666
#  Transit_A - xxx:xxx
#  Transit_B - xxx:xxx
#
#  Well-Known communities 
#  no-export    -  65535:65281  # do not advertise to any eBGP peers
#  no-advertise -  65535:65282  # do not advertise to any BGP peer
#  local-as     -  65535:65283  # do not advertise this route to peers outside the local as
#
# IP Can be used to test
# blackholing: x.x.x.x
#
##############################################
# Some packages we use
use NetAddr::IP;
use Data::Validate::IP;
use Tie::File;
use Net::SMTP::Multipart;

# This is the exaBGP config file location
$exabgpConf = "/usr/etc/exabgp/exaBGP.conf";

# Hash we use to validate BGP subnets
my %prefix;

######################################################
# This is specific to a current setup where we need  #
# an additional community added to BGP customer      #
# prefixes we want to announce/blackhole. Prefixes   #
# we originate do not need this                      #
#      						 #
# Syntax is $prefix{Customer_(number)} = "prefix";   #
######################################################
#$prefix{Smiley_1} = "10.0.0.0./8";
#$prefix{Sado_1} = "172.16.0.0/24";

#########################
# Script starts here    #
#########################
print "######################\n";
print "#   Blackhole tool   #\n";
print "#  Please take care  #\n";
print "######################\n\n";

print "Enter the IP you would like to blackhole:\n";
$userip =  <STDIN>;
chomp ($userip);

# Check user has input at least a usable IP
if (is_ipv4($userip)) {
        print "Looks like an ipv4 address\n";
}
  else {
        print "Not a valid ipv4 address\n";
        exit;
}

print "\nComments/Reason for blackholing (ticket no?):\n";
$comment = <STDIN>;

my $ip = NetAddr::IP->new($userip);
my $bgpcust = 0;

print "\n\nChecking if IP is part of customer prefix.....\n";
while (($name, $value) = each (%prefix)){
        #print "$name has the prefix of $value \n";
        $check = NetAddr::IP->new($value);
        if ($ip->within($check)) {
                print "$ip is withing $name prefix of $value \n";
                print "An extra community will be applied\n";
                $bgpcust = 1;
                last;
        }
}
if ($bgpcust == 0) {
        print "Not found in any BGP customer announcements\n";
}

####################
# Prompt to check! #
####################
print "\n\n\nYou are about to blackhole the IP: $userip \n";
print "Are you sure you want to continue? (Y/N):";
if (<STDIN> !~ /^[yY]/) {
        print ("Quitting!\n");
        exit;
}

########################
# Add config to exabgp #
########################
print "\n\nAdding exaBGP config...\n";
my $announcement;
my $bgpcomment = "# $comment";

# Check if extra community needed
if ($bgpcust == 1) {
        print "BGP customer prefix adding extra community\n";
        $announcement = "route $userip/32 next-hop 192.0.2.1 community [65001:666 65001:400];";
} else {
        $announcement = "route $userip/32 next-hop 192.0.2.1 community [65001:666];";
}

# Open file
tie @lines, &#039;Tie::File&#039;, $exabgpConf or die;
for (my $i = 0;  $i < @lines; $i++) {
                if (@lines[$i] =~ /INSERT_NEW/) {
                        # Add comment
                        splice @lines, $i+1, 0, $bgpcomment;
                        # add our new announcement 
                        splice @lines, $i+2, 0, $announcement;
                }
}
# Close file
untie @lines;

#################
# exabgp reload #
#################
print "Reloading exabgp\n";
system("exabgp_reload");

#####################
# Mail notification #
#####################
print "Mailing NOC\n";
$smtp = Net::SMTP::Multipart->new(localhost);
$smtp->Header(To    =>  "noc\@m00nie.com",
              From  =>  "RTBH\@rr01.lon-mon",
              Subj  =>  "$userip blackholed");
$smtp->Text("Was blackholed with the comment:\n$comment");
$smtp->End();
print "Mail sent\n";

You should now just have to edit the script with the location of your exaBGP config file and your good to go. I'd recommend having a test /32 you can play around with and not upset anyone too much. Next is to add switches to the script to allow us to pass IPs as arguments then we can call it via webpages etc :)

As ever any comments/suggestions always welcome

m00nie