Parcourir la source

Initial import of our blackhole scripts

Sebastien Badia il y a 10 ans
commit
e4f69a75d4
2 fichiers modifiés avec 236 ajouts et 0 suppressions
  1. 111 0
      blackhole/blackhole.sh
  2. 125 0
      blackhole/flood-detector.sh

+ 111 - 0
blackhole/blackhole.sh

@@ -0,0 +1,111 @@
+#!/usr/local/bin/bash
+#
+# Author:: Sebastien Badia (<seb@sebian.fr>)
+# Date:: 2014-02-13 04:01:56 +0100
+
+if [[ "x${DEBUG}" == "x1" ]]; then
+  set -e
+  set -x
+fi
+
+hostname=$(hostname -s)
+case $hostname in
+  "zoulou")
+    BGPNEIGHBOR="212.85.148.109"
+    ;;
+  "yankee")
+    BGPNEIGHBOR="80.231.79.69"
+    ;;
+  "x-ray")
+    BGPNEIGHBOR="79.143.245.137"
+    ;;
+  "grimoire")
+    BGPNEIGHBOR="1.1.1.1"
+    ;;
+  *)
+    echo "Unknow router"
+    exit 1
+esac
+
+show_usage() {
+  cat <<EOF
+Usage: $0 [OPTION]
+Blackhole script
+
+    -a [add|del|list]     Action à effectuer.
+    -i [a.b.c.d/n]        Petite victime.
+    -h (help)             Affiche cette aide.
+EOF
+exit 1
+}
+
+while getopts "a:i:h" opt; do
+  case $opt in
+    a)
+      case $OPTARG in
+        "add")
+          action="add"
+          ;;
+        "del")
+          action="del"
+          ;;
+        "list")
+          action="list"
+          ;;
+        *)
+          echo "Not a action (add/del/list)"
+          ;;
+      esac
+      ;;
+    i)
+      case $OPTARG in
+        *.*.*.*/* )
+          net=$OPTARG
+          ;;
+        * )
+          echo "Not a valid ip (a.b.c.d/n), ($OPTARG)"
+          exit 1
+      esac
+      ;;
+    h)
+      show_usage
+      exit 2
+      ;;
+    *)
+      echo "Bad params"
+      exit 1
+      ;;
+  esac
+done
+
+if [[ "$action" == "add" ]]; then
+  mask=`echo $net | cut -d / -f 2`
+  if [ $mask -le 24 -o $mask -gt 32 ]; then
+    echo To blackhole a whole /$mask is not reasonable
+    exit 1
+  fi
+  echo "Adding $net to blackhole:"
+  # then to the router blackhole :
+  vtysh -d bgpd -c "conf t" -c "router bgp 20766" -c "network $net route-map blackhole"
+  # then clear the out announce to our transit :
+  vtysh -d bgpd -c "clear ip bgp $BGPNEIGHBOR soft out"
+  #vtysh -d zebra -c "conf t" -c "ip route $net 127.0.0.1 blackhole"
+  route add $net 127.0.0.1 -blackhole
+elif [[ "$action" == "del" ]]; then
+  echo "Removing $net from blackhole:"
+  # then to the router blackhole :
+  vtysh -d bgpd -c "conf t" -c "router bgp 20766" -c "no network $net"
+  # then clear the out announce to our transit :
+  vtysh -d bgpd -c "clear ip bgp $BGPNEIGHBOR soft out"
+  #vtysh -d zebra -c "conf t" -c "no ip route $net 127.0.0.1 blackhole"
+  route del $net 127.0.0.1 -blackhole
+elif [[ "$action" == "list" ]]; then
+  echo Those networks are black-holed by BGPD:
+  vtysh -d bgpd -c 'show run' | grep 'network .* route-map blackhole' | awk '{print $2}'
+  echo Those networks are black-holed by ZEBRA via kernel:
+  vtysh -c 'sh ip route kernel' | grep 'lo0, bh' | awk '{print $2}'
+  vtysh -c 'sh ip route static' | grep 'lo0, bh' | awk '{print $2}'
+else
+  echo "Action  problem"
+  exit 1
+fi

+ 125 - 0
blackhole/flood-detector.sh

@@ -0,0 +1,125 @@
+#!/usr/local/bin/bash
+
+# Author:: Benjamin Sonntag (<benjamin _at_ sonntag _dot_ fr>)
+# Author:: Sebastien Badia (<seb _at_ sebian _dot_ fr>)
+# Author:: Philippe Le Brouster (<plb _at_ nebkha _dot_ net>)
+
+# detect flood by first counting the number of packets per second on an interface,
+# if the PPS is too high, search for a victim and add it to blackhole
+
+if [[ "x${DEBUG}" == "x1" ]]; then
+  set -e
+  set -x
+fi
+
+hostname=$(hostname -s)
+case $hostname in
+  "zoulou")
+    IFACE="em1.109"
+    ;;
+  "yankee")
+    IFACE="em0.179"
+    ;;
+  "x-ray")
+    IFACE="em0.3012"
+    ;;
+  "grimoire")
+    IFACE="eth0"
+    ;;
+  *)
+    echo "Unknown router"
+    exit 1
+esac
+
+# Above this rate, trigger the flood removal process
+MAXPPS=50000
+# Max PPS for the victim itself :
+MAXPPSVICTIM=5000
+# The mail recipient to notify :
+MAILRECIPIENT="root@gitoyen.net"
+
+show_usage(){
+  cat <<EOHELP
+Usage: $0 [OPTION]
+Flood detector and blackhole
+
+  -e      Nmap expression.
+  -i      Interface to catch (default $IFACE)
+  -n      PPs that trigger tcpdump (default $MAXPPS)
+  -t      PPs that trigger the blackhole (default $MAXPPSVICTIM)
+  -m      Recipient (default $MAILRECIPIENT)
+  -h      Show this help.
+
+./flood-detector.sh -e 'dst net 80.67.160.0/24 or dst net 80.67.174.0/24'
+
+EOHELP
+}
+
+while getopts "i:e:n:t:m:h" opt; do
+  case $opt in
+    e)
+      # Filter the tcpdump on that expression then
+      FILTER="$OPTARG"
+      ;;
+    n)
+      MAXPPS="$OPTARG"
+      ;;
+    t)
+      MAXPPSVICTIM="$OPTARG"
+      ;;
+    i)
+      IFACE="$OPTARG"
+      ;;
+    m)
+      MAILRECIPIENT="$OPTARG"
+      ;;
+    *)
+      show_usage
+      exit 1
+      ;;
+  esac
+done
+
+if [ -z "$FILTER" ]; then
+  show_usage
+  exit 1
+fi
+
+echo "Auto Blackholing"
+echo "IFACE        $IFACE"
+echo "FILTER       $FILTER"
+echo "MAXPPS       $MAXPPS"
+echo "MAXPPSVICTIM $MAXPPSVICTIM"
+
+while true
+do
+  INPPS=`netstat -w 1 -I "$IFACE" -q 3 | tail -1 | awk '{print $1}' `
+  if [ "$INPPS" -gt "$MAXPPS" ]
+    then
+      echo "`date` $INPPS > $MAXPPS, searching for a victim"
+      # Ok, we are flooded, turn the blackhole ON for the victim
+      #tcpdump -i "$IFACE" -p -n -w /tmp/flood.pcap "$FILTER" &
+      tcpdump -i "$IFACE" -p -n -w - "$FILTER" | gzip - > /tmp/flood.pcap.gz  &
+      ME="$!"
+      sleep 2
+      kill -TERM "$ME" >/dev/null 2>/dev/null
+      sleep 1
+      kill -KILL "$ME" >/dev/null 2>/dev/null
+      # Now find the victim and add it to the blackhole :
+      #BLACK="`tcpdump -r /tmp/flood.pcap -n 2>/dev/null |awk '{print $5}' |awk -F "." '{print $1 "." $2 "." $3 "." $4}' |sort | uniq -c | sort -gr | head -1`"
+      BLACK="` zcat /tmp/flood.pcap.gz 2>/dev/null | tcpdump -r - -n 2>/dev/null |awk '{print $5}' |awk -F "." '{print $1 "." $2 "." $3 "." $4}' |sort | uniq -c | sort -gr | head -1`"
+      BLACKCOUNT="`echo $BLACK | awk '{print $1}'`"
+      BLACKME="`echo $BLACK | awk '{print $2}'|cut -d':' -f1`"
+      if [ -n "$BLACKME" ] && [ -n "$BLACKCOUNT" ] && [ "$BLACKCOUNT" -gt "$MAXPPSVICTIM" ];
+      then
+        echo "`date` found $BLACKME that received $BLACKCOUNT pps, blackholing..."
+        # we got him, add him to the blackhole :
+        bash /tmp/blackhole.sh -a add -i ${BLACKME}/32
+        # And we tell the admin ;)
+	( echo "Automatic blackhole triggered at `date`" ; echo "PPS was $INPPS, and $BLACKCOUNT was sent to $BLACKME" ) | mail -s "Automatic Blackhole triggered on `hostname` for $BLACKME" $MAILRECIPIENT
+      else
+        echo "`date` Nobody found for the filtered expression, will try again later"
+      fi
+  fi
+sleep 5
+done