nDPI代码深度解析(一)

来源:互联网 发布:部落冲突弹簧升级数据 编辑:程序博客网 时间:2024/05/16 00:29
nDPI从OpenDPI发展而来,解决了OpenDPI的诸多问题,并具备相当完善的应用层协议识别功能,几乎成为DPI领域的唯一之选。nDPI所能识别的具体协议列表,以及很对OpenDPI做了哪些优化,这里不再详列。nDPI项目代码不敢苟同,代码洋洋洒洒如行云流水,缺少一种统一的编码风格,部分代码仍有较大改进空间,且缺少完善文档及注释。本系列文档,旨在深度解析nDPI项目代码。

nDPI协议识别总体分为如下部分:

  • 结构初始化 ndpi_workflow_init
  • 议模块加载 ndpi_init_protocol_defaults
  • 协议识别算法注册 ndpi_set_protocol_detection_bitmask2
  • 进行流量分类,进行协议识别 ndpi_detection_process_packet
  • 针对未能识别的协议进行协议猜测 ndpi_guess_protocol_id
  • 产生协议识别结果,记录在结构体 ndpi_flow_struct

上述每一部分都需要进行详细走读,有了这个框架流程后,便可粗略清楚每个部分干了哪些事。其中,协议记载,以及协议识别算法注册部分,均采用了模块化方法,可很方便地进行新增或卸载协议,该部分后续详细介绍。

关键结构体走读:
该结构体贯穿整个流程中,从初始化,到产生识别结果,至为关键。该数据结构的组织,决定了一些关键流程及算法,称为nDPI的核心不为过。

struct ndpi_flow_struct {  /*协议识别结果*/  u_int16_t detected_protocol_stack[NDPI_PROTOCOL_SIZE]; #ifndef WIN32  __attribute__ ((__packed__))#endif  u_int16_t protocol_stack_info;  /* init parameter, internal used to set up timestamp,... */  u_int16_t guessed_protocol_id, guessed_host_protocol_id;  u_int8_t protocol_id_already_guessed:1, host_already_guessed:1, init_finished:1, setup_packet_direction:1, packet_direction:1, check_extra_packets:1;  /*     if ndpi_struct->direction_detect_disable == 1     tcp sequence number connection tracking  */  u_int32_t next_tcp_seq_nr[2];  u_int8_t max_extra_packets_to_check;  u_int8_t num_extra_packets_checked;  int (*extra_packets_func) (struct ndpi_detection_module_struct *, struct ndpi_flow_struct *flow);  /*     the tcp / udp / other l4 value union     used to reduce the number of bytes for tcp or udp protocol states  */  union {    struct ndpi_flow_tcp_struct tcp;    struct ndpi_flow_udp_struct udp;  } l4;  /*     Pointer to src or dst     that identifies the     server of this connection  */  struct ndpi_id_struct *server_id;  /* HTTP host or DNS query */  u_char host_server_name[256];  /*     This structure below will not not stay inside the protos     structure below as HTTP is used by many subprotocols     such as FaceBook, Google... so it is hard to know     when to use it or not. Thus we leave it outside for the     time being.  */  struct {    ndpi_http_method method;    char *url, *content_type;    u_int8_t  num_request_headers, num_response_headers;    u_int8_t  request_version; /* 0=1.0 and 1=1.1. Create an enum for this? */    u_char response_status_code[5]; /* 200, 404, etc. */  } http;  union {    /* the only fields useful for nDPI and ntopng */    struct {      u_int8_t num_queries, num_answers, reply_code;      u_int16_t query_type, query_class, rsp_type;    } dns;    struct {      u_int8_t request_code;      u_int8_t version;    } ntp;    struct {      char client_certificate[48], server_certificate[48];    } ssl;    struct {      char client_signature[48], server_signature[48];    } ssh;    struct {      char answer[96];    } mdns;    struct {      char version[96];    } ubntac2;    struct {      /* Via HTTP User-Agent */      u_char detected_os[32];      /* Via HTTP X-Forwarded-For */      u_char nat_ip[24];    } http;    struct {      /* Bittorrent hash */      u_char hash[20];    } bittorrent;    struct {      char fingerprint[48];    } dhcp;  } protos;  /*** ALL protocol specific 64 bit variables here ***/  /* protocols which have marked a connection as this connection cannot be protocol XXX, multiple u_int64_t */  NDPI_PROTOCOL_BITMASK excluded_protocol_bitmask;  u_int8_t num_stun_udp_pkts;#ifdef NDPI_PROTOCOL_REDIS  u_int8_t redis_s2d_first_char, redis_d2s_first_char;#endif  u_int16_t packet_counter;           // can be 0 - 65000  u_int16_t packet_direction_counter[2];  u_int16_t byte_counter[2];#ifdef NDPI_PROTOCOL_BITTORRENT  u_int8_t bittorrent_stage;              // can be 0 - 255#endif#ifdef NDPI_PROTOCOL_DIRECTCONNECT  u_int32_t directconnect_stage:2;        // 0 - 1#endif#ifdef NDPI_PROTOCOL_SIP#ifdef NDPI_PROTOCOL_YAHOO  u_int32_t sip_yahoo_voice:1;#endif#endif#ifdef NDPI_PROTOCOL_HTTP  u_int32_t http_detected:1;#endif#ifdef NDPI_PROTOCOL_RTSP  u_int32_t rtsprdt_stage:2;  u_int32_t rtsp_control_flow:1;#endif#ifdef NDPI_PROTOCOL_YAHOO  u_int32_t yahoo_detection_finished:2;#endif#ifdef NDPI_PROTOCOL_ZATTOO  u_int32_t zattoo_stage:3;#endif#ifdef NDPI_PROTOCOL_QQ  u_int32_t qq_stage:3;#endif#ifdef NDPI_PROTOCOL_THUNDER  u_int32_t thunder_stage:2;                // 0 - 3#endif#ifdef NDPI_PROTOCOL_OSCAR  u_int32_t oscar_ssl_voice_stage:3;  u_int32_t oscar_video_voice:1;#endif#ifdef NDPI_PROTOCOL_FLORENSIA  u_int32_t florensia_stage:1;#endif#ifdef NDPI_PROTOCOL_SOCKS  u_int32_t socks5_stage:2;                 // 0 - 3  u_int32_t socks4_stage:2;                 // 0 - 3#endif#ifdef NDPI_PROTOCOL_EDONKEY  u_int32_t edonkey_stage:2;                    // 0 - 3#endif#ifdef NDPI_PROTOCOL_FTP_CONTROL  u_int32_t ftp_control_stage:2;#endif#ifdef NDPI_PROTOCOL_RTMP  u_int32_t rtmp_stage:2;#endif#ifdef NDPI_PROTOCOL_PANDO  u_int32_t pando_stage:3;#endif#ifdef NDPI_PROTOCOL_STEAM  u_int32_t steam_stage:3;  u_int32_t steam_stage1:3;         // 0 - 4  u_int32_t steam_stage2:2;         // 0 - 2  u_int32_t steam_stage3:2;         // 0 - 2#endif#ifdef NDPI_PROTOCOL_PPLIVE  u_int32_t pplive_stage1:3;            // 0 - 6  u_int32_t pplive_stage2:2;            // 0 - 2  u_int32_t pplive_stage3:2;            // 0 - 2#endif#ifdef NDPI_PROTOCOL_STARCRAFT  u_int32_t starcraft_udp_stage : 3;    // 0-7#endif#ifdef NDPI_PROTOCOL_OPENVPN  u_int8_t ovpn_session_id[8];  u_int8_t ovpn_counter;#endif#ifdef NDPI_PROTOCOL_TINC  u_int8_t tinc_state;  struct tinc_cache_entry tinc_cache_entry;#endif#ifdef NDPI_PROTOCOL_CSGO  u_int8_t csgo_strid[18],csgo_state,csgo_s2;  u_int32_t csgo_id2;#endif  /* internal structures to save functions calls */  struct ndpi_packet_struct packet;  struct ndpi_flow_struct *flow;  struct ndpi_id_struct *src;  struct ndpi_id_struct *dst;};
阅读全文
0 0
原创粉丝点击