Skip to content

Commit d1bc462

Browse files
Update README.md
1 parent a04fd1c commit d1bc462

4 files changed

Lines changed: 246 additions & 3 deletions

File tree

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ Author and legal owner: Pavel Odintsov
2020

2121

2222
### Installation
23-
- [Linux install instructions](https://github.com/pavel-odintsov/fastnetmon/wiki/Install)
23+
- [Linux install instructions](https://fastnetmon.com/install/)
2424
- [macOS install instructions](https://formulae.brew.sh/formula/fastnetmon)
2525
- [FreeBSD port](https://www.freshports.org/net-mgmt/fastnetmon/)
2626
- [VyOS bundled support](https://vyos.io/)

src/fastnetmon.conf

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,13 @@ logging_remote_syslog_logging = off
1717
logging_remote_syslog_server = 10.10.10.10
1818
logging_remote_syslog_port = 514
1919

20+
# To make FastNetMon better we need to know how you use it and what's your software and hardware platform.
21+
# To accomplish this FastNetMon sends usage information every 1 hour to our statistics server https://community-stats.fastnetmon.com
22+
# We keep high standards of data protection and you can find our privacy policy here: https://community-stats.fastnetmon.com
23+
# You can find information which is being sent at GitHub: https://github.com/pavel-odintsov/fastnetmon/search?q=send_usage_data_to_reporting_server
24+
# If you prefer to disable this capability you need to set following flag to on
25+
disable_usage_report = off
26+
2027
# Enable/Disable any actions in case of attack
2128
enable_ban = on
2229

src/fastnetmon.cpp

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,7 @@ unsigned int stats_thread_sleep_time = 3600;
166166
// Delay before we send first report about usage
167167
unsigned int stats_thread_initial_call_delay = 30;
168168

169-
std::string reporting_server = "community-stats.pavel-odintsov.com";
169+
std::string reporting_server = "community-stats.fastnetmon.com";
170170

171171
// Each this seconds we will check about available data in bucket
172172
unsigned int check_for_availible_for_processing_packets_buckets = 1;
@@ -256,6 +256,9 @@ std::vector<flow_spec_rule_t> static_flowspec_based_whitelist;
256256
std::string graphite_thread_execution_time_desc = "Time consumed by pushing data to Graphite";
257257
struct timeval graphite_thread_execution_time;
258258

259+
// Run stats thread
260+
bool usage_stats = true;
261+
259262
void init_global_ban_settings() {
260263
// ban Configuration params
261264
global_ban_settings.enable_ban_for_pps = false;
@@ -2052,6 +2055,16 @@ int main(int argc, char** argv) {
20522055
set_boost_process_name(inaccurate_time_generator_thread, "fast_time");
20532056
service_thread_group.add_thread(inaccurate_time_generator_thread);
20542057

2058+
if (configuration_map.count("disable_usage_report") != 0 && configuration_map["disable_usage_report"] == "on") {
2059+
usage_stats = false;
2060+
}
2061+
2062+
if (usage_stats) {
2063+
auto stats_thread = new boost::thread(collect_stats);
2064+
set_boost_process_name(stats_thread, "stats");
2065+
service_thread_group.add_thread(stats_thread);
2066+
}
2067+
20552068
// Run screen draw thread for IPv4
20562069
service_thread_group.add_thread(new boost::thread(screen_draw_ipv4_thread));
20572070

src/fastnetmon_logic.cpp

Lines changed: 224 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -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
30273210
void 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

Comments
 (0)