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