Added all required pieces for IPv6 blocks (#887)

This commit is contained in:
Pavel Odintsov 2020-11-24 22:51:21 +00:00 committed by GitHub
parent 675293bda3
commit ff69f6f42a
Signed by: GitHub
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 433 additions and 26 deletions

121
src/ban_list.hpp Normal file
View File

@ -0,0 +1,121 @@
#pragma once
#include <boost/uuid/uuid.hpp>
#include <boost/uuid/uuid_generators.hpp>
#include <boost/uuid/uuid_io.hpp>
// This class stores blocked with blackhole hosts
template <typename TemplateKeyType> class blackhole_ban_list_t {
public:
blackhole_ban_list_t() {
}
// Is this host blackholed?
bool is_blackholed(TemplateKeyType client_id) {
std::lock_guard<std::mutex> lock_guard(structure_mutex);
return ban_list_storage.count(client_id) > 0;
}
// Do we have blackhole with certain uuid?
// If we have we will return IP address for this mitigation
bool is_blackholed_by_uuid(boost::uuids::uuid mitigation_uuid, TemplateKeyType& client_id) {
std::lock_guard<std::mutex> lock_guard(structure_mutex);
auto itr = std::find_if(ban_list_storage.begin(), ban_list_storage.end(),
[mitigation_uuid](const std::pair<const TemplateKeyType, attack_details_t>& pair) {
return pair.second.attack_uuid == mitigation_uuid;
});
if (itr == ban_list_storage.end()) {
return false;
}
client_id = itr->first;
return true;
}
// Add host to blackhole
bool add_to_blackhole(TemplateKeyType client_id, attack_details_t current_attack) {
std::lock_guard<std::mutex> lock_guard(structure_mutex);
ban_list_storage[client_id] = current_attack;
return true;
}
bool remove_from_blackhole(TemplateKeyType client_id) {
std::lock_guard<std::mutex> lock_guard(structure_mutex);
ban_list_storage.erase(client_id);
return true;
}
bool remove_from_blackhole_and_keep_copy(TemplateKeyType client_id, attack_details_t& current_attack) {
std::lock_guard<std::mutex> lock_guard(structure_mutex);
// Confirm that we still have this element in storage
if (ban_list_storage.count(client_id) == 0) {
return false;
}
// Copy current value
current_attack = ban_list_storage[client_id];
// Remove it
ban_list_storage.erase(client_id);
return true;
}
// Add blackholed hosts from external storage to internal
bool set_whole_banlist(std::map<TemplateKeyType, banlist_item_t>& ban_list_param) {
std::lock_guard<std::mutex> lock_guard(structure_mutex);
// Copy whole content of passed list to current list
ban_list_storage.insert(ban_list_param.begin(), ban_list_param.end());
return true;
}
// Get list of all blackholed hosts
bool get_blackholed_hosts(std::vector<TemplateKeyType>& blackholed_hosts) {
std::lock_guard<std::mutex> lock_guard(structure_mutex);
for (auto& elem : ban_list_storage) {
blackholed_hosts.push_back(elem.first);
}
return true;
}
bool get_whole_banlist(std::map<TemplateKeyType, banlist_item_t>& ban_list_copy) {
std::lock_guard<std::mutex> lock_guard(structure_mutex);
// Copy whole content of this structure
ban_list_copy.insert(ban_list_storage.begin(), ban_list_storage.end());
return true;
}
bool get_blackhole_details(TemplateKeyType client_id, banlist_item_t& banlist_item) {
std::lock_guard<std::mutex> lock_guard(structure_mutex);
auto itr = ban_list_storage.find(client_id);
if (itr == ban_list_storage.end()) {
return false;
}
banlist_item = itr->second;
return true;
}
private:
std::map<TemplateKeyType, banlist_item_t> ban_list_storage;
std::mutex structure_mutex;
};

View File

@ -1428,4 +1428,3 @@ std::string convert_any_ip_to_string(subnet_ipv6_cidr_mask_t subnet) {
return print_ipv6_cidr_subnet(subnet);
}

View File

@ -112,6 +112,8 @@
#include "packet_bucket.h"
#include "ban_list.hpp"
#ifdef FASTNETMON_API
using fastmitigation::BanListReply;
using fastmitigation::BanListRequest;
@ -134,6 +136,9 @@ std::string cli_stats_ipv6_file_path = "/tmp/fastnetmon_ipv6.dat";
unsigned int stats_thread_sleep_time = 3600;
unsigned int stats_thread_initial_call_delay = 30;
// Each this seconds we will check about available data in bucket
unsigned int check_for_availible_for_processing_packets_buckets = 1;
// Current time with pretty low precision, we use separate thread to update it
time_t current_inaccurate_time = 0;
@ -142,6 +147,10 @@ packet_buckets_storage_t<subnet_ipv6_cidr_mask_t> packet_buckets_ipv6_storage;
unsigned int recalculate_speed_timeout = 1;
// We will remove all packet buckets which runs longer than this time. This value used only for one shot buckets.
// Infinite bucket's will not removed
unsigned int maximum_time_since_bucket_start_to_remove = 120;
FastnetmonPlatformConfigurtion fastnetmon_platform_configuration;
// Send or not any details about attack for ban script call over stdin
@ -397,6 +406,9 @@ map_of_vector_counters_t SubnetVectorMapSpeedAverage;
map_for_counters GeoIpCounter;
#endif
// IPv6 hosts
blackhole_ban_list_t<subnet_ipv6_cidr_mask_t> ban_list_ipv6_ng;
// In ddos info we store attack power and direction
std::map<uint32_t, banlist_item_t> ban_list;
std::map<uint32_t, std::vector<simple_packet_t> > ban_list_details;
@ -492,10 +504,14 @@ class FastnetmonApiServiceImpl final : public Fastnetmon::Service {
ban_list_details[client_ip] = std::vector<simple_packet_t>();
ban_list_details_mutex.unlock();
subnet_ipv6_cidr_mask_t zero_ipv6_address;
boost::circular_buffer<simple_packet_t> empty_simple_packets_buffer;
logger << log4cpp::Priority::INFO << "API call ban handlers manually";
std::string flow_attack_details = "manually triggered attack";
call_ban_handlers(client_ip, current_attack, flow_attack_details);
call_ban_handlers(client_ip, zero_ipv6_address, false, current_attack, flow_attack_details, attack_detection_source_t::Automatic, "", empty_simple_packets_buffer);
return Status::OK;
}
@ -1715,6 +1731,12 @@ int main(int argc, char** argv) {
service_thread_group.add_thread(new boost::thread(cleanup_ban_list));
}
// This thread will check about filled buckets with packets and process they
auto check_traffic_buckets_thread = new boost::thread(check_traffic_buckets);
set_boost_process_name(check_traffic_buckets_thread, "check_buckets");
service_thread_group.add_thread(check_traffic_buckets_thread);
#ifdef PF_RING
if (enable_data_collection_from_mirror) {
packet_capture_plugin_thread_group.add_thread(new boost::thread(start_pfring_collection, process_packet));

View File

@ -46,6 +46,8 @@
#include "packet_bucket.h"
#include "ban_list.hpp"
extern packet_buckets_storage_t<subnet_ipv6_cidr_mask_t> packet_buckets_ipv6_storage;
extern bool print_average_traffic_counts;
extern std::string cli_stats_file_path;
@ -56,6 +58,7 @@ extern map_of_vector_counters_for_flow_t SubnetVectorMapFlow;
extern bool DEBUG_DUMP_ALL_PACKETS;
extern bool DEBUG_DUMP_OTHER_PACKETS;
extern uint64_t total_ipv4_packets;
extern blackhole_ban_list_t<subnet_ipv6_cidr_mask_t> ban_list_ipv6_ng;
extern uint64_t total_ipv6_packets;
extern map_of_vector_counters_t SubnetVectorMapSpeed;
extern double average_calculation_amount;
@ -65,11 +68,13 @@ extern uint64_t our_ipv6_packets;
extern map_of_vector_counters_t SubnetVectorMap;
extern uint64_t non_ip_packets;
extern uint64_t total_simple_packets_processed;
extern unsigned int maximum_time_since_bucket_start_to_remove;
extern unsigned int max_ips_in_list;
extern struct timeval speed_calculation_time;
extern struct timeval drawing_thread_execution_time;
extern time_t last_call_of_traffic_recalculation;
extern std::string cli_stats_ipv6_file_path;
extern unsigned int check_for_availible_for_processing_packets_buckets;
extern abstract_subnet_counters_t<subnet_ipv6_cidr_mask_t> ipv6_host_counters;
extern abstract_subnet_counters_t<subnet_ipv6_cidr_mask_t> ipv6_subnet_counters;
extern bool process_incoming_traffic;
@ -717,28 +722,38 @@ bool exceed_mbps_speed(uint64_t in_counter, uint64_t out_counter, unsigned int t
}
}
// Return true when we should ban this IP
bool we_should_ban_this_ip(map_element_t* average_speed_element, ban_settings_t current_ban_settings) {
// we detect overspeed by packets
// Return true when we should ban this entity
bool we_should_ban_this_entity(map_element_t* average_speed_element,
ban_settings_t& current_ban_settings,
attack_detection_threshold_type_t& attack_detection_source,
attack_detection_direction_type_t& attack_detection_direction) {
attack_detection_source = attack_detection_threshold_type_t::unknown;
attack_detection_direction = attack_detection_direction_type_t::unknown;
// we detect overspeed by packets
if (current_ban_settings.enable_ban_for_pps &&
exceed_pps_speed(average_speed_element->in_packets, average_speed_element->out_packets,
current_ban_settings.ban_threshold_pps)) {
logger << log4cpp::Priority::DEBUG << "We detected this attack by pps limit";
attack_detection_source = attack_detection_threshold_type_t::packets_per_second;
return true;
}
if (current_ban_settings.enable_ban_for_bandwidth &&
exceed_mbps_speed(average_speed_element->in_bytes, average_speed_element->out_bytes,
current_ban_settings.ban_threshold_mbps)) {
logger << log4cpp::Priority::DEBUG << "We detected this attack by mbps limit";
attack_detection_source = attack_detection_threshold_type_t::bytes_per_second;
return true;
}
if (current_ban_settings.enable_ban_for_flows_per_second &&
exceed_flow_speed(average_speed_element->in_flows, average_speed_element->out_flows,
current_ban_settings.ban_threshold_flows)) {
logger << log4cpp::Priority::DEBUG << "We detected this attack by flow limit";
attack_detection_source = attack_detection_threshold_type_t::flows_per_second;
return true;
}
@ -748,21 +763,23 @@ bool we_should_ban_this_ip(map_element_t* average_speed_element, ban_settings_t
if (current_ban_settings.enable_ban_for_tcp_pps &&
exceed_pps_speed(average_speed_element->tcp_in_packets, average_speed_element->tcp_out_packets,
current_ban_settings.ban_threshold_tcp_pps)) {
logger << log4cpp::Priority::DEBUG << "We detected this attack by tcp pps limit";
attack_detection_source = attack_detection_threshold_type_t::tcp_packets_per_second;
return true;
}
if (current_ban_settings.enable_ban_for_udp_pps &&
exceed_pps_speed(average_speed_element->udp_in_packets, average_speed_element->udp_out_packets,
current_ban_settings.ban_threshold_udp_pps)) {
logger << log4cpp::Priority::DEBUG << "We detected this attack by udp pps limit";
attack_detection_source = attack_detection_threshold_type_t::udp_packets_per_second;
return true;
}
if (current_ban_settings.enable_ban_for_icmp_pps &&
exceed_pps_speed(average_speed_element->icmp_in_packets, average_speed_element->icmp_out_packets,
current_ban_settings.ban_threshold_icmp_pps)) {
logger << log4cpp::Priority::DEBUG << "We detected this attack by icmp pps limit";
attack_detection_source = attack_detection_threshold_type_t::icmp_packets_per_second;
return true;
}
@ -770,21 +787,21 @@ bool we_should_ban_this_ip(map_element_t* average_speed_element, ban_settings_t
if (current_ban_settings.enable_ban_for_tcp_bandwidth &&
exceed_mbps_speed(average_speed_element->tcp_in_bytes, average_speed_element->tcp_out_bytes,
current_ban_settings.ban_threshold_tcp_mbps)) {
logger << log4cpp::Priority::DEBUG << "We detected this attack by tcp mbps limit";
attack_detection_source = attack_detection_threshold_type_t::tcp_bytes_per_second;;
return true;
}
if (current_ban_settings.enable_ban_for_udp_bandwidth &&
exceed_mbps_speed(average_speed_element->udp_in_bytes, average_speed_element->udp_out_bytes,
current_ban_settings.ban_threshold_udp_mbps)) {
logger << log4cpp::Priority::DEBUG << "We detected this attack by udp mbps limit";
attack_detection_source = attack_detection_threshold_type_t::udp_bytes_per_second;
return true;
}
if (current_ban_settings.enable_ban_for_icmp_bandwidth &&
exceed_mbps_speed(average_speed_element->icmp_in_bytes, average_speed_element->icmp_out_bytes,
current_ban_settings.ban_threshold_icmp_mbps)) {
logger << log4cpp::Priority::DEBUG << "We detected this attack by icmp mbps limit";
attack_detection_source = attack_detection_threshold_type_t::icmp_bytes_per_second;
return true;
}
@ -957,7 +974,10 @@ void cleanup_ban_list() {
ban_settings_t current_ban_settings =
get_ban_settings_for_this_subnet(itr->second.customer_network, host_group_name);
if (we_should_ban_this_ip(average_speed_element, current_ban_settings)) {
attack_detection_threshold_type_t attack_detection_source;
attack_detection_direction_type_t attack_detection_direction;
if (we_should_ban_this_entity(average_speed_element, current_ban_settings, attack_detection_source, attack_detection_direction)) {
logger << log4cpp::Priority::ERROR << "Attack to IP " << client_ip_as_string
<< " still going! We should not unblock this host";
@ -1859,11 +1879,32 @@ void execute_ip_ban(uint32_t client_ip, map_element_t average_speed_element, std
logger << log4cpp::Priority::INFO << "Attack with direction: " << data_direction_as_string
<< " IP: " << client_ip_as_string << " Power: " << pps_as_string;
call_ban_handlers(client_ip, ban_list[client_ip], flow_attack_details);
subnet_ipv6_cidr_mask_t zero_ipv6_address;
boost::circular_buffer<simple_packet_t> empty_simple_packets_buffer;
call_ban_handlers(client_ip, zero_ipv6_address, false, ban_list[client_ip], flow_attack_details, attack_detection_source_t::Automatic, "", empty_simple_packets_buffer);
}
void call_ban_handlers(uint32_t client_ip, attack_details_t& current_attack, std::string flow_attack_details) {
std::string client_ip_as_string = convert_ip_as_uint_to_string(client_ip);
void call_ban_handlers(uint32_t client_ip,
subnet_ipv6_cidr_mask_t client_ipv6,
bool ipv6,
attack_details_t& current_attack,
std::string flow_attack_details,
attack_detection_source_t attack_detection_source,
std::string simple_packets_dump,
boost::circular_buffer<simple_packet_t>& simple_packets_buffer) {
bool ipv4 = !ipv6;
std::string client_ip_as_string = "";
if (ipv4) {
client_ip_as_string = convert_ip_as_uint_to_string(client_ip);
} else {
client_ip_as_string = print_ipv6_address(client_ipv6.subnet_address);
}
std::string pps_as_string = convert_int_to_string(current_attack.attack_power);
std::string data_direction_as_string = get_direction_name(current_attack.attack_direction);
@ -1875,7 +1916,7 @@ void call_ban_handlers(uint32_t client_ip, attack_details_t& current_attack, std
std::string full_attack_description = basic_attack_information + flow_attack_details;
if (store_attack_details_to_file) {
if (store_attack_details_to_file && ipv4) {
print_attack_details_to_file(full_attack_description, client_ip_as_string, current_attack);
}
@ -1900,7 +1941,7 @@ void call_ban_handlers(uint32_t client_ip, attack_details_t& current_attack, std
logger << log4cpp::Priority::INFO << "Script for ban client is finished: " << client_ip_as_string;
}
if (exabgp_enabled) {
if (exabgp_enabled && ipv4) {
logger << log4cpp::Priority::INFO << "Call ExaBGP for ban client started: " << client_ip_as_string;
boost::thread exabgp_thread(exabgp_ban_manage, "ban", client_ip_as_string, current_attack);
@ -1910,7 +1951,7 @@ void call_ban_handlers(uint32_t client_ip, attack_details_t& current_attack, std
}
#ifdef ENABLE_GOBGP
if (gobgp_enabled) {
if (gobgp_enabled && ipv4) {
logger << log4cpp::Priority::INFO << "Call GoBGP for ban client started: " << client_ip_as_string;
boost::thread gobgp_thread(gobgp_ban_manage, "ban", client_ip_as_string, current_attack);
@ -1921,7 +1962,7 @@ void call_ban_handlers(uint32_t client_ip, attack_details_t& current_attack, std
#endif
#ifdef REDIS
if (redis_enabled) {
if (redis_enabled && ipv4) {
std::string redis_key_name = client_ip_as_string + "_information";
if (!redis_prefix.empty()) {
@ -1950,7 +1991,7 @@ void call_ban_handlers(uint32_t client_ip, attack_details_t& current_attack, std
#endif
#ifdef MONGO
if (mongodb_enabled) {
if (mongodb_enabled && ipv4) {
std::string mongo_key_name = client_ip_as_string + "_information_" +
print_time_t_in_fastnetmon_format(current_attack.ban_timestamp);
@ -2445,7 +2486,11 @@ void recalculate_speed() {
std::string host_group_name;
ban_settings_t current_ban_settings = get_ban_settings_for_this_subnet(itr->first, host_group_name);
if (we_should_ban_this_ip(current_average_speed_element, current_ban_settings)) {
attack_detection_threshold_type_t attack_detection_source;
attack_detection_direction_type_t attack_detection_direction;
if (we_should_ban_this_entity(current_average_speed_element, current_ban_settings, attack_detection_source, attack_detection_direction)) {
logger << log4cpp::Priority::DEBUG
<< "We have found host group for this host as: " << host_group_name;
@ -3339,3 +3384,173 @@ std::string print_channel_speed_ipv6(std::string traffic_type, direction_t packe
return stream.str();
}
template <typename TemplateKeyType>
void remove_orphaned_buckets(packet_buckets_storage_t<TemplateKeyType>* packet_storage, std::string protocol) {
std::lock_guard<std::mutex> lock_guard(packet_storage->packet_buckets_map_mutex);
// List of buckets to remove
std::vector<TemplateKeyType> buckets_to_remove;
// logger << log4cpp::Priority::DEBUG << "We've got " << packet_storage->packet_buckets_map.size() << " packets buckets for processing";
// Find buckets for removal
// We should not remove them here because it's tricky to do properly in C++
for (auto it = packet_storage->packet_buckets_map.begin(); it != packet_storage->packet_buckets_map.end(); ++it) {
if (should_remove_orphaned_bucket<TemplateKeyType>(*it)) {
logger << log4cpp::Priority::DEBUG << "We decided to remove " << protocol << " bucket "
<< convert_any_ip_to_string(it->first);
buckets_to_remove.push_back(it->first);
}
}
// logger << log4cpp::Priority::DEBUG << "We have " << buckets_to_remove.size() << " " << protocol << " orphaned buckets for cleanup";
for (auto client_ip : buckets_to_remove) {
// Let's dump some data from it
packet_bucket_t* bucket = &packet_storage->packet_buckets_map[client_ip];
logger << log4cpp::Priority::WARN << "We've found orphaned bucket for IP: " << convert_any_ip_to_string(client_ip)
<< " it has " << bucket->parsed_packets_circular_buffer.size() << " parsed packets"
<< " and " << bucket->raw_packets_circular_buffer.size() << " raw packets"
<< " we will remove it";
// Stop packet collection ASAP
bucket->we_could_receive_new_data = false;
// Remove it completely from map
packet_storage->packet_buckets_map.erase(client_ip);
}
return;
}
std::string get_attack_description_ipv6(subnet_ipv6_cidr_mask_t ipv6_address, attack_details_t& current_attack) {
std::stringstream attack_description;
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();
}
void execute_ipv6_ban(subnet_ipv6_cidr_mask_t ipv6_client,
attack_details_t current_attack,
std::string simple_packets_dump,
boost::circular_buffer<simple_packet_t>& simple_packets_buffer) {
// Execute ban actions
ban_list_ipv6_ng.add_to_blackhole(ipv6_client, current_attack);
logger << log4cpp::Priority::INFO << "IPv6 address " << print_ipv6_cidr_subnet(ipv6_client) << " was banned";
uint32_t zero_ipv4_address = 0;
call_ban_handlers(zero_ipv4_address, ipv6_client, true, current_attack, "", attack_detection_source_t::Automatic,
simple_packets_dump, simple_packets_buffer);
}
void process_filled_buckets_ipv6() {
std::lock_guard<std::mutex> lock_guard(packet_buckets_ipv6_storage.packet_buckets_map_mutex);
std::vector<subnet_ipv6_cidr_mask_t> filled_buckets;
for (auto itr = packet_buckets_ipv6_storage.packet_buckets_map.begin();
itr != packet_buckets_ipv6_storage.packet_buckets_map.end(); ++itr) {
// Find one time capture requests which filled completely
if (itr->second.collection_pattern == collection_pattern_t::ONCE &&
itr->second.we_collected_full_buffer_least_once && !itr->second.is_already_processed) {
logger << log4cpp::Priority::DEBUG << "We have filled buckets for " << convert_any_ip_to_string(itr->first);
filled_buckets.push_back(itr->first);
}
}
// logger << log4cpp::Priority::DEBUG << "We have " << filled_buckets.size() << " filled buckets";
for (auto ipv6_address : filled_buckets) {
logger << log4cpp::Priority::INFO << "We've got new completely filled bucket with packets for IPv6 "
<< print_ipv6_cidr_subnet(ipv6_address);
packet_bucket_t* bucket = &packet_buckets_ipv6_storage.packet_buckets_map[ipv6_address];
// Here I extract attack details saved at time when we crossed threshold
attack_details_t current_attack = bucket->attack_details;
std::string basic_attack_information = get_attack_description_ipv6(ipv6_address, current_attack);
// For all attack types at this moment we could prepare simple packet dump
std::string simple_packet_dump;
if (bucket->parsed_packets_circular_buffer.size() != 0) {
std::stringstream ss;
for (simple_packet_t& packet : bucket->parsed_packets_circular_buffer) {
ss << print_simple_packet(packet);
}
simple_packet_dump = ss.str();
}
// For IPv6 we support only blackhole at this moment. BGP Flow spec for IPv6 isn't so populare and we will skip implementation for some future
execute_ipv6_ban(ipv6_address, current_attack, simple_packet_dump, bucket->parsed_packets_circular_buffer);
// Mark it as processed. This will hide it from second call of same function
bucket->is_already_processed = true;
// Stop packet collection ASAP
bucket->we_could_receive_new_data = false;
// Remove it completely from map
packet_buckets_ipv6_storage.packet_buckets_map.erase(ipv6_address);
}
}
// This functions will check for packet buckets availible for processing
void check_traffic_buckets() {
while (true) {
// Process buckets which haven't filled by packets
remove_orphaned_buckets(&packet_buckets_ipv6_storage, "ipv6");
process_filled_buckets_ipv6();
boost::this_thread::sleep(boost::posix_time::seconds(check_for_availible_for_processing_packets_buckets));
}
}
// We use this function as callback for find_if to clean up orphaned buckets
template <typename TemplatedKeyType>
bool should_remove_orphaned_bucket(const std::pair<TemplatedKeyType, packet_bucket_t>& pair) {
logger << log4cpp::Priority::DEBUG << "Process bucket for " << convert_any_ip_to_string(pair.first);
// We process only "once" buckets
if (pair.second.collection_pattern != collection_pattern_t::ONCE) {
logger << log4cpp::Priority::DEBUG << "We do not cleanup buckets with non-once collection pattern "
<< convert_any_ip_to_string(pair.first);
return false;
}
std::chrono::duration<double> elapsed_from_start_seconds = std::chrono::system_clock::now() - pair.second.collection_start_time;
// We do cleanup for them in another function
if (pair.second.we_collected_full_buffer_least_once) {
logger << log4cpp::Priority::DEBUG << "We do not cleanup finished bucket for "
<< convert_any_ip_to_string(pair.first) << " it's " << elapsed_from_start_seconds.count() << " seconds old";
return false;
}
logger << log4cpp::Priority::DEBUG << "Bucket is " << elapsed_from_start_seconds.count() << " seconds old for "
<< convert_any_ip_to_string(pair.first) << " and has " << pair.second.parsed_packets_circular_buffer.size()
<< " parsed packets and " << pair.second.raw_packets_circular_buffer.size() << " raw packets";
if (elapsed_from_start_seconds.count() > maximum_time_since_bucket_start_to_remove) {
logger << log4cpp::Priority::DEBUG << "We're going to remove bucket for "
<< convert_any_ip_to_string(pair.first) << " because it's too old";
return true;
}
return false;
}

View File

@ -9,6 +9,9 @@
#include <hiredis/hiredis.h>
#endif
#include "all_logcpp_libraries.h"
#include "packet_bucket.h"
typedef std::map<std::string, uint32_t> active_flow_spec_announces_t;
void build_speed_counters_from_packet_counters(map_element_t& new_speed_element,
@ -24,7 +27,10 @@ std::string get_amplification_attack_type(amplification_attack_type_t attack_typ
std::string generate_flow_spec_for_amplification_attack(amplification_attack_type_t amplification_attack_type,
std::string destination_ip);
bool we_should_ban_this_ip(map_element_t* average_speed_element, ban_settings_t current_ban_settings);
bool we_should_ban_this_entity(map_element_t* average_speed_element,
ban_settings_t& current_ban_settings,
attack_detection_threshold_type_t& attack_detection_source,
attack_detection_direction_type_t& attack_detection_direction);
bool exceed_mbps_speed(uint64_t in_counter, uint64_t out_counter, unsigned int threshold_mbps);
bool exceed_flow_speed(uint64_t in_counter, uint64_t out_counter, unsigned int threshold);
@ -88,7 +94,15 @@ redisContext* redis_init_connection();
#endif
void execute_ip_ban(uint32_t client_ip, map_element_t average_speed_element, std::string flow_attack_details, subnet_cidr_mask_t customer_subnet);
void call_ban_handlers(uint32_t client_ip, attack_details_t& current_attack, std::string flow_attack_details);
void call_ban_handlers(uint32_t client_ip,
subnet_ipv6_cidr_mask_t client_ipv6,
bool ipv6,
attack_details_t& current_attack,
std::string flow_attack_details,
attack_detection_source_t attack_detection_source,
std::string simple_packets_dump,
boost::circular_buffer<simple_packet_t>& simple_packets_buffer);
#ifdef MONGO
void store_data_in_mongo(std::string key_name, std::string attack_details_json);
@ -141,3 +155,7 @@ void increment_incoming_flow_counters(map_of_vector_counters_for_flow_t& SubnetV
const subnet_cidr_mask_t& current_subnet);
void traffic_draw_ipv6_program();
void check_traffic_buckets();
void process_filled_buckets_ipv6();
template <typename TemplatedKeyType>
bool should_remove_orphaned_bucket(const std::pair<TemplatedKeyType, packet_bucket_t>& pair);

View File

@ -26,6 +26,38 @@ typedef std::map<std::string, uint64_t> graphite_data_t;
// Enum with available sort by field
enum sort_type_t { PACKETS, BYTES, FLOWS };
// Source of attack detection
enum class attack_detection_source_t : uint32_t { Automatic = 1, Manual = 2, Other = 255 };
// Which direction of traffic triggered attack
enum class attack_detection_direction_type_t {
unknown,
incoming,
outgoing,
};
// How we have detected this attack?
enum class attack_detection_threshold_type_t {
unknown,
packets_per_second,
bytes_per_second,
flows_per_second,
tcp_packets_per_second,
udp_packets_per_second,
icmp_packets_per_second,
tcp_bytes_per_second,
udp_bytes_per_second,
icmp_bytes_per_second,
tcp_syn_packets_per_second,
tcp_syn_bytes_per_second,
};
/* Class for custom comparison fields by different fields */
template <typename T> class TrafficComparatorClass {
private: