aegis-dos-protection/include/Inspection.hpp
2021-10-24 12:51:25 +02:00

315 lines
12 KiB
C++

/**
* @file Inspection.hpp
* @author Robert
* @brief the Inspection get packets polled by the PacketContainer and evaluates
* each packets legitimation. Invalid packets will be dropped while valid
* packets are forwarded to the Treatment.
* @version 0.5
* @date 2021-06-14
*
* @copyright Copyright (c) 2021
*
*/
#pragma once
#include "Configurator.hpp"
#include "PacketDissection/PacketContainer.hpp"
#include <rte_cycles.h>
#include <stdint.h>
/**
* @brief the Inspection evaluates PacketContainers and forwards valid packets
* while illegimite packets are destroyed
*
*/
class Inspection {
public:
/**
* @brief Construct a new Inspection object with default arguments from
* configuration file
*
*/
inline Inspection()
: _UDP_flood_weight(
Configurator::instance()->get_config_as_unsigned_int(
"UDP_flood_weight")),
_TCP_flood_weight(
Configurator::instance()->get_config_as_unsigned_int(
"TCP_flood_weight")),
_ICMP_flood_weight(
Configurator::instance()->get_config_as_unsigned_int(
"ICMP_flood_weight")),
_SYNFIN_weight(Configurator::instance()->get_config_as_unsigned_int(
"SYNFIN_weight")),
_SMALLWINDOW_weight(
Configurator::instance()->get_config_as_unsigned_int(
"SMALLWINDOW_weight")),
_threshold_UDP(Configurator::instance()->get_config_as_unsigned_int(
"threshold_UDP")),
_threshold_TCP(Configurator::instance()->get_config_as_unsigned_int(
"threshold_TCP")),
_threshold_ICMP(Configurator::instance()->get_config_as_unsigned_int(
"threshold_ICMP")),
_current_threshold_UDP(
Configurator::instance()->get_config_as_unsigned_int(
"threshold_UDP")),
_current_threshold_TCP(
Configurator::instance()->get_config_as_unsigned_int(
"threshold_TCP")),
_current_threshold_ICMP(
Configurator::instance()->get_config_as_unsigned_int(
"threshold_ICMP")),
_min_window_size(Configurator::instance()->get_config_as_unsigned_int(
"min_window_size")),
_attack_level(0), _packetrate_UDP(0), _packetrate_TCP(0),
_packetrate_ICMP(0), _clock_frequence(rte_get_tsc_hz()) {}
/**
* @brief update the current stats and send them to global statistic
*
* @param udp_packets
* @param tcp_packets
* @param icmp_packets
* @param UDP_Floods
* @param TCP_Floods
* @param ICMP_Floods
* @param SYN_FINs
* @param Small_Windows
* @param duration
*/
inline void update_stats(uint16_t udp_packets, uint16_t tcp_packets,
uint16_t icmp_packets, uint16_t UDP_Floods,
uint16_t TCP_Floods, uint16_t ICMP_Floods,
uint16_t SYN_FINs, uint16_t Small_Windows,
uint64_t duration) {
duration = duration > 1 ? duration : 1;
duration = duration * _clock_frequence;
// calculate new packetrate based on relative duration
_packetrate_UDP = udp_packets / duration;
_packetrate_TCP = tcp_packets / duration;
_packetrate_ICMP = icmp_packets / duration;
// calculate attack level based on diverent counted attacks and their
// weight on ddos
/// \todo (can) adapting weights to most occuring attacks
_attack_level =
UDP_Floods * _UDP_flood_weight + TCP_Floods * _TCP_flood_weight +
ICMP_Floods * _ICMP_flood_weight + SYN_FINs * _SYNFIN_weight +
Small_Windows * _SMALLWINDOW_weight;
// calculate new threshold
_current_threshold_UDP = _threshold_UDP - (1 / _threshold_UDP) *
_attack_level *
_attack_level;
_current_threshold_TCP = _threshold_TCP - (1 / _threshold_TCP) *
_attack_level *
_attack_level;
_current_threshold_ICMP = _threshold_ICMP - (1 / _threshold_ICMP) *
_attack_level *
_attack_level;
/// \todo send to global statistic
/* Stats update_statistics(
attacks = UDP_Floods + TCP_Floods + ICMP_Floods + SYN_FINs +
Small_Windows;
// bytes
// dropped
packets = udp_packets + tcp_packets + icmp_packets;
work_time = duration;
*/
}
/**
* @brief get packet container reference and run analysis on each packet
* included in the PacketContainer
*
* @param pkt_container PacketContainer with certain amount of packets
*
* \startuml
* title analyzePacket(PacketContainer)
* start
* :create temporary counters;
* :initiate packetIndex at 0;
* while(PacketContainer size > current packetIndex)
* :extract PacketInfo from PacketContainer at packetIndex;
* if (is UDP Protocoll) then (yes)
* :increase UDP counter;
* if(UDP Threshold met) then (yes)
* #FF0000:detected UDP Flood;
* :increase attack counter;
* :drop packet;
* else (no)
* endif
* elseif (is TCP Protocoll) then (yes)
* :increase TCP counter;
* if(TCP Threshold met) then (yes)
* #FF0000:detected TCP Flood;
* :increase attack counter;
* :drop packet;
* else (no)
* endif
* if(WindowSize too small) then (yes)
* #FF0000:detected Small/Zero Window;
* :increase attack counter;
* :drop packet;
* else (no)
* endif
* if(Flag Pattern forbidden) then (yes)
* #FF0000:detected SYN-FIN(-ACK);
* :increase attack counter;
* :drop packet;
* else (no)
* endif
* elseif (is ICMP Protocoll) then (yes)
* :increase ICMP counter;
* if(ICMP Threshold met) then (yes)
* #FF0000:detected ICMP Flood;
* :increase attack counter;
* :drop packet;
* else (no)
* endif
* else (no protocoll of interest)
* endif
* :increase packetIndex;
* endwhile
* :update local threshold with temporary counters;
* :send temporary counters to global statistic;
* end
* \enduml
*/
inline void analyze_container(PacketContainer* pkt_container) {
uint16_t temp_udp_packets = 0;
uint16_t temp_tcp_packets = 0;
uint16_t temp_icmp_packets = 0;
uint16_t temp_attack_UDP_Flood = 0;
uint16_t temp_attack_TCP_Flood = 0;
uint16_t temp_attack_ICMP_Flood = 0;
uint16_t temp_attack_SYN_FIN = 0;
uint16_t temp_attack_Small_Window = 0;
uint64_t startTime = rte_get_tsc_cycles();
for (int index = 0;
index < pkt_container->get_number_of_polled_packets(); ++index) {
PacketInfo* packetInfo = pkt_container->get_packet_at_index(index);
if (packetInfo != nullptr) {
switch (packetInfo->get_type()) {
case IPv4UDP: {
++temp_udp_packets;
if (temp_udp_packets > _current_threshold_UDP) {
// alt: if(_current_threshold_UDP > temp_udp_packets) {
++temp_attack_UDP_Flood;
// UDP Flood
/// \todo (can) create patchmap and allow last recent
/// established connections to connect further matching
/// srcIp & dstIp
pkt_container->drop_packet(index);
break;
}
// forward packet
break;
}
case IPv4TCP: {
PacketInfoIpv4Tcp* TCP4packetInfo =
static_cast<PacketInfoIpv4Tcp*>(packetInfo);
++temp_tcp_packets;
if (temp_tcp_packets > _current_threshold_TCP) {
// TCP Flood
/// \todo (can) create patchmap and allow last recent
/// established connections to connect further matching
/// srcIp & dstIp
++temp_attack_TCP_Flood;
pkt_container->drop_packet(index);
break;
}
if (TCP4packetInfo->get_window_size() < _min_window_size) {
// Zero/Small Window
++temp_attack_Small_Window;
pkt_container->drop_packet(index);
break;
}
if ((uint8_t(TCP4packetInfo->get_flags()) & 0b00000011) ==
0b00000011) {
// flags in reverse format
// FIN,SYN,RST,PSH,ACK,URG,ECE,CWR SYN-FIN/SYN-FIN-ACK
++temp_attack_SYN_FIN;
pkt_container->drop_packet(index);
break;
}
// forward packet
break;
}
case IPv4ICMP: {
++temp_icmp_packets;
if (temp_icmp_packets > _current_threshold_ICMP) {
// ICMP Flood
++temp_attack_ICMP_Flood;
pkt_container->drop_packet(index);
break;
}
// forward packet
break;
}
default: { // not identifyable or not of interest
// forward packet
break;
}
}
}
}
uint64_t endTime = rte_get_tsc_cycles();
update_stats(temp_udp_packets, temp_tcp_packets, temp_icmp_packets,
temp_attack_UDP_Flood, temp_attack_TCP_Flood,
temp_attack_ICMP_Flood, temp_attack_SYN_FIN,
temp_attack_Small_Window, (uint64_t)endTime - startTime);
return;
}
uint16_t get_UDP_packet_rate() { return _packetrate_UDP; };
uint16_t get_TCP_packet_rate() { return _packetrate_TCP; };
uint16_t get_ICMP_packet_rate() { return _packetrate_ICMP; };
uint16_t get_UDP_threshold() { return _current_threshold_UDP; };
uint16_t get_TCP_threshold() { return _current_threshold_TCP; };
uint16_t get_ICMP_threshold() { return _current_threshold_ICMP; };
uint16_t get_attack_level() { return _attack_level; };
private:
/// weight of UDP Flood attacks
uint8_t _UDP_flood_weight;
/// weight of TCP Flood attacks
uint8_t _TCP_flood_weight;
/// weight of ICMP Flood attacks
uint8_t _ICMP_flood_weight;
/// weight of SYN-FIN and SYN_FIN_ACK attacks
uint8_t _SYNFIN_weight;
/// weight of Zero/Small Window attacks
uint8_t _SMALLWINDOW_weight;
/// absolute threshold of udp packets
uint16_t _threshold_UDP;
/// absolute threshold of tcp packets
uint16_t _threshold_TCP;
/// absolute threshold of icmp packets
uint16_t _threshold_ICMP;
/// current threshold of udp packets
uint16_t _current_threshold_UDP;
/// current threshold of tcp packets
uint16_t _current_threshold_TCP;
/// current threshold of icmp packets
uint16_t _current_threshold_ICMP;
/// min window size for no-small-window
uint16_t _min_window_size;
/// current attack level
uint16_t _attack_level;
/// current packetrate of udp packets
uint64_t _packetrate_UDP;
/// current packetrate of tcp packets
uint64_t _packetrate_TCP;
/// current packetrate of icmp packets
uint64_t _packetrate_ICMP;
/// TSC frequency for this lcore
uint64_t _clock_frequence;
};