петък, март 12, 2021

HA with ExaBGP

The idea is simple: convenient way to blackhole some prefixes (bogus, wellknown C&C, spam,malicious, personally predefined, etc)

I'm using Linux + exaBGP + python script to collect some prefixes from a list of sources; exaBGP holding BGP session with our 2 RR and announce generated list of prefixes with blackhole community.

 exaBGP  is a python application to interact with BGP networks

List of prefixes is generated by generate_blacklists.py 

https://drive.google.com/file/d/1XgksQVcb2rpabv8OVCBkFabR6YuQpxV9

The configuration itself is pretty straightforward  and self-explanatory 

1. to announce a single static route:

neighbor 192.168.0.1 {
router-id 192.168.0.10;
local-address 192.168.0.10;
local-as 12345;
peer-as 12345;

### optional

### hold-time 180;
### outgoing-ttl 1;
### capability {
### multi-session;
### }


family {
ipv4 unicast;
}
static {
route 10.0.0.1/32 next-hop self;

route 10.0.0/24 origin IGP as-path [10 20 30 30 30  ]  next-hop 192.168.2.1;

route 172.10.0.0/22 next-hop 192.168.2.1 med 200 community [30303:30303] split /24;

route 9.9.9.9/32 next-hop 192.168.2.1 extended-community [ target:120000L:123 origin:130000:1234 ];
}
}

### Or 

announce {
        ipv4 {
            unicast 10.0..0/24 next-hop 192.168.2.1 local-preference 200 community 30303:30303;
        }
    } 

A direct API command (via exabgcli <- for systemd https://github.com/Exa-Networks/exabgp/blob/master/etc/systemd/exabgp.service)

announce route 10.0.0/24 origin IGP as-path [10 20 30 30 30  ]  next-hop 192.168.2.1

2 servers; preview VIP is assigned as secondary IP; nginx listening on this "VIP"; if no output from curl == stop announcing VIP i.e. no incoming connections (ToDo: more detailed explanation about healthcheck and route announce)

process service-nginx {
run python3 -m exabgp healthcheck -s --name nginx --cmd "curl --fail --verbose --max-time 2 http://localhost" --start-ip 0;
encoder text;
}
neighbor 192.168.0.1 {
router-id 192.168.0.10;
local-address 192.168.0.10;
local-as 12345;
peer-as 12345;

api services {
processes [ service-nginx ];
}

ExaBGP could be used for DDoS protection (with NetFlow/syslog/monitoring), Internet Watch Inerception, Traffic Engineering, Server's HA and any other SDN variations


Some useful links:

https://github.com/Exa-Networks/exabgp

https://vincent.bernat.ch/en/blog/2013-exabgp-highavailability

https://thepacketgeek.com/exabgp/

Part 1 : https://www.dasblinkenlichten.com/working-with-exabgp-4/

Part 2: https://www.dasblinkenlichten.com/building-static-routes-with-exabgp/

https://blog.plessis.info/blog/2020/02/11/haproxy-exabgp.html

 

 

Simple example from developer:

neighbor 192.168.127.128 {        
description "will flap a route until told otherwise";        
router-id 198.111.227.39;        
local-address 192.168.127.1;        
local-as 65533;        
peer-as 65533;        
### add and remove routes when flap.sh prints
### flap.sh should produce readable for ExaBGP output
### in proper ExaBGP API syntax
process loving-flaps {                
run etc/processes/flap.sh;        
}

1 - take your favourite language : perl, python, lua, C, shell, french !
2 - create a forever loop3 - print what you want to do ...
#!/bin/sh
# ignore Control C
trap
'' SIGINT
while `true`;

### that echo result is understandable for ExaBGP API
do echo "announce route 192.0.2.1 next-hop 10.0.0.1"
sleep 10
echo "withdraw route 192.0.2.1 next-hop 10.0.0.1"
sleep 10
done

Real life example:








neighbor 10.255.1.254 {
    router-id 10.255.42.1;
    local-as 65042;
    peer-as 65001;

    api services {
        processes [ watch-loghost, watch-mailhost ];
    }
}

process watch-loghost {
    encoder text;
    run python -m exabgp healthcheck --cmd "nc -z -w2 -u localhost 514" --no-syslog --label loghost --withdraw-on-down --ip 10.255.255.1/32;
}

process watch-mailhost {
    encoder text;
    run python -m exabgp healthcheck --cmd "nc -z -w2 localhost 25" --no-syslog --label mailhost --withdraw-on-down --ip 10.255.255.2/32;
}