1
0
Fork 0
mirror of https://github.com/pavel-odintsov/fastnetmon synced 2024-05-26 20:26:16 +02:00

Since this commit we could parse attack details with DPI

This commit is contained in:
Pavel Odintsov 2015-07-29 17:15:04 +02:00
parent 56553af327
commit 0e00a9c333
4 changed files with 166 additions and 4 deletions

View File

@ -41,6 +41,7 @@ Features:
- Thresholds could be configured in per subnet basis with hostgroups feature
- Could [announce blocked IPs](docs/EXABGP_INTEGRATION.md) to BGP router with [ExaBGP](https://github.com/Exa-Networks/exabgp)
- Have integration with [Graphite](docs/GRAPHITE_INTEGRATION.md)
- Deep packet inspection for attack traffic
- netmap support (open source; wire speed processing; only Intel hardware NICs or any hypervisor VM type)
- Could filter out NetFLOW v5 flows or sFLOW packets with script implemented in LUA (useful for port exclude)
- Supports L2TP decapsulation, VLAN untagging and MPLS processing in mirror mode

View File

@ -106,6 +106,7 @@ add_library(sflow_plugin STATIC sflow_plugin/sflow_collector.cpp)
add_library(netflow_plugin STATIC netflow_plugin/netflow_collector.cpp)
target_link_libraries(netflow_plugin ipfix_rfc)
# set(ENABLE_DPI_SUPPORT YES)
if (ENABLE_DPI_SUPPORT)
add_library(fast_dpi STATIC fast_dpi.cpp)

View File

@ -24,6 +24,7 @@
#include "libpatricia/patricia.h"
#include "fastnetmon_types.h"
#include "fastnetmon_packet_parser.h"
#include "fast_library.h"
#include "packet_storage.h"
#include "bgp_flow_spec.h"
@ -31,6 +32,10 @@
// Here we store variables which differs for different paltforms
#include "fast_platform.h"
#ifdef ENABLE_DPI
#include "fast_dpi.h"
#endif
// Plugins
#include "sflow_plugin/sflow_collector.h"
#include "netflow_plugin/netflow_collector.h"
@ -111,6 +116,13 @@ int unban_iteration_sleep_time = 60;
bool unban_enabled = true;
#ifdef ENABLE_DPI
struct ndpi_detection_module_struct* my_ndpi_struct = NULL;
u_int32_t ndpi_size_flow_struct = 0;
u_int32_t ndpi_size_id_struct = 0;
#endif
/* Configuration block, we must move it to configuration file */
#ifdef REDIS
unsigned int redis_port = 6379;
@ -312,6 +324,10 @@ bool process_incoming_traffic = true;
bool process_outgoing_traffic = true;
// Prototypes
#ifdef ENABLE_DPI
void init_current_instance_of_ndpi();
#endif
#ifdef HWFILTER_LOCKING
void block_all_traffic_with_82599_hardware_filtering(std::string client_ip_as_string);
#endif
@ -2198,6 +2214,10 @@ int main(int argc, char** argv) {
// If we not failed in check steps we could run toolkit
print_pid_to_file(getpid(), pid_path);
#ifdef ENABLE_DPI
init_current_instance_of_ndpi();
#endif
lookup_tree = New_Patricia(32);
whitelist_tree = New_Patricia(32);
@ -3022,6 +3042,122 @@ void send_attack_details(uint32_t client_ip, attack_details current_attack_detai
}
}
#ifdef ENABLE_DPI
void dpi_parse_packet(char* buffer, uint32_t len, std::stringstream& ss) {
struct pfring_pkthdr packet_header;
memset(&packet_header, 0, sizeof(packet_header));
packet_header.len = len;
packet_header.caplen = len;
fastnetmon_parse_pkt((u_char*)buffer, &packet_header, 3, 1, 0);
struct ndpi_id_struct *src = NULL;
struct ndpi_id_struct *dst = NULL;
struct ndpi_flow_struct *flow = NULL;
src = (struct ndpi_id_struct*)malloc(ndpi_size_id_struct);
memset(src, 0, ndpi_size_id_struct);
dst = (struct ndpi_id_struct*)malloc(ndpi_size_id_struct);
memset(dst, 0, ndpi_size_id_struct);
flow = (struct ndpi_flow_struct *)malloc(ndpi_size_flow_struct);
memset(flow, 0, ndpi_size_flow_struct);
uint32_t current_tickt = 0;
uint8_t* iph = (uint8_t*)(&buffer[packet_header.extended_hdr.parsed_pkt.offset.l3_offset]);
unsigned int ipsize = packet_header.len;
ndpi_protocol detected_protocol = ndpi_detection_process_packet(my_ndpi_struct, flow, iph, ipsize, current_tickt, src, dst);
char* protocol_name = ndpi_get_proto_name(my_ndpi_struct, detected_protocol.protocol);
char* master_protocol_name = ndpi_get_proto_name(my_ndpi_struct, detected_protocol.master_protocol);
char print_buffer[512];
fastnetmon_print_parsed_pkt(print_buffer, 512, (u_char*)buffer, &packet_header);
ss << print_buffer << " protocol: " << protocol_name << " master_protocol: " << master_protocol_name << "\n";
ndpi_free_flow(flow);
free(dst);
free(src);
}
#endif
#ifdef ENABLE_DPI
void init_current_instance_of_ndpi() {
my_ndpi_struct = init_ndpi();
if (my_ndpi_struct == NULL) {
logger << log4cpp::Priority::ERROR << "Can't load nDPI, disable it!";
process_pcap_attack_dumps_with_dpi = false;
return;
}
// Load sizes of main parsing structures
ndpi_size_id_struct = ndpi_detection_get_sizeof_ndpi_id_struct();
ndpi_size_flow_struct = ndpi_detection_get_sizeof_ndpi_flow_struct();
}
// Not so pretty copy and paste from pcap_reader()
// TODO: rewrite to memory parser
void produce_dpi_dump_for_pcap_dump(std::string pcap_file_path, std::stringstream& ss) {
int filedesc = open(pcap_file_path.c_str(), O_RDONLY);
if (filedesc <= 0) {
logger << log4cpp::Priority::ERROR << "Can't open file for DPI";
return;
}
struct fastnetmon_pcap_file_header pcap_header;
ssize_t file_header_readed_bytes = read(filedesc, &pcap_header, sizeof(struct fastnetmon_pcap_file_header));
if (file_header_readed_bytes != sizeof(struct fastnetmon_pcap_file_header)) {
logger << log4cpp::Priority::ERROR << "Can't read pcap file header";
return;
}
// http://www.tcpdump.org/manpages/pcap-savefile.5.html
if (pcap_header.magic == 0xa1b2c3d4 or pcap_header.magic == 0xd4c3b2a1) {
// printf("Magic readed correctly\n");
} else {
logger << log4cpp::Priority::ERROR << "Magic in file header broken";
return;
}
// Buffer for packets
char packet_buffer[pcap_header.snaplen];
unsigned int read_packets = 0;
while (1) {
// printf("Start packet %d processing\n", read_packets);
struct fastnetmon_pcap_pkthdr pcap_packet_header;
ssize_t packet_header_readed_bytes =
read(filedesc, &pcap_packet_header, sizeof(struct fastnetmon_pcap_pkthdr));
if (packet_header_readed_bytes != sizeof(struct fastnetmon_pcap_pkthdr)) {
// We haven't any packets
break;
}
if (pcap_packet_header.incl_len > pcap_header.snaplen) {
logger << log4cpp::Priority::ERROR << "Please enlarge packet buffer for DPI";
return;
}
ssize_t packet_payload_readed_bytes = read(filedesc, packet_buffer, pcap_packet_header.incl_len);
if (pcap_packet_header.incl_len != packet_payload_readed_bytes) {
logger << log4cpp::Priority::ERROR << "I read packet header but can't read packet payload";
return;
}
dpi_parse_packet(packet_buffer, pcap_packet_header.incl_len, ss);
}
}
#endif
void call_attack_details_handlers(uint32_t client_ip, attack_details& current_attack, std::string attack_fingerprint) {
std::string client_ip_as_string = convert_ip_as_uint_to_string(client_ip);
std::string attack_direction = get_direction_name(current_attack.attack_direction);
@ -3029,10 +3165,11 @@ void call_attack_details_handlers(uint32_t client_ip, attack_details& current_at
print_attack_details_to_file(attack_fingerprint, client_ip_as_string, current_attack);
if (collect_attack_pcap_dumps) {
std::string ban_timestamp_as_string = print_time_t_in_fastnetmon_format(current_attack.ban_timestamp);
std::string attack_pcap_dump_path = attack_details_folder + "/" + client_ip_as_string + "_" + ban_timestamp_as_string + ".pcap";
// We place this variables here because we need this paths from DPI parser code
std::string ban_timestamp_as_string = print_time_t_in_fastnetmon_format(current_attack.ban_timestamp);
std::string attack_pcap_dump_path = attack_details_folder + "/" + client_ip_as_string + "_" + ban_timestamp_as_string + ".pcap";
if (collect_attack_pcap_dumps) {
int pcap_fump_filedesc = open(attack_pcap_dump_path.c_str(), O_WRONLY|O_CREAT, S_IRUSR|S_IWUSR);
if (pcap_fump_filedesc <= 0) {
logger << log4cpp::Priority::ERROR << "Can't open file for storing pcap dump: " << attack_pcap_dump_path;
@ -3046,10 +3183,24 @@ void call_attack_details_handlers(uint32_t client_ip, attack_details& current_at
}
// Freeup memory
current_attack.pcap_attack_dump.deallocate_buffer();
current_attack.pcap_attack_dump.deallocate_buffer();
}
}
#ifdef ENABLE_DPI
// Yes, will be fine to read packets from the memory but we haven't this code yet
// Thus we could read from file with not good performance because it's simpler
if (collect_attack_pcap_dumps && process_pcap_attack_dumps_with_dpi) {
std::stringstream string_buffer_for_dpi_data;
string_buffer_for_dpi_data << "\n\nDPI\n\n";
produce_dpi_dump_for_pcap_dump(attack_pcap_dump_path, string_buffer_for_dpi_data);
attack_fingerprint = attack_fingerprint + string_buffer_for_dpi_data.str();
}
#endif
// Pass attack details to script
if (notify_script_enabled) {
logger << log4cpp::Priority::INFO

View File

@ -117,6 +117,15 @@ class packet_storage_t {
void* get_buffer_pointer() {
return memory_pointer;
}
unsigned int get_max_packet_size() {
return this->max_packet_size;
}
void set_max_packet_size(unsigned int new_max_packet_size) {
this->max_packet_size = new_max_packet_size;
}
private:
unsigned char* memory_pointer;
unsigned char* memory_pos;