dddos.php 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. <?php
  2. $prog = <<<EOT
  3. #include <linux/skbuff.h>
  4. #include <uapi/linux/ip.h>
  5. #define MAX_NB_PACKETS 1000
  6. #define LEGAL_DIFF_TIMESTAMP_PACKETS 1000000
  7. BPF_HASH(rcv_packets);
  8. struct detectionPackets {
  9. u64 nb_ddos_packets;
  10. };
  11. BPF_PERF_OUTPUT(events);
  12. int detect_ddos(struct pt_regs *ctx, void *skb){
  13. struct detectionPackets detectionPacket = {};
  14. // Used to count number of received packets
  15. u64 rcv_packets_nb_index = 0, rcv_packets_nb_inter=1, *rcv_packets_nb_ptr;
  16. // Used to measure elapsed time between 2 successive received packets
  17. u64 rcv_packets_ts_index = 1, rcv_packets_ts_inter=0, *rcv_packets_ts_ptr;
  18. /* The algorithm analyses packets received by ip_rcv function
  19. * and measures the difference in reception time between each packet.
  20. * DDOS flooders send millions of packets such that difference of
  21. * timestamp between 2 successive packets is so small
  22. * (which is not like regular applications behaviour).
  23. * This script looks for this difference in time and if it sees
  24. * more than MAX_NB_PACKETS successive packets with a difference
  25. * of timestamp between each one of them less than
  26. * LEGAL_DIFF_TIMESTAMP_PACKETS ns,
  27. * ------------------ It Triggers an ALERT -----------------
  28. * Those settings must be adapted depending on regular network traffic
  29. * -------------------------------------------------------------------
  30. * Important: this is a rudimentary intrusion detection system, one can
  31. * test a real case attack using hping3. However; if regular network
  32. * traffic increases above predefined detection settings, a false
  33. * positive alert will be triggered (an example would be the
  34. * case of large file downloads).
  35. */
  36. rcv_packets_nb_ptr = rcv_packets.lookup(&rcv_packets_nb_index);
  37. rcv_packets_ts_ptr = rcv_packets.lookup(&rcv_packets_ts_index);
  38. if(rcv_packets_nb_ptr != 0 && rcv_packets_ts_ptr != 0){
  39. rcv_packets_nb_inter = *rcv_packets_nb_ptr;
  40. rcv_packets_ts_inter = bpf_ktime_get_ns() - *rcv_packets_ts_ptr;
  41. if(rcv_packets_ts_inter < LEGAL_DIFF_TIMESTAMP_PACKETS){
  42. rcv_packets_nb_inter++;
  43. } else {
  44. rcv_packets_nb_inter = 0;
  45. }
  46. if(rcv_packets_nb_inter > MAX_NB_PACKETS){
  47. detectionPacket.nb_ddos_packets = rcv_packets_nb_inter;
  48. events.perf_submit(ctx, &detectionPacket, sizeof(detectionPacket));
  49. }
  50. }
  51. rcv_packets_ts_inter = bpf_ktime_get_ns();
  52. rcv_packets.update(&rcv_packets_nb_index, &rcv_packets_nb_inter);
  53. rcv_packets.update(&rcv_packets_ts_index, &rcv_packets_ts_inter);
  54. return 0;
  55. }
  56. EOT;
  57. $b = new Bpf(["text" => $prog]);
  58. $b->attach_kprobe("ip_rcv", "detect_ddos");
  59. echo "DDOS detector started ... Hit Ctrl-C to end!\n";
  60. echo sprintf("%-26s %-10s\n", "TIME(s)", "MESSAGE");
  61. function trigger_alert_event($ctx, $data, $size)
  62. {
  63. $event = unpack("Qnb_ddos_packets", $data);
  64. echo sprintf("%-26s %s %ld\n", date("Y-m-d H:i:s"), "DDOS Attack => nb of packets up to now: ", $event['nb_ddos_packets']);
  65. }
  66. $b->events->open_perf_buffer("trigger_alert_event");
  67. while (true) {
  68. try {
  69. $b->perf_buffer_poll();
  70. } catch (Exception $e) {
  71. exit;
  72. }
  73. }