2015-03-19 15:07:24 +01:00
|
|
|
#include <fcntl.h>
|
2020-05-23 20:55:10 +02:00
|
|
|
#include <iostream>
|
|
|
|
#include <sstream>
|
2015-03-19 16:38:18 +01:00
|
|
|
#include <stdint.h>
|
2020-05-23 20:55:10 +02:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
2015-03-19 21:06:55 +01:00
|
|
|
#include <string.h>
|
|
|
|
#include <string>
|
2020-05-23 20:55:10 +02:00
|
|
|
#include <sys/stat.h>
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <unistd.h>
|
2015-03-19 21:06:55 +01:00
|
|
|
|
2015-07-15 13:02:45 +02:00
|
|
|
#include "fastnetmon_pcap_format.h"
|
|
|
|
|
2015-07-24 14:45:15 +02:00
|
|
|
#ifdef ENABLE_DPI
|
|
|
|
#include "fast_dpi.h"
|
|
|
|
#endif
|
|
|
|
|
2015-03-19 21:06:55 +01:00
|
|
|
#include <arpa/inet.h>
|
2020-05-23 20:55:10 +02:00
|
|
|
#include <netinet/in.h>
|
|
|
|
#include <sys/socket.h>
|
2015-03-19 21:06:55 +01:00
|
|
|
|
2015-05-29 14:08:12 +02:00
|
|
|
#include "netflow_plugin/netflow_collector.h"
|
2015-06-17 12:35:42 +02:00
|
|
|
#include "sflow_plugin/sflow_collector.h"
|
|
|
|
|
|
|
|
#include "sflow_plugin/sflow.h"
|
2020-05-23 20:55:10 +02:00
|
|
|
#include "sflow_plugin/sflow_data.h"
|
2015-06-17 12:35:42 +02:00
|
|
|
|
2020-05-23 20:55:10 +02:00
|
|
|
#include "fast_library.h"
|
2015-05-29 14:08:12 +02:00
|
|
|
#include "fastnetmon_packet_parser.h"
|
|
|
|
#include "fastnetmon_types.h"
|
2015-03-19 21:06:55 +01:00
|
|
|
|
|
|
|
#include "log4cpp/Appender.hh"
|
2020-05-23 20:55:10 +02:00
|
|
|
#include "log4cpp/BasicLayout.hh"
|
|
|
|
#include "log4cpp/Category.hh"
|
2015-03-19 21:06:55 +01:00
|
|
|
#include "log4cpp/FileAppender.hh"
|
|
|
|
#include "log4cpp/Layout.hh"
|
2020-05-23 20:55:10 +02:00
|
|
|
#include "log4cpp/OstreamAppender.hh"
|
2015-03-19 21:06:55 +01:00
|
|
|
#include "log4cpp/PatternLayout.hh"
|
|
|
|
#include "log4cpp/Priority.hh"
|
|
|
|
|
2017-07-28 01:09:58 +02:00
|
|
|
#include "unified_parser.hpp"
|
2015-09-10 14:52:26 +02:00
|
|
|
|
2015-03-19 21:06:55 +01:00
|
|
|
// Fake config
|
|
|
|
std::map<std::string, std::string> configuration_map;
|
|
|
|
|
|
|
|
std::string log_file_path = "/tmp/fastnetmon_pcap_reader.log";
|
|
|
|
log4cpp::Category& logger = log4cpp::Category::getRoot();
|
|
|
|
|
2015-09-10 14:52:26 +02:00
|
|
|
uint64_t total_unparsed_packets = 0;
|
|
|
|
|
2015-07-29 14:32:09 +02:00
|
|
|
uint64_t dns_amplification_packets = 0;
|
|
|
|
uint64_t ntp_amplification_packets = 0;
|
|
|
|
uint64_t ssdp_amplification_packets = 0;
|
2015-03-19 15:07:24 +01:00
|
|
|
|
2015-08-30 19:34:13 +02:00
|
|
|
uint64_t raw_parsed_packets = 0;
|
|
|
|
uint64_t raw_unparsed_packets = 0;
|
|
|
|
|
2015-05-15 12:55:52 +02:00
|
|
|
/* It's prototype for moc testing of FastNetMon, it's very useful for netflow or direct packet
|
|
|
|
* parsers debug */
|
2015-03-19 15:07:24 +01:00
|
|
|
|
2015-03-19 21:06:55 +01:00
|
|
|
void init_logging() {
|
2015-05-15 12:55:52 +02:00
|
|
|
log4cpp::PatternLayout* layout = new log4cpp::PatternLayout();
|
|
|
|
layout->setConversionPattern("%d [%p] %m%n");
|
2015-03-19 21:06:55 +01:00
|
|
|
|
2015-05-15 12:55:52 +02:00
|
|
|
log4cpp::Appender* appender = new log4cpp::FileAppender("default", log_file_path);
|
2015-03-19 21:06:55 +01:00
|
|
|
appender->setLayout(layout);
|
|
|
|
|
|
|
|
logger.setPriority(log4cpp::Priority::INFO);
|
|
|
|
logger.addAppender(appender);
|
|
|
|
logger.info("Logger initialized!");
|
|
|
|
}
|
|
|
|
|
2015-07-22 14:16:13 +02:00
|
|
|
void pcap_parse_packet(const char* flow_type, char* buffer, uint32_t len);
|
2015-03-19 15:07:24 +01:00
|
|
|
|
2020-08-02 14:12:42 +02:00
|
|
|
void my_fastnetmon_packet_handler(simple_packet_t& current_packet) {
|
2015-05-15 12:55:52 +02:00
|
|
|
std::cout << print_simple_packet(current_packet);
|
2015-03-19 21:06:55 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
extern process_packet_pointer netflow_process_func_ptr;
|
2015-06-17 12:35:42 +02:00
|
|
|
extern process_packet_pointer sflow_process_func_ptr;
|
2015-03-19 21:06:55 +01:00
|
|
|
|
2015-07-22 14:16:13 +02:00
|
|
|
char* flow_type = NULL;
|
|
|
|
|
2015-07-24 14:45:15 +02:00
|
|
|
#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
|
|
|
|
|
2015-07-30 20:41:50 +02:00
|
|
|
void pcap_parse_packet(char* buffer, uint32_t len, uint32_t snap_len) {
|
2015-03-19 21:06:55 +01:00
|
|
|
struct pfring_pkthdr packet_header;
|
|
|
|
memset(&packet_header, 0, sizeof(packet_header));
|
|
|
|
packet_header.len = len;
|
2015-07-30 20:41:50 +02:00
|
|
|
packet_header.caplen = snap_len;
|
2015-03-19 21:06:55 +01:00
|
|
|
|
2015-05-15 12:55:52 +02:00
|
|
|
fastnetmon_parse_pkt((u_char*)buffer, &packet_header, 4, 1, 0);
|
|
|
|
|
|
|
|
// char print_buffer[512];
|
|
|
|
// fastnetmon_print_parsed_pkt(print_buffer, 512, (u_char*)buffer, &packet_header);
|
|
|
|
// logger.info("%s", print_buffer);
|
2015-03-19 21:06:55 +01:00
|
|
|
|
|
|
|
char* payload_ptr = packet_header.extended_hdr.parsed_pkt.offset.payload_offset + buffer;
|
2015-03-20 09:32:05 +01:00
|
|
|
|
2015-07-29 14:32:09 +02:00
|
|
|
if (packet_header.len < packet_header.extended_hdr.parsed_pkt.offset.payload_offset) {
|
2015-07-27 16:44:51 +02:00
|
|
|
printf("Something goes wrong! Offset %u is bigger than total packet length %u\n",
|
2020-05-23 20:55:10 +02:00
|
|
|
packet_header.extended_hdr.parsed_pkt.offset.payload_offset, packet_header.len);
|
2015-03-20 09:32:05 +01:00
|
|
|
return;
|
|
|
|
}
|
2015-05-15 12:55:52 +02:00
|
|
|
|
2015-03-20 09:32:05 +01:00
|
|
|
unsigned int payload_length = packet_header.len - packet_header.extended_hdr.parsed_pkt.offset.payload_offset;
|
2015-06-17 12:35:42 +02:00
|
|
|
|
|
|
|
if (strcmp(flow_type, "netflow") == 0) {
|
|
|
|
netflow_process_func_ptr = my_fastnetmon_packet_handler;
|
|
|
|
|
|
|
|
std::string fake_peer_ip = "10.0.1.2";
|
|
|
|
process_netflow_packet((u_int8_t*)payload_ptr, payload_length, fake_peer_ip);
|
|
|
|
} else if (strcmp(flow_type, "sflow") == 0) {
|
|
|
|
sflow_process_func_ptr = my_fastnetmon_packet_handler;
|
|
|
|
|
|
|
|
SFSample sample;
|
|
|
|
memset(&sample, 0, sizeof(sample));
|
|
|
|
|
|
|
|
sample.rawSample = (uint8_t*)payload_ptr;
|
|
|
|
sample.rawSampleLen = payload_length;
|
|
|
|
sample.sourceIP.type = SFLADDRESSTYPE_IP_V4;
|
|
|
|
|
|
|
|
read_sflow_datagram(&sample);
|
2015-07-22 14:16:13 +02:00
|
|
|
} else if (strcmp(flow_type, "raw") == 0) {
|
|
|
|
// We do not need parsed data here
|
2015-08-30 20:34:49 +02:00
|
|
|
struct pfring_pkthdr raw_packet_header;
|
|
|
|
memset(&raw_packet_header, 0, sizeof(raw_packet_header));
|
2015-07-22 14:16:13 +02:00
|
|
|
|
2015-08-30 20:34:49 +02:00
|
|
|
raw_packet_header.len = len;
|
|
|
|
raw_packet_header.caplen = snap_len;
|
2015-07-22 14:16:13 +02:00
|
|
|
|
2015-08-30 20:34:49 +02:00
|
|
|
int parser_return_code = fastnetmon_parse_pkt((u_char*)buffer, &raw_packet_header, 4, 1, 0);
|
2015-08-30 19:34:13 +02:00
|
|
|
|
|
|
|
// We are not interested so much in l2 data and we interested only in l3 data here and more
|
|
|
|
if (parser_return_code < 3) {
|
2020-05-23 20:55:10 +02:00
|
|
|
printf("Parser failed for with code %d following packet with number %llu\n",
|
|
|
|
parser_return_code, raw_unparsed_packets + raw_parsed_packets);
|
2015-08-30 19:34:13 +02:00
|
|
|
raw_unparsed_packets++;
|
|
|
|
} else {
|
|
|
|
raw_parsed_packets++;
|
|
|
|
}
|
2015-07-22 14:16:13 +02:00
|
|
|
|
|
|
|
char print_buffer[512];
|
2015-08-30 20:34:49 +02:00
|
|
|
fastnetmon_print_parsed_pkt(print_buffer, 512, (u_char*)buffer, &raw_packet_header);
|
2015-09-10 14:52:26 +02:00
|
|
|
printf("Raw parser: %s", print_buffer);
|
|
|
|
|
2020-08-02 14:12:42 +02:00
|
|
|
simple_packet_t packet;
|
2015-09-10 14:52:26 +02:00
|
|
|
// TODO: add support for caplen here!
|
2017-07-28 01:09:58 +02:00
|
|
|
if (parse_raw_packet_to_simple_packet((u_char*)buffer, len, packet, false)) {
|
2015-09-10 14:52:26 +02:00
|
|
|
std::cout << "High level parser: " << print_simple_packet(packet) << std::endl;
|
|
|
|
} else {
|
|
|
|
printf("High level parser failed\n");
|
2020-05-23 20:55:10 +02:00
|
|
|
}
|
2015-07-24 14:45:15 +02:00
|
|
|
} else if (strcmp(flow_type, "dpi") == 0) {
|
|
|
|
#ifdef ENABLE_DPI
|
2020-05-23 20:55:10 +02:00
|
|
|
struct ndpi_id_struct* src = NULL;
|
|
|
|
struct ndpi_id_struct* dst = NULL;
|
|
|
|
struct ndpi_flow_struct* flow = NULL;
|
2015-07-24 14:45:15 +02:00
|
|
|
|
|
|
|
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);
|
|
|
|
|
2020-05-23 20:55:10 +02:00
|
|
|
flow = (struct ndpi_flow_struct*)malloc(ndpi_size_flow_struct);
|
2015-07-24 14:45:15 +02:00
|
|
|
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]);
|
2020-05-23 20:55:10 +02:00
|
|
|
unsigned int ipsize = packet_header.len;
|
2015-07-24 14:45:15 +02:00
|
|
|
|
2020-05-23 20:55:10 +02:00
|
|
|
ndpi_protocol detected_protocol =
|
|
|
|
ndpi_detection_process_packet(my_ndpi_struct, flow, iph, ipsize, current_tickt, src, dst);
|
2015-07-24 14:45:15 +02:00
|
|
|
|
|
|
|
char* protocol_name = ndpi_get_proto_name(my_ndpi_struct, detected_protocol.protocol);
|
2020-05-23 20:55:10 +02:00
|
|
|
char* master_protocol_name = ndpi_get_proto_name(my_ndpi_struct, detected_protocol.master_protocol);
|
2015-07-24 14:45:15 +02:00
|
|
|
|
|
|
|
printf("Protocol: %s master protocol: %s\n", protocol_name, master_protocol_name);
|
|
|
|
|
2015-07-29 08:39:12 +02:00
|
|
|
if (detected_protocol.protocol == NDPI_PROTOCOL_DNS) {
|
2020-05-23 20:55:10 +02:00
|
|
|
// It's answer for ANY request with so much
|
|
|
|
if (flow->protos.dns.query_type == 255 &&
|
|
|
|
flow->protos.dns.num_queries < flow->protos.dns.num_answers) {
|
2015-07-29 14:32:09 +02:00
|
|
|
dns_amplification_packets++;
|
|
|
|
}
|
2020-05-23 20:55:10 +02:00
|
|
|
|
|
|
|
printf("It's DNS, we could check packet type. query_type: %d query_class: %d rsp_code: "
|
|
|
|
"%d num answers: %d, num queries: %d\n",
|
|
|
|
flow->protos.dns.query_type, flow->protos.dns.query_class, flow->protos.dns.rsp_type,
|
|
|
|
flow->protos.dns.num_answers, flow->protos.dns.num_queries);
|
2015-07-29 08:39:12 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
struct {
|
|
|
|
u_int8_t num_queries, num_answers, ret_code;
|
|
|
|
u_int8_t bad_packet // the received packet looks bad
|
|
|
|
u_int16_t query_type, query_class, rsp_type;
|
|
|
|
} dns;
|
|
|
|
*/
|
|
|
|
|
2020-05-23 20:55:10 +02:00
|
|
|
|
2015-07-29 14:32:09 +02:00
|
|
|
} else if (detected_protocol.protocol == NDPI_PROTOCOL_NTP) {
|
2020-05-23 20:55:10 +02:00
|
|
|
printf("Request type field: %d version: %d\n", flow->protos.ntp.request_code,
|
|
|
|
flow->protos.ntp.version);
|
2015-07-29 14:32:09 +02:00
|
|
|
|
|
|
|
// Detect packets with type MON_GETLIST_1
|
|
|
|
if (flow->protos.ntp.version == 2 && flow->protos.ntp.request_code == 42) {
|
|
|
|
ntp_amplification_packets++;
|
|
|
|
}
|
|
|
|
} else if (detected_protocol.protocol == NDPI_PROTOCOL_SSDP) {
|
|
|
|
ssdp_amplification_packets++;
|
2015-07-29 08:39:12 +02:00
|
|
|
}
|
|
|
|
|
2015-07-29 07:54:48 +02:00
|
|
|
ndpi_free_flow(flow);
|
2015-07-24 14:45:15 +02:00
|
|
|
free(dst);
|
|
|
|
free(src);
|
2020-05-23 20:55:10 +02:00
|
|
|
#endif
|
2015-06-17 12:35:42 +02:00
|
|
|
} else {
|
|
|
|
printf("We do not support this flow type: %s\n", flow_type);
|
|
|
|
}
|
2015-03-19 21:06:55 +01:00
|
|
|
}
|
|
|
|
|
2015-05-29 15:28:10 +02:00
|
|
|
int main(int argc, char** argv) {
|
2015-03-20 01:15:23 +01:00
|
|
|
init_logging();
|
2015-05-29 15:28:10 +02:00
|
|
|
|
2015-06-17 12:35:42 +02:00
|
|
|
if (argc != 3) {
|
2015-07-24 14:45:15 +02:00
|
|
|
printf("Please provide flow type: sflow, netflow, raw or dpi and path to pcap dump\n");
|
2015-05-29 15:28:10 +02:00
|
|
|
exit(1);
|
|
|
|
}
|
2020-05-23 20:55:10 +02:00
|
|
|
|
2015-07-22 14:16:13 +02:00
|
|
|
flow_type = argv[1];
|
2015-06-17 12:35:42 +02:00
|
|
|
printf("We will process file: %s as %s dump\n", argv[2], argv[1]);
|
2015-07-24 14:45:15 +02:00
|
|
|
|
|
|
|
#ifdef ENABLE_DPI
|
|
|
|
if (strcmp(flow_type, "dpi") == 0) {
|
|
|
|
my_ndpi_struct = init_ndpi();
|
|
|
|
|
|
|
|
if (my_ndpi_struct == NULL) {
|
|
|
|
printf("Can't load nDPI\n");
|
|
|
|
exit(0);
|
|
|
|
}
|
|
|
|
|
2020-05-23 20:55:10 +02:00
|
|
|
ndpi_size_id_struct = ndpi_detection_get_sizeof_ndpi_id_struct();
|
2015-07-24 14:45:15 +02:00
|
|
|
ndpi_size_flow_struct = ndpi_detection_get_sizeof_ndpi_flow_struct();
|
|
|
|
}
|
|
|
|
#endif
|
2020-05-23 20:55:10 +02:00
|
|
|
|
2015-07-22 14:16:13 +02:00
|
|
|
pcap_reader(argv[2], pcap_parse_packet);
|
2015-07-29 14:32:09 +02:00
|
|
|
|
2015-08-30 19:34:13 +02:00
|
|
|
if (strcmp(flow_type, "raw") == 0) {
|
|
|
|
printf("Parsed packets: %llu\n", raw_parsed_packets);
|
|
|
|
printf("Unparsed packets: %llu\n", raw_unparsed_packets);
|
|
|
|
|
|
|
|
printf("Total packets: %llu\n", raw_parsed_packets + raw_unparsed_packets);
|
|
|
|
}
|
|
|
|
|
2015-07-29 14:32:09 +02:00
|
|
|
#ifdef ENABLE_DPI
|
2015-08-30 20:34:49 +02:00
|
|
|
if (strcmp(flow_type, "dpi") == 0) {
|
|
|
|
printf("DNS amplification packets: %lld\n", dns_amplification_packets);
|
|
|
|
printf("NTP amplification packets: %lld\n", ntp_amplification_packets);
|
|
|
|
printf("SSDP amplification packets: %lld\n", ssdp_amplification_packets);
|
|
|
|
}
|
2015-07-29 14:32:09 +02:00
|
|
|
#endif
|
2015-03-19 15:07:24 +01:00
|
|
|
}
|