Added logic to exclude some traffic from processing using JSON encoded BGP Flow Spec rules in format https://fastnetmon.com/docs-fnm-advanced/fastnetmon-bgp-flow-spec-rfc-5575-json-representation/ in file /etc/whitelist_rules one rule per line

This commit is contained in:
Pavel Odintsov 2024-06-05 02:21:00 +03:00
parent 3d73a457d7
commit 3bc7cf62e0
4 changed files with 72 additions and 2 deletions

View File

@ -956,7 +956,7 @@ target_link_libraries(fastnetmon fastnetmon_pcap_format)
target_link_libraries(fastnetmon ipfix_rfc)
target_link_libraries(fastnetmon_logic bgp_protocol bgp_protocol_flow_spec exabgp_action)
target_link_libraries(fastnetmon_logic filter bgp_protocol bgp_protocol_flow_spec exabgp_action)
target_link_libraries(fastnetmon_logic protobuf_traffic_format)

View File

@ -24,4 +24,7 @@ class FastnetmonPlatformConfigurtion {
// Path to temporarily store backtrace when fatal failure happened
std::string backtrace_path = "${FASTNETMON_BACKTRACE_PATH}";
// Path to whitelist rules
std::string whitelist_rules_path = "${FASTNETMON_WHITELIST_RULES_PATH}";
};

View File

@ -64,6 +64,8 @@
#include "actions/gobgp_action.hpp"
#endif
#include "bgp_protocol_flow_spec.hpp"
// Yes, maybe it's not an good idea but with this we can guarantee working code in example plugin
#include "example_plugin/example_collector.hpp"
@ -243,6 +245,9 @@ bool exabgp_announce_host = false;
ban_settings_t global_ban_settings;
// We use these flow spec rules as custom whitelist
std::vector<flow_spec_rule_t> static_flowspec_based_whitelist;
void init_global_ban_settings() {
// ban Configuration params
global_ban_settings.enable_ban_for_pps = false;
@ -370,6 +375,8 @@ uint64_t our_ipv6_packets = 0;
uint64_t incoming_total_flows_speed = 0;
uint64_t outgoing_total_flows_speed = 0;
uint64_t total_flowspec_whitelist_packets = 0;
// Network counters for IPv6
abstract_subnet_counters_t<subnet_ipv6_cidr_mask_t, subnet_counter_t> ipv6_subnet_counters;
@ -1124,6 +1131,46 @@ void subnet_vectors_allocator(prefix_t* prefix, void* data) {
logger << log4cpp::Priority::INFO << "Successfully allocated " << ipv4_host_counters.average_speed_map.size() << " counters";
}
// Load flow spec based whitelist
bool load_whitelist_rules() {
if (!file_exists(fastnetmon_platform_configuration.whitelist_rules_path)) {
return true;
}
auto whitelist_rules_json = read_file_to_vector(fastnetmon_platform_configuration.whitelist_rules_path);
logger << log4cpp::Priority::INFO << "Read " << whitelist_rules_json.size() << " whitelist rules from configuration";
for (auto json_encoded_flow_spec : whitelist_rules_json) {
flow_spec_rule_t flow_spec_rule;
bool need_action_section = false;
bool parse_result =
read_flow_spec_from_json_to_native_format(json_encoded_flow_spec, flow_spec_rule, need_action_section);
if (!parse_result) {
logger << log4cpp::Priority::ERROR << "Cannot parse flowspec whitelist rule: " << json_encoded_flow_spec;
continue;
}
// Print rule to verify that parser worked correctly
std::string flow_spec_rule_as_json_to_print;
if (encode_flow_spec_to_json(flow_spec_rule, flow_spec_rule_as_json_to_print, false)) {
logger << log4cpp::Priority::DEBUG << "Loaded rule " << flow_spec_rule_as_json_to_print;
} else {
logger << log4cpp::Priority::ERROR << "Cannot encode flow spec rule for printing";
}
static_flowspec_based_whitelist.push_back(flow_spec_rule);
}
logger << log4cpp::Priority::INFO << "Loaded " << static_flowspec_based_whitelist.size() << " whitelist rules";
return true;
}
bool load_our_networks_list() {
if (file_exists(fastnetmon_platform_configuration.white_list_path)) {
std::vector<std::string> network_list_from_config =
@ -1790,6 +1837,8 @@ int main(int argc, char** argv) {
load_our_networks_list();
load_whitelist_rules();
// We should specify size of circular buffers here
packet_buckets_ipv4_storage.set_buffers_capacity(ban_details_records_count);

View File

@ -18,6 +18,10 @@
#include "fast_library.hpp"
#include "fast_platform.hpp"
#include "bgp_protocol_flow_spec.hpp"
#include "filter.hpp"
#include "fast_endianless.hpp"
// Plugins
@ -2388,8 +2392,9 @@ void collect_traffic_to_buckets_ipv4(const simple_packet_t& current_packet, pack
void process_packet(simple_packet_t& current_packet) {
extern abstract_subnet_counters_t<uint32_t, subnet_counter_t> ipv4_host_counters;
extern packet_buckets_storage_t<uint32_t> packet_buckets_ipv4_storage;
extern std::vector<flow_spec_rule_t> static_flowspec_based_whitelist;
extern map_of_vector_counters_for_flow_t SubnetVectorMapFlow;
extern uint64_t total_flowspec_whitelist_packets;
#ifdef KAFKA
extern bool kafka_traffic_export;
@ -2451,6 +2456,19 @@ void process_packet(simple_packet_t& current_packet) {
}
#endif
// Check against static flow spec based whitelist
if ((current_packet.packet_direction == INCOMING or current_packet.packet_direction == OUTGOING) &&
static_flowspec_based_whitelist.size() > 0) {
// We do not use mutex here because we load this list only on startup
bool should_we_whitelist_this_packet = filter_packet_by_flowspec_rule_list(current_packet, static_flowspec_based_whitelist);
if (should_we_whitelist_this_packet) {
total_flowspec_whitelist_packets++;
return;
}
}
// It's useful in case when we can't find what packets do not processed correctly
if (DEBUG_DUMP_OTHER_PACKETS && current_packet.packet_direction == OTHER) {
logger << log4cpp::Priority::INFO << "Dump other: " << print_simple_packet(current_packet);