@@ -1210,6 +1210,8 @@ void call_blackhole_actions_per_host(attack_action_t attack_action,
12101210 const boost::circular_buffer<simple_packet_t >& simple_packets_buffer,
12111211 const boost::circular_buffer<fixed_size_packet_storage_t >& raw_packets_buffer) {
12121212
1213+ extern bool usage_stats;
1214+
12131215 bool ipv4 = !ipv6;
12141216 std::string client_ip_as_string = " " ;
12151217
@@ -1350,6 +1352,11 @@ void call_blackhole_actions_per_host(attack_action_t attack_action,
13501352 }
13511353#endif
13521354 }
1355+
1356+ if (usage_stats) {
1357+ boost::thread attack_report_thread (send_attack_data_to_reporting_server, basic_attack_information_in_json);
1358+ attack_report_thread.detach ();
1359+ }
13531360}
13541361
13551362
@@ -1506,7 +1513,7 @@ void traffic_draw_ipv4_program() {
15061513 }
15071514
15081515 output_buffer << " FastNetMon " << fastnetmon_platform_configuration.fastnetmon_version
1509- << " Author: http ://pavel-odintsov.com"
1516+ << " Author: https ://pavel-odintsov.com"
15101517 << " \n "
15111518 << " IPs ordered by: " << sort_parameter << " \n " ;
15121519
@@ -3023,6 +3030,182 @@ bool get_instance_id(std::string& instance_id) {
30233030 return true ;
30243031}
30253032
3033+ void send_usage_data_to_reporting_server () {
3034+ extern std::string reporting_server;
3035+ extern total_speed_counters_t total_counters_ipv4;
3036+ extern total_speed_counters_t total_counters_ipv6;
3037+
3038+ // Build query
3039+ std::stringstream request_stream;
3040+
3041+ request_stream << " https://" << reporting_server << " /stats_v1" ;
3042+
3043+
3044+ std::string stats_json_string;
3045+
3046+ try {
3047+ nlohmann::json stats;
3048+
3049+ uint64_t incoming_ipv4 = total_counters_ipv4.total_speed_average_counters [INCOMING].total .bytes ;
3050+ uint64_t outgoing_ipv4 = total_counters_ipv4.total_speed_average_counters [OUTGOING].total .bytes ;
3051+
3052+ uint64_t incoming_ipv6 = total_counters_ipv6.total_speed_average_counters [INCOMING].total .bytes ;
3053+ uint64_t outgoing_ipv6 = total_counters_ipv6.total_speed_average_counters [OUTGOING].total .bytes ;
3054+
3055+ stats[" incoming_traffic_speed" ] = incoming_ipv4 + incoming_ipv6;
3056+ stats[" outgoing_traffic_speed" ] = outgoing_ipv4 + outgoing_ipv6;
3057+
3058+ stats[" incoming_traffic_speed_ipv4" ] = incoming_ipv4;
3059+ stats[" outgoing_traffic_speed_ipv4" ] = outgoing_ipv4;
3060+
3061+ stats[" incoming_traffic_speed_ipv6" ] = incoming_ipv6;
3062+ stats[" outgoing_traffic_speed_ipv6" ] = outgoing_ipv6;
3063+
3064+ stats[" flows_speed" ] = netflow_ipfix_all_protocols_total_flows_speed;
3065+ stats[" headers_speed" ] = sflow_raw_packet_headers_total_speed;
3066+ stats[" total_hosts" ] = total_number_of_hosts_in_our_networks;
3067+ stats[" cap_plugins" ] = generate_list_of_enabled_capture_engines ();
3068+ stats[" speed_calc_time" ] = speed_calculation_time.tv_sec ;
3069+ stats[" version" ] = fastnetmon_platform_configuration.fastnetmon_version ;
3070+ stats[" virt_method" ] = get_virtualisation_method ();
3071+
3072+ // We use statically allocated counters in that case
3073+ stats[" hosts_hash_ipv4" ] = total_number_of_hosts_in_our_networks;
3074+
3075+ ssize_t hosts_hash_size_ipv6 = 0 ;
3076+
3077+ {
3078+ std::lock_guard<std::mutex> lock_guard (ipv6_host_counters.counter_map_mutex );
3079+ hosts_hash_size_ipv6 = ipv6_host_counters.average_speed_map .size ();
3080+ }
3081+
3082+ stats[" hosts_hash_ipv6" ] = hosts_hash_size_ipv6;
3083+
3084+ bool gobgp = false ;
3085+
3086+ if (configuration_map.count (" gobgp" ) != 0 && configuration_map[" gobgp" ] == " on" ) {
3087+ gobgp = true ;
3088+ }
3089+
3090+ stats[" bgp" ] = gobgp;
3091+
3092+ stats[" bgp_flow_spec" ] = false ;
3093+
3094+ bool influxdb = false ;
3095+
3096+ if (configuration_map.count (" influxdb" ) != 0 && configuration_map[" influxdb" ] == " on" ) {
3097+ influxdb = true ;
3098+ }
3099+
3100+ stats[" influxdb" ] = influxdb;
3101+
3102+ stats[" clickhouse_metrics" ] = false ;
3103+ stats[" traffic_db" ] = false ;
3104+ stats[" prometheus" ] = false ;
3105+
3106+ std::string cpu_model;
3107+ get_cpu_model (cpu_model);
3108+
3109+ stats[" cpu_model" ] = cpu_model;
3110+
3111+ stats[" cpu_logical_cores" ] = get_logical_cpus_number ();
3112+
3113+ // Mbytes
3114+ stats[" memory_size" ] = get_total_memory ();
3115+
3116+ std::string kernel_version = " unknown" ;
3117+
3118+ if (!get_kernel_version (kernel_version)) {
3119+ logger << log4cpp::Priority::ERROR << " Cannot get Linux kernel version" ;
3120+ }
3121+
3122+ stats[" kernel_version" ] = kernel_version;
3123+
3124+ std::vector<std::string> cpu_flags;
3125+
3126+ if (!get_cpu_flags (cpu_flags)) {
3127+ logger << log4cpp::Priority::ERROR << " Cannot get CPU flags" ;
3128+ }
3129+
3130+ stats[" cpu_flags" ] = cpu_flags;
3131+
3132+ std::string linux_distro_name = " unknown" ;
3133+
3134+ if (!get_linux_distro_name (linux_distro_name)) {
3135+ logger << log4cpp::Priority::ERROR << " Cannot get Linux distro name" ;
3136+ }
3137+
3138+ stats[" linux_distro_name" ] = linux_distro_name;
3139+
3140+ std::string linux_distro_version = " unknown" ;
3141+
3142+ if (!get_linux_distro_version (linux_distro_version)) {
3143+ logger << log4cpp::Priority::ERROR << " Cannot get Linux distro version" ;
3144+ }
3145+
3146+ stats[" linux_distro_version" ] = linux_distro_version;
3147+
3148+ std::string instance_id;
3149+
3150+ if (get_instance_id (instance_id)) {
3151+ stats[" instance_id" ] = instance_id;
3152+ } else {
3153+ // OK, it's optional
3154+ }
3155+
3156+ stats_json_string = stats.dump ();
3157+ } catch (...) {
3158+ logger << log4cpp::Priority::ERROR << " Failed to serialise stats" ;
3159+ return ;
3160+ }
3161+
3162+ // It's fair to show but we will expose our delay. We need to make delay random first
3163+ // logger << log4cpp::Priority::DEBUG << "Preparing to send following information to telemetry server " << request_stream.str();
3164+
3165+ uint32_t response_code = 0 ;
3166+ std::string response_body;
3167+ std::string error_text;
3168+
3169+ std::map<std::string, std::string> headers;
3170+
3171+ // I think we need to do it to make clear about format for remote app
3172+ headers[" Content-Type" ] = " application/json" ;
3173+
3174+ // Just do it to know about DNS issues, execute_web_request can do DNS resolution on it's own
3175+ std::string reporting_server_ip_address = dns_lookup (reporting_server);
3176+
3177+ if (reporting_server_ip_address.empty ()) {
3178+ logger << log4cpp::Priority::DEBUG << " Stats server resolver failed, please check your DNS" ;
3179+ return ;
3180+ }
3181+
3182+ bool result = execute_web_request_secure (request_stream.str (), " post" , stats_json_string, response_code,
3183+ response_body, headers, error_text);
3184+
3185+ if (!result) {
3186+ logger << log4cpp::Priority::DEBUG << " Can't collect stats data" ;
3187+ return ;
3188+ }
3189+
3190+ if (response_code != 200 ) {
3191+ logger << log4cpp::Priority::DEBUG << " Got code " << response_code << " from stats server instead of 200" ;
3192+ return ;
3193+ }
3194+ }
3195+
3196+
3197+ void collect_stats () {
3198+ extern unsigned int stats_thread_initial_call_delay;
3199+ extern unsigned int stats_thread_sleep_time;
3200+
3201+ boost::this_thread::sleep (boost::posix_time::seconds (stats_thread_initial_call_delay));
3202+
3203+ while (true ) {
3204+ send_usage_data_to_reporting_server ();
3205+ boost::this_thread::sleep (boost::posix_time::seconds (stats_thread_sleep_time));
3206+ }
3207+ }
3208+
30263209// Adds total traffic metrics to Prometheus endpoint
30273210void add_total_traffic_to_prometheus (const total_speed_counters_t & total_counters, std::stringstream& output, const std::string& protocol_version) {
30283211 std::vector<direction_t > directions = { INCOMING, OUTGOING, INTERNAL, OTHER };
@@ -3288,3 +3471,43 @@ std::string get_human_readable_attack_detection_direction(attack_detection_direc
32883471 return " unknown" ;
32893472 }
32903473}
3474+
3475+ // Sends attack information to reporting server
3476+ void send_attack_data_to_reporting_server (const std::string& attack_json_string) {
3477+ extern std::string reporting_server;
3478+
3479+ // Build query
3480+ std::stringstream request_stream;
3481+
3482+ request_stream << " https://" << reporting_server << " /attacks_v1" ;
3483+
3484+ uint32_t response_code = 0 ;
3485+ std::string response_body;
3486+ std::string error_text;
3487+
3488+ std::map<std::string, std::string> headers;
3489+
3490+ // I think we need to do it to make clear about format for remote app
3491+ headers[" Content-Type" ] = " application/json" ;
3492+
3493+ // Just do it to know about DNS issues, execute_web_request can do DNS resolution on it's own
3494+ std::string reporting_server_ip_address = dns_lookup (reporting_server);
3495+
3496+ if (reporting_server_ip_address.empty ()) {
3497+ logger << log4cpp::Priority::DEBUG << " Stats server resolver failed, please check your DNS" ;
3498+ return ;
3499+ }
3500+
3501+ bool result = execute_web_request_secure (request_stream.str (), " post" , attack_json_string, response_code,
3502+ response_body, headers, error_text);
3503+
3504+ if (!result) {
3505+ logger << log4cpp::Priority::DEBUG << " Can't collect attack stats data" ;
3506+ return ;
3507+ }
3508+
3509+ if (response_code != 200 ) {
3510+ logger << log4cpp::Priority::DEBUG << " Got code " << response_code << " from stats server instead of 200" ;
3511+ return ;
3512+ }
3513+ }
0 commit comments