flood-detector.sh 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. #!/usr/local/bin/bash
  2. # Author:: Benjamin Sonntag (<benjamin _at_ sonntag _dot_ fr>)
  3. # Author:: Sebastien Badia (<seb _at_ sebian _dot_ fr>)
  4. # Author:: Philippe Le Brouster (<plb _at_ nebkha _dot_ net>)
  5. # detect flood by first counting the number of packets per second on an interface,
  6. # if the PPS is too high, search for a victim and add it to blackhole
  7. if [[ "x${DEBUG}" == "x1" ]]; then
  8. set -e
  9. set -x
  10. fi
  11. hostname=$(hostname -s)
  12. case $hostname in
  13. "zoulou")
  14. IFACE="em1.109"
  15. ;;
  16. "yankee")
  17. IFACE="em0.179"
  18. ;;
  19. "x-ray")
  20. IFACE="em0.3012"
  21. ;;
  22. "grimoire")
  23. IFACE="eth0"
  24. ;;
  25. *)
  26. echo "Unknown router"
  27. exit 1
  28. esac
  29. # Above this rate, trigger the flood removal process
  30. MAXPPS=50000
  31. # Max PPS for the victim itself :
  32. MAXPPSVICTIM=5000
  33. # The mail recipient to notify :
  34. MAILRECIPIENT="root@gitoyen.net"
  35. show_usage(){
  36. cat <<EOHELP
  37. Usage: $0 [OPTION]
  38. Flood detector and blackhole
  39. -e Nmap expression.
  40. -i Interface to catch (default $IFACE)
  41. -n PPs that trigger tcpdump (default $MAXPPS)
  42. -t PPs that trigger the blackhole (default $MAXPPSVICTIM)
  43. -m Recipient (default $MAILRECIPIENT)
  44. -h Show this help.
  45. ./flood-detector.sh -e 'dst net 80.67.160.0/24 or dst net 80.67.174.0/24'
  46. EOHELP
  47. }
  48. while getopts "i:e:n:t:m:h" opt; do
  49. case $opt in
  50. e)
  51. # Filter the tcpdump on that expression then
  52. FILTER="$OPTARG"
  53. ;;
  54. n)
  55. MAXPPS="$OPTARG"
  56. ;;
  57. t)
  58. MAXPPSVICTIM="$OPTARG"
  59. ;;
  60. i)
  61. IFACE="$OPTARG"
  62. ;;
  63. m)
  64. MAILRECIPIENT="$OPTARG"
  65. ;;
  66. *)
  67. show_usage
  68. exit 1
  69. ;;
  70. esac
  71. done
  72. if [ -z "$FILTER" ]; then
  73. show_usage
  74. exit 1
  75. fi
  76. echo "Auto Blackholing"
  77. echo "IFACE $IFACE"
  78. echo "FILTER $FILTER"
  79. echo "MAXPPS $MAXPPS"
  80. echo "MAXPPSVICTIM $MAXPPSVICTIM"
  81. while true
  82. do
  83. INPPS=`netstat -w 1 -I "$IFACE" -q 3 | tail -1 | awk '{print $1}' `
  84. if [ "$INPPS" -gt "$MAXPPS" ]
  85. then
  86. echo "`date` $INPPS > $MAXPPS, searching for a victim"
  87. # Ok, we are flooded, turn the blackhole ON for the victim
  88. #tcpdump -i "$IFACE" -p -n -w /tmp/flood.pcap "$FILTER" &
  89. tcpdump -i "$IFACE" -p -n -w - "$FILTER" | gzip - > /tmp/flood.pcap.gz &
  90. ME="$!"
  91. sleep 2
  92. kill -TERM "$ME" >/dev/null 2>/dev/null
  93. sleep 1
  94. kill -KILL "$ME" >/dev/null 2>/dev/null
  95. # Now find the victim and add it to the blackhole :
  96. #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`"
  97. 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`"
  98. BLACKCOUNT="`echo $BLACK | awk '{print $1}'`"
  99. BLACKME="`echo $BLACK | awk '{print $2}'|cut -d':' -f1`"
  100. if [ -n "$BLACKME" ] && [ -n "$BLACKCOUNT" ] && [ "$BLACKCOUNT" -gt "$MAXPPSVICTIM" ];
  101. then
  102. echo "`date` found $BLACKME that received $BLACKCOUNT pps, blackholing..."
  103. # we got him, add him to the blackhole :
  104. bash /tmp/blackhole.sh -a add -i ${BLACKME}/32
  105. # And we tell the admin ;)
  106. ( 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
  107. else
  108. echo "`date` Nobody found for the filtered expression, will try again later"
  109. fi
  110. fi
  111. sleep 5
  112. done