1
0
Fork 0
mirror of https://github.com/pavel-odintsov/fastnetmon synced 2024-05-04 02:36:17 +02:00

Unified logic to store attack's traffic

This commit is contained in:
Pavel Odintsov 2023-07-10 15:58:32 +01:00
parent d0076012e6
commit f6bad000a0
4 changed files with 68 additions and 176 deletions

View File

@ -4,7 +4,7 @@
#include <boost/serialization/nvp.hpp>
// structure with attack details
class attack_details_t : public subnet_counter_t {
class attack_details_t {
public:
// This operation is very heavy, it may crash in case of entropy shortage and it actually happened to our customer
bool generate_uuid() {
@ -45,14 +45,6 @@ class attack_details_t : public subnet_counter_t {
// Separate section with traffic counters
subnet_counter_t traffic_counters{};
// Average counters
uint64_t average_in_bytes = 0;
uint64_t average_out_bytes = 0;
uint64_t average_in_packets = 0;
uint64_t average_out_packets = 0;
uint64_t average_in_flows = 0;
uint64_t average_out_flows = 0;
// Time when we ban this IP
time_t ban_timestamp = 0;
bool unban_enabled = true;

View File

@ -1032,46 +1032,45 @@ std::string serialize_attack_description(const attack_details_t& current_attack)
<< "Attack direction: " << get_direction_name(current_attack.attack_direction) << "\n"
<< "Attack protocol: " << get_printable_protocol_name(current_attack.attack_protocol) << "\n";
attack_description << "Total incoming traffic: " << convert_speed_to_mbps(current_attack.total.in_bytes) << " mbps\n"
<< "Total outgoing traffic: " << convert_speed_to_mbps(current_attack.total.out_bytes) << " mbps\n"
<< "Total incoming pps: " << current_attack.total.in_packets << " packets per second\n"
<< "Total outgoing pps: " << current_attack.total.out_packets << " packets per second\n"
<< "Total incoming flows: " << current_attack.in_flows << " flows per second\n"
<< "Total outgoing flows: " << current_attack.out_flows << " flows per second\n";
// Add average counters
attack_description << "Average incoming traffic: " << convert_speed_to_mbps(current_attack.average_in_bytes) << " mbps\n"
<< "Average outgoing traffic: " << convert_speed_to_mbps(current_attack.average_out_bytes) << " mbps\n"
<< "Average incoming pps: " << current_attack.average_in_packets << " packets per second\n"
<< "Average outgoing pps: " << current_attack.average_out_packets << " packets per second\n"
<< "Average incoming flows: " << current_attack.average_in_flows << " flows per second\n"
<< "Average outgoing flows: " << current_attack.average_out_flows << " flows per second\n";
attack_description
<< "Total incoming traffic: " << convert_speed_to_mbps(current_attack.traffic_counters.total.in_bytes) << " mbps\n"
<< "Total outgoing traffic: " << convert_speed_to_mbps(current_attack.traffic_counters.total.out_bytes) << " mbps\n"
<< "Total incoming pps: " << current_attack.traffic_counters.total.in_packets << " packets per second\n"
<< "Total outgoing pps: " << current_attack.traffic_counters.total.out_packets << " packets per second\n"
<< "Total incoming flows: " << current_attack.traffic_counters.in_flows << " flows per second\n"
<< "Total outgoing flows: " << current_attack.traffic_counters.out_flows << " flows per second\n";
attack_description
<< "Incoming ip fragmented traffic: " << convert_speed_to_mbps(current_attack.fragmented.in_bytes) << " mbps\n"
<< "Outgoing ip fragmented traffic: " << convert_speed_to_mbps(current_attack.fragmented.out_bytes) << " mbps\n"
<< "Incoming ip fragmented pps: " << current_attack.fragmented.in_packets << " packets per second\n"
<< "Outgoing ip fragmented pps: " << current_attack.fragmented.out_packets << " packets per second\n"
<< "Incoming ip fragmented traffic: " << convert_speed_to_mbps(current_attack.traffic_counters.fragmented.in_bytes) << " mbps\n"
<< "Outgoing ip fragmented traffic: " << convert_speed_to_mbps(current_attack.traffic_counters.fragmented.out_bytes)
<< " mbps\n"
<< "Incoming ip fragmented pps: " << current_attack.traffic_counters.fragmented.in_packets << " packets per second\n"
<< "Outgoing ip fragmented pps: " << current_attack.traffic_counters.fragmented.out_packets << " packets per second\n"
<< "Incoming tcp traffic: " << convert_speed_to_mbps(current_attack.tcp.in_bytes) << " mbps\n"
<< "Outgoing tcp traffic: " << convert_speed_to_mbps(current_attack.tcp.out_bytes) << " mbps\n"
<< "Incoming tcp pps: " << current_attack.tcp.in_packets << " packets per second\n"
<< "Outgoing tcp pps: " << current_attack.tcp.out_packets << " packets per second\n"
<< "Incoming syn tcp traffic: " << convert_speed_to_mbps(current_attack.tcp_syn.in_bytes) << " mbps\n"
<< "Outgoing syn tcp traffic: " << convert_speed_to_mbps(current_attack.tcp_syn.out_bytes) << " mbps\n"
<< "Incoming syn tcp pps: " << current_attack.tcp_syn.in_packets << " packets per second\n"
<< "Outgoing syn tcp pps: " << current_attack.tcp_syn.out_packets << " packets per second\n"
<< "Incoming dropped traffic: " << convert_speed_to_mbps(current_attack.traffic_counters.dropped.in_bytes) << " mbps\n"
<< "Outgoing dropped traffic: " << convert_speed_to_mbps(current_attack.traffic_counters.dropped.out_bytes) << " mbps\n"
<< "Incoming dropped pps: " << current_attack.traffic_counters.dropped.in_packets << " packets per second\n"
<< "Outgoing dropped pps: " << current_attack.traffic_counters.dropped.out_packets << " packets per second\n"
<< "Incoming udp traffic: " << convert_speed_to_mbps(current_attack.udp.in_bytes) << " mbps\n"
<< "Outgoing udp traffic: " << convert_speed_to_mbps(current_attack.udp.out_bytes) << " mbps\n"
<< "Incoming udp pps: " << current_attack.udp.in_packets << " packets per second\n"
<< "Outgoing udp pps: " << current_attack.udp.out_packets << " packets per second\n"
<< "Incoming tcp traffic: " << convert_speed_to_mbps(current_attack.traffic_counters.tcp.in_bytes) << " mbps\n"
<< "Outgoing tcp traffic: " << convert_speed_to_mbps(current_attack.traffic_counters.tcp.out_bytes) << " mbps\n"
<< "Incoming tcp pps: " << current_attack.traffic_counters.tcp.in_packets << " packets per second\n"
<< "Outgoing tcp pps: " << current_attack.traffic_counters.tcp.out_packets << " packets per second\n"
<< "Incoming syn tcp traffic: " << convert_speed_to_mbps(current_attack.traffic_counters.tcp_syn.in_bytes) << " mbps\n"
<< "Outgoing syn tcp traffic: " << convert_speed_to_mbps(current_attack.traffic_counters.tcp_syn.out_bytes) << " mbps\n"
<< "Incoming syn tcp pps: " << current_attack.traffic_counters.tcp_syn.in_packets << " packets per second\n"
<< "Outgoing syn tcp pps: " << current_attack.traffic_counters.tcp_syn.out_packets << " packets per second\n"
<< "Incoming udp traffic: " << convert_speed_to_mbps(current_attack.traffic_counters.udp.in_bytes) << " mbps\n"
<< "Outgoing udp traffic: " << convert_speed_to_mbps(current_attack.traffic_counters.udp.out_bytes) << " mbps\n"
<< "Incoming udp pps: " << current_attack.traffic_counters.udp.in_packets << " packets per second\n"
<< "Outgoing udp pps: " << current_attack.traffic_counters.udp.out_packets << " packets per second\n"
<< "Incoming icmp traffic: " << convert_speed_to_mbps(current_attack.traffic_counters.icmp.in_bytes) << " mbps\n"
<< "Outgoing icmp traffic: " << convert_speed_to_mbps(current_attack.traffic_counters.icmp.out_bytes) << " mbps\n"
<< "Incoming icmp pps: " << current_attack.traffic_counters.icmp.in_packets << " packets per second\n"
<< "Outgoing icmp pps: " << current_attack.traffic_counters.icmp.out_packets << " packets per second\n";
<< "Incoming icmp traffic: " << convert_speed_to_mbps(current_attack.icmp.in_bytes) << " mbps\n"
<< "Outgoing icmp traffic: " << convert_speed_to_mbps(current_attack.icmp.out_bytes) << " mbps\n"
<< "Incoming icmp pps: " << current_attack.icmp.in_packets << " packets per second\n"
<< "Outgoing icmp pps: " << current_attack.icmp.out_packets << " packets per second\n";
return attack_description.str();
}
@ -1080,23 +1079,30 @@ attack_type_t detect_attack_type(const attack_details_t& current_attack) {
double threshold_value = 0.9;
if (current_attack.attack_direction == INCOMING) {
if (current_attack.tcp_syn.in_packets > threshold_value * current_attack.total.in_packets) {
if (current_attack.traffic_counters.tcp_syn.in_packets > threshold_value * current_attack.traffic_counters.total.in_packets) {
return ATTACK_SYN_FLOOD;
} else if (current_attack.icmp.in_packets > threshold_value * current_attack.total.in_packets) {
} else if (current_attack.traffic_counters.icmp.in_packets >
threshold_value * current_attack.traffic_counters.total.in_packets) {
return ATTACK_ICMP_FLOOD;
} else if (current_attack.fragmented.in_packets > threshold_value * current_attack.total.in_packets) {
} else if (current_attack.traffic_counters.fragmented.in_packets >
threshold_value * current_attack.traffic_counters.total.in_packets) {
return ATTACK_IP_FRAGMENTATION_FLOOD;
} else if (current_attack.udp.in_packets > threshold_value * current_attack.total.in_packets) {
} else if (current_attack.traffic_counters.udp.in_packets >
threshold_value * current_attack.traffic_counters.total.in_packets) {
return ATTACK_UDP_FLOOD;
}
} else if (current_attack.attack_direction == OUTGOING) {
if (current_attack.tcp_syn.out_packets > threshold_value * current_attack.total.out_packets) {
if (current_attack.traffic_counters.tcp_syn.out_packets >
threshold_value * current_attack.traffic_counters.total.out_packets) {
return ATTACK_SYN_FLOOD;
} else if (current_attack.icmp.out_packets > threshold_value * current_attack.total.out_packets) {
} else if (current_attack.traffic_counters.icmp.out_packets >
threshold_value * current_attack.traffic_counters.total.out_packets) {
return ATTACK_ICMP_FLOOD;
} else if (current_attack.fragmented.out_packets > threshold_value * current_attack.total.out_packets) {
} else if (current_attack.traffic_counters.fragmented.out_packets >
threshold_value * current_attack.traffic_counters.total.out_packets) {
return ATTACK_IP_FRAGMENTATION_FLOOD;
} else if (current_attack.udp.out_packets > threshold_value * current_attack.total.out_packets) {
} else if (current_attack.traffic_counters.udp.out_packets >
threshold_value * current_attack.traffic_counters.total.out_packets) {
return ATTACK_UDP_FLOOD;
}
}
@ -1104,6 +1110,7 @@ attack_type_t detect_attack_type(const attack_details_t& current_attack) {
return ATTACK_UNKNOWN;
}
std::string get_printable_attack_name(attack_type_t attack) {
if (attack == ATTACK_SYN_FLOOD) {
return "syn_flood";
@ -1137,30 +1144,6 @@ std::string serialize_network_load_to_text(subnet_counter_t& network_speed_meter
return buffer.str();
}
std::string serialize_statistic_counters_about_attack(const attack_details_t& current_attack) {
std::stringstream attack_description;
double average_packet_size_for_incoming_traffic = 0;
double average_packet_size_for_outgoing_traffic = 0;
if (current_attack.average_in_packets > 0) {
average_packet_size_for_incoming_traffic = (double)current_attack.average_in_bytes / (double)current_attack.average_in_packets;
}
if (current_attack.average_out_packets > 0) {
average_packet_size_for_outgoing_traffic = (double)current_attack.average_out_bytes / (double)current_attack.average_out_packets;
}
// We do not need very accurate size
attack_description.precision(1);
attack_description << "Average packet size for incoming traffic: " << std::fixed
<< average_packet_size_for_incoming_traffic << " bytes \n"
<< "Average packet size for outgoing traffic: " << std::fixed
<< average_packet_size_for_outgoing_traffic << " bytes \n";
return attack_description.str();
}
std::string dns_lookup(std::string domain_name) {
try {
boost::asio::io_service io_service;

View File

@ -93,7 +93,6 @@ std::string serialize_attack_description(const attack_details_t& current_attack)
attack_type_t detect_attack_type(const attack_details_t& current_attack);
std::string get_printable_attack_name(attack_type_t attack);
std::string serialize_network_load_to_text(subnet_counter_t& network_speed_meter, bool average);
std::string serialize_statistic_counters_about_attack(const attack_details_t& current_attack);
std::string dns_lookup(std::string domain_name);
bool store_data_to_stats_server(unsigned short int graphite_port, std::string graphite_host, std::string buffer_as_string);

View File

@ -853,13 +853,11 @@ std::string get_attack_description(uint32_t client_ip, const attack_details_t& c
attack_description << "IP: " << convert_ip_as_uint_to_string(client_ip) << "\n";
attack_description << serialize_attack_description(current_attack) << "\n";
attack_description << serialize_statistic_counters_about_attack(current_attack);
return attack_description.str();
}
// Serialises traffic counters to JSON
bool serialize_traffic_counters_to_json(const attack_details_t& traffic_counters, nlohmann::json& json_details) {
bool serialize_traffic_counters_to_json(const subnet_counter_t& traffic_counters, nlohmann::json& json_details) {
try {
json_details["total_incoming_traffic"] = traffic_counters.total.in_bytes;
json_details["total_incoming_traffic_bits"] = traffic_counters.total.in_bytes * 8;
@ -936,6 +934,7 @@ bool serialize_traffic_counters_to_json(const attack_details_t& traffic_counters
return true;
}
bool serialize_attack_description_to_json(const attack_details_t& current_attack, nlohmann::json& json_details) {
// We need to catch exceptions as code may raise them here
try {
@ -947,7 +946,7 @@ bool serialize_attack_description_to_json(const attack_details_t& current_attack
return false;
}
if (!serialize_traffic_counters_to_json(current_attack, json_details)) {
if (!serialize_traffic_counters_to_json(current_attack.traffic_counters, json_details)) {
logger << log4cpp::Priority::ERROR << "Cannot add traffic counters to JSON document";
return false;
}
@ -1329,47 +1328,8 @@ void execute_ip_ban(uint32_t client_ip, subnet_counter_t average_speed_element,
current_attack.attack_power = pps;
current_attack.max_attack_power = pps;
current_attack.total.in_packets = in_pps;
current_attack.total.out_packets = out_pps;
current_attack.total.in_bytes = in_bps;
current_attack.total.out_bytes = out_bps;
// pass flow information
current_attack.in_flows = in_flows;
current_attack.out_flows = out_flows;
current_attack.fragmented.in_packets = average_speed_element.fragmented.in_packets;
current_attack.tcp.in_packets = average_speed_element.tcp.in_packets;
current_attack.tcp_syn.in_packets = average_speed_element.tcp_syn.in_packets;
current_attack.udp.in_packets = average_speed_element.udp.in_packets;
current_attack.icmp.in_packets = average_speed_element.icmp.in_packets;
current_attack.fragmented.out_packets = average_speed_element.fragmented.out_packets;
current_attack.tcp.out_packets = average_speed_element.tcp.out_packets;
current_attack.tcp_syn.out_packets = average_speed_element.tcp_syn.out_packets;
current_attack.udp.out_packets = average_speed_element.udp.out_packets;
current_attack.icmp.out_packets = average_speed_element.icmp.out_packets;
current_attack.fragmented.out_bytes = average_speed_element.fragmented.out_bytes;
current_attack.tcp.out_bytes = average_speed_element.tcp.out_bytes;
current_attack.tcp_syn.out_bytes = average_speed_element.tcp_syn.out_bytes;
current_attack.udp.out_bytes = average_speed_element.udp.out_bytes;
current_attack.icmp.out_bytes = average_speed_element.icmp.out_bytes;
current_attack.fragmented.in_bytes = average_speed_element.fragmented.in_bytes;
current_attack.tcp.in_bytes = average_speed_element.tcp.in_bytes;
current_attack.tcp_syn.in_bytes = average_speed_element.tcp_syn.in_bytes;
current_attack.udp.in_bytes = average_speed_element.udp.in_bytes;
current_attack.icmp.in_bytes = average_speed_element.icmp.in_bytes;
current_attack.average_in_packets = average_speed_element.total.in_packets;
current_attack.average_in_bytes = average_speed_element.total.in_bytes;
current_attack.average_in_flows = average_speed_element.in_flows;
current_attack.average_out_packets = average_speed_element.total.out_packets;
current_attack.average_out_bytes = average_speed_element.total.out_bytes;
current_attack.average_out_flows = average_speed_element.out_flows;
// Copy traffic metrics
current_attack.traffic_counters = average_speed_element;
if (collect_attack_pcap_dumps) {
bool buffer_allocation_result = current_attack.pcap_attack_dump.allocate_buffer(number_of_packets_for_pcap_attack_dump);
@ -1807,7 +1767,7 @@ std::string get_human_readable_threshold_type(attack_detection_threshold_type_t
// This function fills attack information from different information sources
bool fill_attack_information(subnet_counter_t average_speed_element,
bool fill_attack_information(
attack_details_t& current_attack,
std::string& host_group_name,
std::string& parent_host_group_name,
@ -1815,12 +1775,12 @@ bool fill_attack_information(subnet_counter_t average_speed_element,
int ban_time) {
uint64_t pps = 0;
uint64_t in_pps = average_speed_element.total.in_packets;
uint64_t out_pps = average_speed_element.total.out_packets;
uint64_t in_bps = average_speed_element.total.in_bytes;
uint64_t out_bps = average_speed_element.total.out_bytes;
uint64_t in_flows = average_speed_element.in_flows;
uint64_t out_flows = average_speed_element.out_flows;
uint64_t in_pps = current_attack.traffic_counters.total.in_packets;
uint64_t out_pps = current_attack.traffic_counters.total.out_packets;
uint64_t in_bps = current_attack.traffic_counters.total.in_bytes;
uint64_t out_bps = current_attack.traffic_counters.total.out_bytes;
uint64_t in_flows = current_attack.traffic_counters.in_flows;
uint64_t out_flows = current_attack.traffic_counters.out_flows;
direction_t data_direction;
@ -1848,7 +1808,7 @@ bool fill_attack_information(subnet_counter_t average_speed_element,
}
}
current_attack.attack_protocol = detect_attack_protocol(average_speed_element, data_direction);
current_attack.attack_protocol = detect_attack_protocol(current_attack.traffic_counters, data_direction);
current_attack.host_group = host_group_name;
current_attack.parent_host_group = parent_host_group_name;
@ -1871,48 +1831,6 @@ bool fill_attack_information(subnet_counter_t average_speed_element,
current_attack.attack_power = pps;
current_attack.max_attack_power = pps;
current_attack.total.in_packets = in_pps;
current_attack.total.out_packets = out_pps;
current_attack.total.in_bytes = in_bps;
current_attack.total.out_bytes = out_bps;
// pass flow information
current_attack.in_flows = in_flows;
current_attack.out_flows = out_flows;
current_attack.fragmented.in_packets = average_speed_element.fragmented.in_packets;
current_attack.tcp.in_packets = average_speed_element.tcp.in_packets;
current_attack.tcp_syn.in_packets = average_speed_element.tcp_syn.in_packets;
current_attack.udp.in_packets = average_speed_element.udp.in_packets;
current_attack.icmp.in_packets = average_speed_element.icmp.in_packets;
current_attack.fragmented.out_packets = average_speed_element.fragmented.out_packets;
current_attack.tcp.out_packets = average_speed_element.tcp.out_packets;
current_attack.tcp_syn.out_packets = average_speed_element.tcp_syn.out_packets;
current_attack.udp.out_packets = average_speed_element.udp.out_packets;
current_attack.icmp.out_packets = average_speed_element.icmp.out_packets;
current_attack.fragmented.out_bytes = average_speed_element.fragmented.out_bytes;
current_attack.tcp.out_bytes = average_speed_element.tcp.out_bytes;
current_attack.tcp_syn.out_bytes = average_speed_element.tcp_syn.out_bytes;
current_attack.udp.out_bytes = average_speed_element.udp.out_bytes;
current_attack.icmp.out_bytes = average_speed_element.icmp.out_bytes;
current_attack.fragmented.in_bytes = average_speed_element.fragmented.in_bytes;
current_attack.tcp.in_bytes = average_speed_element.tcp.in_bytes;
current_attack.tcp_syn.in_bytes = average_speed_element.tcp_syn.in_bytes;
current_attack.udp.in_bytes = average_speed_element.udp.in_bytes;
current_attack.icmp.in_bytes = average_speed_element.icmp.in_bytes;
current_attack.average_in_packets = average_speed_element.total.in_packets;
current_attack.average_in_bytes = average_speed_element.total.in_bytes;
current_attack.average_in_flows = average_speed_element.in_flows;
current_attack.average_out_packets = average_speed_element.total.out_packets;
current_attack.average_out_bytes = average_speed_element.total.out_bytes;
current_attack.average_out_flows = average_speed_element.out_flows;
return true;
}
@ -1967,7 +1885,9 @@ void speed_calculation_callback_local_ipv6(const subnet_ipv6_cidr_mask_t& curren
std::string parent_group;
attack_details_t attack_details;
fill_attack_information(current_average_speed_element, attack_details, host_group_name, parent_group, unban_enabled, global_ban_time);
attack_details.traffic_counters = current_average_speed_element;
fill_attack_information(attack_details, host_group_name, parent_group, unban_enabled, global_ban_time);
attack_details.ipv6 = true;
// TODO: Also, we should find IPv6 network for attack here
@ -2087,7 +2007,7 @@ void speed_calculation_callback_local_ipv4(const uint32_t& client_ip, const subn
// field copy
std::string parent_group;
fill_attack_information(attack_details.traffic_counters, attack_details, host_group_name,
fill_attack_information(attack_details, host_group_name,
parent_group, unban_enabled,
global_ban_time);
@ -3245,8 +3165,6 @@ std::string get_attack_description_ipv6(subnet_ipv6_cidr_mask_t ipv6_address, co
attack_description << "IP: " << print_ipv6_address(ipv6_address.subnet_address) << "\n";
attack_description << serialize_attack_description(current_attack) << "\n";
attack_description << serialize_statistic_counters_about_attack(current_attack);
return attack_description.str();
}