forked from iovisor/bcc
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
ddos_detector.py to monitor DDOS attacks (iovisor#2140)
ddos_detector.py to monitor DDOS attacks
- Loading branch information
1 parent
3f7b596
commit c77b158
Showing
2 changed files
with
141 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
#!/usr/bin/python | ||
# | ||
# dddos.py DDOS dectection system. | ||
# | ||
# Written as a basic tracing example of using ePBF | ||
# to detect a potential DDOS attack against a system. | ||
# | ||
# Copyright (c) 2019 Jugurtha BELKALEM. | ||
# Licensed under the Apache License, Version 2.0 (the "License") | ||
# | ||
# 14-Jan-2019 Jugurtha BELKALEM Created this. | ||
|
||
from bcc import BPF | ||
import ctypes as ct | ||
import datetime | ||
prog = """ | ||
#include <linux/skbuff.h> | ||
#include <uapi/linux/ip.h> | ||
#define MAX_NB_PACKETS 1000 | ||
#define LEGAL_DIFF_TIMESTAMP_PACKETS 1000000 | ||
BPF_HASH(rcv_packets); | ||
struct detectionPackets { | ||
u64 nb_ddos_packets; | ||
}; | ||
BPF_PERF_OUTPUT(events); | ||
int detect_ddos(struct pt_regs *ctx, void *skb){ | ||
struct detectionPackets detectionPacket = {}; | ||
// Used to count number of received packets | ||
u64 rcv_packets_nb_index = 0, rcv_packets_nb_inter=1, *rcv_packets_nb_ptr; | ||
// Used to measure elapsed time between 2 successive received packets | ||
u64 rcv_packets_ts_index = 1, rcv_packets_ts_inter=0, *rcv_packets_ts_ptr; | ||
/* The algorithm analyses packets received by ip_rcv function | ||
* and measures the difference in reception time between each packet. | ||
* DDOS flooders send millions of packets such that difference of | ||
* timestamp between 2 successive packets is so small | ||
* (which is not like regular applications behaviour). | ||
* This script looks for this difference in time and if it sees | ||
* more than MAX_NB_PACKETS succesive packets with a difference | ||
* of timestamp between each one of them less than | ||
* LEGAL_DIFF_TIMESTAMP_PACKETS ns, | ||
* ------------------ It Triggers an ALERT ----------------- | ||
* Those settings must be adapted depending on regular network traffic | ||
* ------------------------------------------------------------------- | ||
* Important: this is a rudimentary intrusion detection system, one can | ||
* test a real case attack using hping3. However; if regular network | ||
* traffic increases above predefined detection settings, a false | ||
* positive alert will be triggered (an example would be the | ||
case of large file downloads). | ||
*/ | ||
rcv_packets_nb_ptr = rcv_packets.lookup(&rcv_packets_nb_index); | ||
rcv_packets_ts_ptr = rcv_packets.lookup(&rcv_packets_ts_index); | ||
if(rcv_packets_nb_ptr != 0 && rcv_packets_ts_ptr != 0){ | ||
rcv_packets_nb_inter = *rcv_packets_nb_ptr; | ||
rcv_packets_ts_inter = bpf_ktime_get_ns() - *rcv_packets_ts_ptr; | ||
if(rcv_packets_ts_inter < LEGAL_DIFF_TIMESTAMP_PACKETS){ | ||
rcv_packets_nb_inter++; | ||
} else { | ||
rcv_packets_nb_inter = 0; | ||
} | ||
if(rcv_packets_nb_inter > MAX_NB_PACKETS){ | ||
detectionPacket.nb_ddos_packets = rcv_packets_nb_inter; | ||
events.perf_submit(ctx, &detectionPacket, sizeof(detectionPacket)); | ||
} | ||
} | ||
rcv_packets_ts_inter = bpf_ktime_get_ns(); | ||
rcv_packets.update(&rcv_packets_nb_index, &rcv_packets_nb_inter); | ||
rcv_packets.update(&rcv_packets_ts_index, &rcv_packets_ts_inter); | ||
return 0; | ||
} | ||
""" | ||
|
||
# Loads eBPF program | ||
b = BPF(text=prog) | ||
|
||
# Attach kprobe to kernel function and sets detect_ddos as kprobe handler | ||
b.attach_kprobe(event="ip_rcv", fn_name="detect_ddos") | ||
|
||
class DetectionTimestamp(ct.Structure): | ||
_fields_ = [("nb_ddos_packets", ct.c_ulonglong)] | ||
|
||
# Show message when ePBF stats | ||
print("DDOS detector started ... Hit Ctrl-C to end!") | ||
|
||
print("%-26s %-10s" % ("TIME(s)", "MESSAGE")) | ||
|
||
def trigger_alert_event(cpu, data, size): | ||
event = ct.cast(data, ct.POINTER(DetectionTimestamp)).contents | ||
print("%-26s %s %ld" % (datetime.datetime.now(), | ||
"DDOS Attack => nb of packets up to now : ", event.nb_ddos_packets)) | ||
|
||
# loop with callback to trigger_alert_event | ||
b["events"].open_perf_buffer(trigger_alert_event) | ||
while 1: | ||
b.perf_buffer_poll() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
Demonstrations of dddos.py, the Linux eBPF/bcc version. | ||
|
||
This tracks ip_rcv function (using kprobe) and elapsed time | ||
between received packets to detect potential DDOS attacks. | ||
|
||
The following steps illustrates the usage of dddos : | ||
1 - Start dddos.py : | ||
# ./dddos.py | ||
DDOS detector started ... Hit Ctrl-C to end! | ||
TIME(s) MESSAGE | ||
|
||
2 - Launch hping3 (or any other flooder) in another terminal as shown below: | ||
# hping3 localhost -S -A -V -p 443 -i u100 | ||
|
||
3 - dddos.py triggers alerts and reports a DDOS attack: | ||
DDOS detector started ... Hit Ctrl-C to end! | ||
TIME(s) MESSAGE | ||
2019-01-16 11:55:12.600734 DDOS Attack => nb of packets up to now : 1001 | ||
2019-01-16 11:55:12.600845 DDOS Attack => nb of packets up to now : 1002 | ||
2019-01-16 11:55:12.600887 DDOS Attack => nb of packets up to now : 1003 | ||
2019-01-16 11:55:12.600971 DDOS Attack => nb of packets up to now : 1004 | ||
2019-01-16 11:55:12.601009 DDOS Attack => nb of packets up to now : 1005 | ||
2019-01-16 11:55:12.601062 DDOS Attack => nb of packets up to now : 1006 | ||
2019-01-16 11:55:12.601096 DDOS Attack => nb of packets up to now : 1007 | ||
2019-01-16 11:55:12.601195 DDOS Attack => nb of packets up to now : 1008 | ||
2019-01-16 11:55:12.601228 DDOS Attack => nb of packets up to now : 1009 | ||
2019-01-16 11:55:12.601331 DDOS Attack => nb of packets up to now : 1010 | ||
2019-01-16 11:55:12.601364 DDOS Attack => nb of packets up to now : 1011 | ||
2019-01-16 11:55:12.601470 DDOS Attack => nb of packets up to now : 1012 | ||
2019-01-16 11:55:12.601505 DDOS Attack => nb of packets up to now : 1013 | ||
2019-01-16 11:55:12.601621 DDOS Attack => nb of packets up to now : 1014 | ||
2019-01-16 11:55:12.601656 DDOS Attack => nb of packets up to now : 1015 | ||
2019-01-16 11:55:12.601757 DDOS Attack => nb of packets up to now : 1016 | ||
2019-01-16 11:55:12.601790 DDOS Attack => nb of packets up to now : 1017 | ||
2019-01-16 11:55:12.601892 DDOS Attack => nb of packets up to now : 1018 | ||
2019-01-16 11:55:12.601925 DDOS Attack => nb of packets up to now : 1019 | ||
2019-01-16 11:55:12.602028 DDOS Attack => nb of packets up to now : 1020 | ||
|
||
Remark : Use Ctrl-C to stop dddos.py |