xref: /aosp_15_r20/external/bcc/examples/tracing/dddos.py (revision 387f9dfdfa2baef462e92476d413c7bc2470293e)
1*387f9dfdSAndroid Build Coastguard Worker#!/usr/bin/python
2*387f9dfdSAndroid Build Coastguard Worker#
3*387f9dfdSAndroid Build Coastguard Worker# dddos.py	DDOS dectection system.
4*387f9dfdSAndroid Build Coastguard Worker#
5*387f9dfdSAndroid Build Coastguard Worker# Written as a basic tracing example of using ePBF
6*387f9dfdSAndroid Build Coastguard Worker# to detect a potential DDOS attack against a system.
7*387f9dfdSAndroid Build Coastguard Worker#
8*387f9dfdSAndroid Build Coastguard Worker# Copyright (c) 2019 Jugurtha BELKALEM.
9*387f9dfdSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License")
10*387f9dfdSAndroid Build Coastguard Worker#
11*387f9dfdSAndroid Build Coastguard Worker# 14-Jan-2019 Jugurtha BELKALEM Created this.
12*387f9dfdSAndroid Build Coastguard Worker
13*387f9dfdSAndroid Build Coastguard Workerfrom bcc import BPF
14*387f9dfdSAndroid Build Coastguard Workerimport ctypes as ct
15*387f9dfdSAndroid Build Coastguard Workerimport datetime
16*387f9dfdSAndroid Build Coastguard Workerprog = """
17*387f9dfdSAndroid Build Coastguard Worker#include <linux/skbuff.h>
18*387f9dfdSAndroid Build Coastguard Worker#include <uapi/linux/ip.h>
19*387f9dfdSAndroid Build Coastguard Worker
20*387f9dfdSAndroid Build Coastguard Worker#define MAX_NB_PACKETS 1000
21*387f9dfdSAndroid Build Coastguard Worker#define LEGAL_DIFF_TIMESTAMP_PACKETS 1000000
22*387f9dfdSAndroid Build Coastguard Worker
23*387f9dfdSAndroid Build Coastguard WorkerBPF_HASH(rcv_packets);
24*387f9dfdSAndroid Build Coastguard Worker
25*387f9dfdSAndroid Build Coastguard Workerstruct detectionPackets {
26*387f9dfdSAndroid Build Coastguard Worker    u64 nb_ddos_packets;
27*387f9dfdSAndroid Build Coastguard Worker};
28*387f9dfdSAndroid Build Coastguard Worker
29*387f9dfdSAndroid Build Coastguard WorkerBPF_PERF_OUTPUT(events);
30*387f9dfdSAndroid Build Coastguard Worker
31*387f9dfdSAndroid Build Coastguard Workerint detect_ddos(struct pt_regs *ctx, void *skb){
32*387f9dfdSAndroid Build Coastguard Worker    struct detectionPackets detectionPacket = {};
33*387f9dfdSAndroid Build Coastguard Worker
34*387f9dfdSAndroid Build Coastguard Worker    // Used to count number of received packets
35*387f9dfdSAndroid Build Coastguard Worker    u64 rcv_packets_nb_index = 0, rcv_packets_nb_inter=1, *rcv_packets_nb_ptr;
36*387f9dfdSAndroid Build Coastguard Worker
37*387f9dfdSAndroid Build Coastguard Worker    // Used to measure elapsed time between 2 successive received packets
38*387f9dfdSAndroid Build Coastguard Worker    u64 rcv_packets_ts_index = 1, rcv_packets_ts_inter=0, *rcv_packets_ts_ptr;
39*387f9dfdSAndroid Build Coastguard Worker
40*387f9dfdSAndroid Build Coastguard Worker    /* The algorithm analyses packets received by ip_rcv function
41*387f9dfdSAndroid Build Coastguard Worker    * and measures the difference in reception time between each packet.
42*387f9dfdSAndroid Build Coastguard Worker    * DDOS flooders send millions of packets such that difference of
43*387f9dfdSAndroid Build Coastguard Worker    * timestamp between 2 successive packets is so small
44*387f9dfdSAndroid Build Coastguard Worker    * (which is not like regular applications behaviour).
45*387f9dfdSAndroid Build Coastguard Worker    * This script looks for this difference in time and if it sees
46*387f9dfdSAndroid Build Coastguard Worker    * more than MAX_NB_PACKETS successive packets with a difference
47*387f9dfdSAndroid Build Coastguard Worker    * of timestamp between each one of them less than
48*387f9dfdSAndroid Build Coastguard Worker    * LEGAL_DIFF_TIMESTAMP_PACKETS ns,
49*387f9dfdSAndroid Build Coastguard Worker    * ------------------ It Triggers an ALERT -----------------
50*387f9dfdSAndroid Build Coastguard Worker    * Those settings must be adapted depending on regular network traffic
51*387f9dfdSAndroid Build Coastguard Worker    * -------------------------------------------------------------------
52*387f9dfdSAndroid Build Coastguard Worker    * Important: this is a rudimentary intrusion detection system, one can
53*387f9dfdSAndroid Build Coastguard Worker    * test a real case attack using hping3. However; if regular network
54*387f9dfdSAndroid Build Coastguard Worker    * traffic increases above predefined detection settings, a false
55*387f9dfdSAndroid Build Coastguard Worker    * positive alert will be triggered (an example would be the
56*387f9dfdSAndroid Build Coastguard Worker    * case of large file downloads).
57*387f9dfdSAndroid Build Coastguard Worker    */
58*387f9dfdSAndroid Build Coastguard Worker    rcv_packets_nb_ptr = rcv_packets.lookup(&rcv_packets_nb_index);
59*387f9dfdSAndroid Build Coastguard Worker    rcv_packets_ts_ptr = rcv_packets.lookup(&rcv_packets_ts_index);
60*387f9dfdSAndroid Build Coastguard Worker    if(rcv_packets_nb_ptr != 0 && rcv_packets_ts_ptr != 0){
61*387f9dfdSAndroid Build Coastguard Worker        rcv_packets_nb_inter = *rcv_packets_nb_ptr;
62*387f9dfdSAndroid Build Coastguard Worker        rcv_packets_ts_inter = bpf_ktime_get_ns() - *rcv_packets_ts_ptr;
63*387f9dfdSAndroid Build Coastguard Worker        if(rcv_packets_ts_inter < LEGAL_DIFF_TIMESTAMP_PACKETS){
64*387f9dfdSAndroid Build Coastguard Worker            rcv_packets_nb_inter++;
65*387f9dfdSAndroid Build Coastguard Worker        } else {
66*387f9dfdSAndroid Build Coastguard Worker            rcv_packets_nb_inter = 0;
67*387f9dfdSAndroid Build Coastguard Worker        }
68*387f9dfdSAndroid Build Coastguard Worker        if(rcv_packets_nb_inter > MAX_NB_PACKETS){
69*387f9dfdSAndroid Build Coastguard Worker            detectionPacket.nb_ddos_packets = rcv_packets_nb_inter;
70*387f9dfdSAndroid Build Coastguard Worker            events.perf_submit(ctx, &detectionPacket, sizeof(detectionPacket));
71*387f9dfdSAndroid Build Coastguard Worker        }
72*387f9dfdSAndroid Build Coastguard Worker    }
73*387f9dfdSAndroid Build Coastguard Worker    rcv_packets_ts_inter = bpf_ktime_get_ns();
74*387f9dfdSAndroid Build Coastguard Worker    rcv_packets.update(&rcv_packets_nb_index, &rcv_packets_nb_inter);
75*387f9dfdSAndroid Build Coastguard Worker    rcv_packets.update(&rcv_packets_ts_index, &rcv_packets_ts_inter);
76*387f9dfdSAndroid Build Coastguard Worker    return 0;
77*387f9dfdSAndroid Build Coastguard Worker}
78*387f9dfdSAndroid Build Coastguard Worker"""
79*387f9dfdSAndroid Build Coastguard Worker
80*387f9dfdSAndroid Build Coastguard Worker# Loads eBPF program
81*387f9dfdSAndroid Build Coastguard Workerb = BPF(text=prog)
82*387f9dfdSAndroid Build Coastguard Worker
83*387f9dfdSAndroid Build Coastguard Worker# Attach kprobe to kernel function and sets detect_ddos as kprobe handler
84*387f9dfdSAndroid Build Coastguard Workerb.attach_kprobe(event="ip_rcv", fn_name="detect_ddos")
85*387f9dfdSAndroid Build Coastguard Worker
86*387f9dfdSAndroid Build Coastguard Workerclass DetectionTimestamp(ct.Structure):
87*387f9dfdSAndroid Build Coastguard Worker    _fields_ = [("nb_ddos_packets", ct.c_ulonglong)]
88*387f9dfdSAndroid Build Coastguard Worker
89*387f9dfdSAndroid Build Coastguard Worker# Show message when ePBF starts
90*387f9dfdSAndroid Build Coastguard Workerprint("DDOS detector started ... Hit Ctrl-C to end!")
91*387f9dfdSAndroid Build Coastguard Worker
92*387f9dfdSAndroid Build Coastguard Workerprint("%-26s %-10s" % ("TIME(s)", "MESSAGE"))
93*387f9dfdSAndroid Build Coastguard Worker
94*387f9dfdSAndroid Build Coastguard Workerdef trigger_alert_event(cpu, data, size):
95*387f9dfdSAndroid Build Coastguard Worker    event = ct.cast(data, ct.POINTER(DetectionTimestamp)).contents
96*387f9dfdSAndroid Build Coastguard Worker    print("%-26s %s %ld" % (datetime.datetime.now(),
97*387f9dfdSAndroid Build Coastguard Worker    "DDOS Attack => nb of packets up to now : ", event.nb_ddos_packets))
98*387f9dfdSAndroid Build Coastguard Worker
99*387f9dfdSAndroid Build Coastguard Worker# loop with callback to trigger_alert_event
100*387f9dfdSAndroid Build Coastguard Workerb["events"].open_perf_buffer(trigger_alert_event)
101*387f9dfdSAndroid Build Coastguard Workerwhile 1:
102*387f9dfdSAndroid Build Coastguard Worker    try:
103*387f9dfdSAndroid Build Coastguard Worker        b.perf_buffer_poll()
104*387f9dfdSAndroid Build Coastguard Worker    except KeyboardInterrupt:
105*387f9dfdSAndroid Build Coastguard Worker        exit()
106