None
Bgp eem scripting at digidraft.net

Bgp eem scripting

2016-04-27

    Every internet service provider ever met a problem related to ddos activity aimed at its customers or even at infrastructure services and equipment. At this point exist many features that allow you to automate some kind of prevention mechanisms. I would like to describe deploying one of them, that based on the Cisco Embedded Event Manager (EEM) TCL scripting.

    For ISP perspective every network activity which one or another way could affect on customers may be considered as ddos. By analyzing the data provided by NetFlow, a network engineer can determine number of packets and bandwidth per second per destination. Typically netflow monitoring system have three main components:  exporter, collector and analyzer. Exporter aggregates packets into flows and exports flow records towards one or more flow collectors. Collector responsible for reception, storage and pre-processing of flow data received from a flow exporter. And analyzer received flow data in the context of intrusion detection or traffic profiling. This is a topic for a separate article.

    let's say we already installed all components in our network. All netflow data of incoming traffic to ISP stored in the collector. The analyzer can determine which number of pps and bps per destination can be regarded as anomaly.

    Here is a simple network diagram.

bgp_eem1

    As bgp peer may be used any kind of software, for instance ExaBGP, Quagga of router with bgp. Bgp border router in this case is cisco 6509.

    Bgp configuration for Cisco:

ip community-list 10 permit 64556:64556
!
route-map RR deny 10
match community 10
!
route-map RR permit 100
!
router bgp 64555
neighbor 10.0.0.2 remote-as 64556
address-family ipv4
  table-map RR filter
  neighbor 10.0.0.2 activate
  neighbor 10.0.0.2 prefix-list DENY-ALL out
!
clear ip bgp ipv4 unicast table-map

    You can see that as soon as router have got a prefix with community 64556:64556 it reflects it to install into routing table. That allows to be able to access address through normal routing.

    Bgp configuration for ExaBGP:

neighbor 10.0.0.1 {
    router-id 10.0.0.2;
    local-address 10.0.0.2;
    local-as 64556;
    peer-as 64555;
    static {
        route 10.0.1.1/32 next-hop 10.0.0.2 community 64556:64556 as-path [65002 65002 65002];
    }
}

    Pay attention to additional as-path attribute, it will be used by tcl script in special cause.

    Analyzer edit exabgp config file and restart the session in causes of threshold exceeded. And then the script is triggered.

    That's the script itself:

# Script triggered every 20 seconds if session with exabgp peer is up.
::cisco::eem::event_register_snmp tag 1.0 oid iso.3.6.1.2.1.15.3.1.2.10.0.0.2 entry_op eq
get_type exact entry_type value entry_val "6" poll_interval 20 maxrun 60
# Import cisco eem and library
namespace import ::cisco::eem::*
namespace import ::cisco::lib::*
# Form a array from event_reqinfo
array set arr_einfo [event_reqinfo]
if {$_cerrno != 0} {
    set result [format "component=%s; subsys err=%s; posix err=%s;\n%s" \
        $_cerr_sub_num $_cerr_sub_err $_cerr_posix_err $_cerr_str]
    error $result
}
# create a list from recently announced prefixes
set filename "64556_LIST"
     set fp [open $filename "r"]
     set IP_LIST [read $fp]
     close $fp
# Set BGP to value of annonces with community 64556:64556 from 10.0.0.2.
array set snmp_res [sys_reqinfo_snmp oid 1.3.6.1.2.1.15.3.1.2.10.0.0.2 get_type exact]
set snmp_val $snmp_res(value)
if {$snmp_val == "6"} {
        set clist1 [list "sh ip bgp community 64556:64556 exact-match | i /32|10.0.0.2"]
                set BGP [cli_run "$clist1"]
                regsub -all {10\.0\.0\.2.{65}} $BGP "" BGP
    } else {
        exit
    }
}
# Get a difference between announced prefixes and prefixes on flash. If don't match, execute everything below.
set PRE_IP_LIST [regexp  -inline -all {\d+\.\d+\.\d+\.\d+\/|6500[1-2]} $BGP]
set NEW_IP_LIST [regexp  -inline -all {\d+\.\d+\.\d+\.\d+|6500[1-2]} $PRE_IP_LIST]
if {$IP_LIST != $NEW_IP_LIST} {
    foreach {IP HOP1 HOP2 HOP3} $NEW_IP_LIST {
        array set NEW_IP_ARRAY "{$IP} {$HOP1 $HOP2 $HOP3}"
    }
        set WRITE [lsearch -regexp [array names NEW_IP_ARRAY] \[0-9\]\[0-9\]\[0-9\]\[0-9\].+]
        if {$WRITE  >= 0} {
                exit
        } else {
# Rewrite to file
                set fileId [open $filename "w"]
                puts -nonewline $fileId $NEW_IP_LIST
                close $fileId
        }
        foreach {IP HOP1 HOP2 HOP3} $IP_LIST {
            array set IP_ARRAY "{$IP} {$HOP1 $HOP2 $HOP3}"
        }
# Add ip into acl 80
proc addto80 { newip } {
  action_syslog priority info msg "add $newip in to acl 80"
  set command "access-list 80 permit $newip"
  set clist2 [list "conf t" "$command" "end"]
  cli_run "$clist2"
}
# Delete ip from acl 80
proc delfrom80 { oldIP } {
         action_syslog priority info msg "del $oldIP from ACL 80"
         set COMMAND "no permit $oldIP"
         set clist4 [list "conf t" "ip access-list standard 80" "$COMMAND" "end"]
         cli_run "$clist4"
}
proc addto81 { newip } {
  action_syslog priority info msg "add $newip in to acl 81"
  set command "access-list 81 permit $newip"
  set clist3 [list "conf t" "$command" "end"]
  cli_run "$clist3"
}
proc delfrom81 { oldIP } {
         action_syslog priority info msg "del $oldIP from ACL 81"
         set COMMAND "no permit $oldIP"
         set clist5 [list "conf t" "ip access-list standard 81" "$COMMAND" "end"]
         cli_run "$clist5"
}
proc addto500Mb { newip } {
  action_syslog priority info msg "add $newip in to acl 500Mb"
  set command "permit ip any host $newip"
  set clist3 [list "conf t" "ip access-list extended 500Mb" "$command" "end"]
  cli_run "$clist3"
}
proc delfrom500Mb { oldIP } {
         action_syslog priority info msg "del $oldIP from acl 500Mb"
         set COMMAND "no permit ip any host $oldIP"
         set clist5 [list "conf t" "ip access-list extended 500Mb" "$COMMAND" "end"]
         cli_run "$clist5"
}
# Get a difference between arrays and run procs.
foreach {newIP newHOPs} [array get NEW_IP_ARRAY] {
  set ADD [info exists IP_ARRAY($newIP)]
  if {$ADD == 1} {
    if {$NEW_IP_ARRAY($newIP) != $IP_ARRAY($newIP)} {
    if {[lindex $NEW_IP_ARRAY($newIP) 0] != [lindex $IP_ARRAY($newIP) 0]} {
     if {[lindex $NEW_IP_ARRAY($newIP) 0] == "65001"} {
      addto80 "$newIP"
     }
     if {[lindex $NEW_IP_ARRAY($newIP) 0] == "65002"} {
      delfrom80 "$newIP"
     }
    }
    if {[lindex $NEW_IP_ARRAY($newIP) 1] != [lindex $IP_ARRAY($newIP) 1]} {
     if {[lindex $NEW_IP_ARRAY($newIP) 1] == "65001"} {
      addto81 "$newIP"
     }
     if {[lindex $NEW_IP_ARRAY($newIP) 1] == "65002"} {
      delfrom81 "$newIP"
     }
    }
    if {[lindex $NEW_IP_ARRAY($newIP) 2] != [lindex $IP_ARRAY($newIP) 2]} {
     if {[lindex $NEW_IP_ARRAY($newIP) 2] == "65001"} {
      addto500Mb "$newIP"
     }
     if {[lindex $NEW_IP_ARRAY($newIP) 2] == "65002"} {
      delfrom500Mb "$newIP"
     }
    }
   } 
  } else {
   if {[lindex $NEW_IP_ARRAY($newIP) 0] == "65001"} {
    addto80 "$newIP"
   }
   if {[lindex $NEW_IP_ARRAY($newIP) 1] == "65001"} {
    addto81 "$newIP"
   }
   if {[lindex $NEW_IP_ARRAY($newIP) 2] == "65001"} {
    addto500Mb "$newIP"
   }
  }
}
foreach {oldIP oldHOPs} [array get IP_ARRAY] {
                set DEL [info exists NEW_IP_ARRAY($oldIP)]
                if {$DEL == 1} {
  } else {
   if {[lindex $IP_ARRAY($oldIP) 0] == "65001"} {
                         delfrom80 "$oldIP"
   }
   if {[lindex $IP_ARRAY($oldIP) 1] == "65001"} {
                         delfrom81 "$oldIP"
   }
   if {[lindex $IP_ARRAY($oldIP) 2] == "65001"} {
                         delfrom500Mb "$oldIP"
   }
  }
}
        set clist8 [list "write"]
        cli_run "$clist8"
}

    Thereby, based on as-path attribute in announcements from bgp peer script can add or delete ip address from standard access-list 80, 81 and extended 500Mb. 65001 - add, 65002 - delete.

    Nevertheless, if you absolutely sure in your uplink blackhole-community you do not need to use it. But, if you have participated in any internet exchange peering it might be helpful. What if one IX-member ignores announcement /32, in this instance you will never be able to automaticaly stop ddos impact.

ACLs can be used in any place you want. For example:

route-map Uplink1-OUT permit 10
 match ip address 80
 set community XXXX:666
!
route-map Uplink2-OUT permit 10
 match ip address 81
 set community YYYY:666
!
class-map match-all 500Mb
  match access-group name 500Mb
!
policy-map DDOS_PROTECT
  class 500Mb
   police cir 500000000 bc 32000000 be 32000000
     conform-action transmit
     exceed-action drop
     violate-action drop
 
Leave a Comment: