/* * dpkt_basic_proto_main.cpp * * Created on: Aug 7, 2020 * Author: iie */ #include #include #include #include #include #include "uthash/uthash.h" //#include //#include #include "stellar/utils.h" #include "stellar/session.h" #include "stellar/stellar_exdata.h" #include "stellar/stellar_mq.h" #include "stellar/packet.h" #include "stellar/appid.h" #include "app_l7_protocol.h" const char *dns_name="DNS"; const char *imap_name="IMAP"; const char *quic_name="QUIC"; const char *g_app_proto_conffile="./tsgconf/main.conf"; const char *l7_protocol_file = (char *)"./tsgconf/tsg_l7_protocol.conf"; const char *log_path = (char *)"./tsglog/glimpse_detector/glimpse_detector"; struct glimpse_detector_schema { int level; int max_pkts; int l7_label_id; int l7_bridge_id; int plugin_exdata_idx; int l7_app_id_exdata_idx; int topic_id; int plugin_id; struct stellar *st; char log_path[128]; char l7_label_name[128]; char l7_bridge_name[128]; char l7_library_name[128]; char l7_protocol_file[128]; struct l7_protocol_hash *name_by_id; void *logger; int tcp_topic_id; int udp_topic_id; }; struct l7_protocol_hash g_app_name2lpi_id[]={ {0, LPI_PROTO_UNKNOWN, "UNCATEGORIZED",{}}, //{0, LPI_PROTO_UNKNOWN, "Unknown_UDP"}, //{0, LPI_PROTO_UNSUPPORTED, "Unknown_Other"}, {0, LPI_PROTO_DNS, "DNS", {}}, {0, LPI_PROTO_FTP_CONTROL, "FTP", {}}, //{0, LPI_PROTO_FTP_DATA, "FTP", NULL, NULL}, {0, LPI_PROTP_FTPS, "FTPS", {}}, {0, LPI_PROTO_HTTP, "HTTP", {}}, {0, LPI_PROTO_HTTPS, "HTTPS", {}}, {0, LPI_PROTO_ICMP, "ICMP", {}}, {0, LPI_PROTO_IKE, "IKE", {}}, {0, LPI_PROTO_MAIL, "MAIL", {}}, {0, LPI_PROTO_IMAP, "IMAP", {}}, {0, LPI_PROTO_IMAPS, "IMAPS", {}}, {0, LPI_PROTO_UDP_ESP, "IPSEC", {}}, {0, LPI_PROTO_XMPP, "XMPP", {}}, {0, LPI_PROTO_UDP_L2TP, "L2TP", {}}, {0, LPI_PROTO_UDP_NTP, "NTP", {}}, {0, LPI_PROTO_POP3, "POP3", {}}, {0, LPI_PROTO_POP3S, "POP3S", {}}, {0, LPI_PROTO_PPTP, "PPTP", {}}, {0, LPI_PROTO_UDP_QUIC, "QUIC", {}}, {0, LPI_PROTO_SIP, "SIP", {}}, {0, LPI_PROTO_SMB, "SMB", {}}, {0, LPI_PROTO_SMTP, "SMTP", {}}, {0, LPI_PROTO_SMTPS, "SMTPS", {}}, {0, LPI_PROTO_SPDY, "SPDY", {}}, {0, LPI_PROTO_SSH, "SSH", {}}, {0, LPI_PROTO_SSL, "SSL", {}}, {0, LPI_PROTO_SOCKS4, "SOCKS", {}}, //{0, LPI_PROTO_SOCKS4, "SOCKS4", NULL, NULL}, //{0, LPI_PROTO_SOCKS5, "SOCKS5", NULL, NULL}, {0, LPI_PROTO_TELNET, "TELNET", {}}, {0, LPI_PROTO_UDP_DHCP, "DHCP", {}}, {0, LPI_PROTO_UDP_RADIUS, "RADIUS", {}}, {0, LPI_PROTO_OPENVPN, "OPENVPN", {}}, {0, LPI_PROTO_STUN, "STUN", {}}, {0, LPI_PROTO_UDP_TEREDO, "TEREDO", {}}, {0, LPI_PROTO_UDP_DTLS, "DTLS", {}}, {0, LPI_PROTO_DOH, "DoH", {}}, {0, LPI_PROTO_UDP_ISAKMP, "ISAKMP", {}}, {0, LPI_PROTO_UDP_MDNS, "MDNS", {}}, {0, LPI_PROTO_NETBIOS, "NETBIOS", {}}, {0, LPI_PROTO_UDP_NETFLOW, "NETFLOW", {}}, {0, LPI_PROTO_RDP, "RDP", {}}, {0, LPI_PROTO_UDP_RTCP, "RTCP", {}}, {0, LPI_PROTO_UDP_RTP, "RTP", {}}, {0, LPI_PROTO_UDP_SLP, "SLP", {}}, {0, LPI_PROTO_UDP_SNMP, "SNMP", {}}, {0, LPI_PROTO_UDP_SSDP, "SSDP", {}}, {0, LPI_PROTO_UDP_TFTP, "TFTP", {}}, {0, LPI_PROTO_UDP_BJNP, "BJNP", {}}, {0, LPI_PROTO_LDAP, "LDAP", {}}, {0, LPI_PROTO_RTMP, "RTMP", {}}, {0, LPI_PROTO_RTSP, "RTSP", {}}, {0, LPI_PROTO_ESNI, "ESNI", {}}, {0, LPI_PROTO_STRATUM, "Stratum", {}}, {0, LPI_PROTO_QQ, "QQ", {}}, {0, LPI_PROTO_WECHAT, "WeChat", {}}, {0, LPI_PROTO_MMS, "MMS", {}}, {0, LPI_PROTO_RSYNC, "RSYNC", {}}, {0, LPI_PROTO_UDP_WIREGUARD, "WIREGUARD", {}}, }; struct dns_header { u_int16_t id; #if __BYTE_ORDER == __LITTLE_ENDIAN u_char rd:1; u_char tc:1; u_char aa:1; u_char opcode:4; u_char qr:1; u_char rcode:4; u_char z:3; u_char ra:1; #elif __BYTE_ORDER == __BIG_ENDIAN u_char qr:1; u_char opcode:4; u_char aa:1; u_char tc:1; u_char rd:1; u_char ra:1; u_char z:3; u_char rcode:4; #endif u_int16_t qdcount; u_int16_t ancount; u_int16_t aucount;//authority count u_int16_t adcount;//additional count }; static void get_host_order_port(struct session *sess __unused, unsigned short *sport, unsigned short *dport) { *sport=0; *dport=0; #if 0 // DONE: get host order port from session api 1.0 enum session_addr_type addr_type; struct session_addr *addr=session_get0_addr(sess, &addr_type); unsigned short n_sport = (addr_type == SESSION_ADDR_TYPE_IPV4_TCP || addr_type == SESSION_ADDR_TYPE_IPV4_UDP) ? (addr->ipv4.sport) : ( (addr_type == SESSION_ADDR_TYPE_IPV6_TCP || addr_type == SESSION_ADDR_TYPE_IPV6_UDP) ? (addr->ipv6.sport) : 0); unsigned short n_dport = (addr_type == SESSION_ADDR_TYPE_IPV4_TCP || addr_type == SESSION_ADDR_TYPE_IPV4_UDP) ? (addr->ipv4.dport) : ( (addr_type == SESSION_ADDR_TYPE_IPV6_TCP || addr_type == SESSION_ADDR_TYPE_IPV6_UDP) ? (addr->ipv6.dport) : 0); //unsigned short n_dport = (pstream->addr.addrtype == ADDR_TYPE_IPV4) ? (pstream->addr.tuple4_v4->dest) : ( (pstream->addr.addrtype == ADDR_TYPE_IPV6) ? (pstream->addr.tuple4_v6->dest) : 0); *sport=ntohs(n_sport); *dport=ntohs(n_dport); #else //get host order port from stellar session api #if 0 const struct tuple6 *t6 = session_get_tuple6(sess); enum flow_direction flow_dir = session_get_tuple6_direction(sess); if(flow_dir == FLOW_DIRECTION_C2S) { *sport = ntohs(t6->src_port); *dport = ntohs(t6->dst_port); } else { *sport = ntohs(t6->dst_port); *dport = ntohs(t6->src_port); } #endif const struct packet *pkt = session_get0_current_packet(sess); enum flow_direction flow_dir=session_get_current_flow_direction(sess); if(pkt && (flow_dir==FLOW_DIRECTION_C2S || flow_dir==FLOW_DIRECTION_S2C)) { int layer_cnt=packet_get_layer_count(pkt); const struct layer *layer = packet_get_layer_by_idx(pkt, layer_cnt - 1); if (layer && layer->proto == LAYER_PROTO_TCP) { *sport = ntohs(layer->hdr.tcp->th_sport); *dport = ntohs(layer->hdr.tcp->th_dport); } if (layer && layer->proto == LAYER_PROTO_UDP) { *sport = ntohs(layer->hdr.udp->uh_sport); *dport = ntohs(layer->hdr.udp->uh_dport); } //S2C, swap sport and dport if(flow_dir == FLOW_DIRECTION_S2C) { unsigned short tmp = *sport; *sport = *dport; *dport = tmp; } } #endif return; } static int revise_lpi_result(struct session *sess, const char *scan_data, const int scan_data_len, lpi_module_t* proto, struct traffic_context *context, int l4_is_tcp, int curdir_is_c2s) { unsigned short sport=0, dport=0; get_host_order_port(sess, &sport, &dport); if(sport == 989 || sport == 990 || dport == 989 || dport == 990) { if(proto->protocol == LPI_PROTO_SSL) { proto->protocol=(lpi_protocol_t)LPI_PROTP_FTPS; proto->category=LPI_CATEGORY_FILES; proto->priority=3; proto->name="FTPS"; proto->lpi_callback=NULL; return 1; } } if(sport==443 || dport==443 || sport==80 || dport==80 || sport==8443 || dport==8443) { if(app_identify_get_quic_protocol(curdir_is_c2s, (const unsigned char *)scan_data, scan_data_len) != QUIC_VERSION_UNKNOWN) { //lpi_quic proto->protocol=LPI_PROTO_UDP_QUIC; proto->category=LPI_CATEGORY_WEB; proto->priority=9; proto->name=quic_name; proto->lpi_callback=NULL; return 1; } } if((sport==53 || dport==53) && (scan_data_len>12)) { struct dns_header *dns_hdr=NULL; if(l4_is_tcp) { dns_hdr=(struct dns_header *)(scan_data+2); } else { dns_hdr=(struct dns_header *)scan_data; } if((dns_hdr->qr==1 && ntohs(dns_hdr->qdcount)==1) || (dns_hdr->qr==0 && ntohs(dns_hdr->qdcount)==1 && ntohs(dns_hdr->aucount)==0 && ntohs(dns_hdr->ancount)==0)) { proto->protocol=LPI_PROTO_DNS; proto->category=LPI_CATEGORY_SERVICES; proto->priority=10; proto->name=dns_name; proto->lpi_callback=NULL; return 1; } } if(((sport==143 || dport==143)) && ( (scan_data_len>=11 && memmem(scan_data, scan_data_len, " CAPABILITY", 11)!=NULL) || (scan_data_len>=7 && memmem(scan_data, scan_data_len, " LOGIN ", 7)!=NULL) ) ) { proto->protocol=LPI_PROTO_IMAP; proto->category=LPI_CATEGORY_MAIL; proto->priority=2; proto->name=imap_name; proto->lpi_callback=NULL; return 1; } int c2s_pkt_cnt=context->c2s_pkt; int s2c_pkt_cnt=context->s2c_pkt; if(app_identify_guess_openvpn((const unsigned char *)scan_data, scan_data_len, c2s_pkt_cnt, s2c_pkt_cnt, &context->ovpn, l4_is_tcp, curdir_is_c2s)==1) { proto->protocol=LPI_PROTO_OPENVPN; proto->category=LPI_CATEGORY_TUNNELLING; proto->priority=4; proto->name="OpenVPN"; proto->lpi_callback=NULL; return 1; } return 0; } static int set_lpi_same_name(struct l7_protocol_hash *l7_protocol_hash, struct l7_protocol_hash *l7_protocol_elem, int lpi_protocol_id) { struct l7_protocol_hash *tmp=(struct l7_protocol_hash *)calloc(1, sizeof(struct l7_protocol_hash)); memcpy(tmp, l7_protocol_elem, sizeof(struct l7_protocol_hash)); tmp->lpi_protocol=lpi_protocol_id; HASH_ADD(hh, l7_protocol_hash, lpi_protocol, sizeof(int), tmp); return 0; } static int get_protocol_id(struct l7_protocol_hash *name_by_id, const lpi_module_t* proto) { struct l7_protocol_hash *out=NULL; HASH_FIND(hh, name_by_id, &(proto->protocol), sizeof(int), out); if(out!=NULL) { return out->protocol_id; } return -1; } static struct app_id_message *app_id_messgae_create(unsigned short *id_array, int id_num) { struct app_id_message *result=CALLOC(struct app_id_message, 1); result->origin=ORIGIN_PROTO_IDENTIFY; result->magic=MESSAGE_MAGIC; result->app_id_num=id_num; for(unsigned int i=0; iapp_id_num; i++) { result->app_id[i]=(int)(id_array[i]); result->surrogate_id[i]=0; } return result; } static int update_protocol_id(unsigned short *old_id_array, int *old_id_num, unsigned short new_id) { int i=0; if(*old_id_num>=MAX_APP_ID_NUM) { return 0; } for(i=0; i<(*old_id_num); i++) { if(new_id==old_id_array[i]) { return 0; } } old_id_array[(*old_id_num)]=new_id; (*old_id_num)++; return 1; } static int l7_protocol_mapper(struct glimpse_detector_schema *g_app_proto_para, const char *filename) { size_t i=0,ret=0; FILE *fp=NULL; char line[1024]={0}; char type_name[32]={0}; struct l7_protocol_hash *name2lpi=NULL; struct l7_protocol_hash *l7_protocol=NULL; struct l7_protocol_hash *out=NULL; fp=fopen(filename, "r"); if(fp==NULL) { printf("Open %s failed ...", filename); return -1; } for(i=0; i<(sizeof(g_app_name2lpi_id)/sizeof(struct l7_protocol_hash)); i++) { HASH_ADD(hh, name2lpi, name, strlen(g_app_name2lpi_id[i].name), &(g_app_name2lpi_id[i])); } memset(line, 0, sizeof(line)); while((fgets(line, sizeof(line), fp))!=NULL) { if(line[0]=='#' || line[0]=='\n' || line[0]=='\r' ||line[0]=='\0') { continue; } l7_protocol=(struct l7_protocol_hash *)calloc(1, sizeof(struct l7_protocol_hash)); ret=sscanf(line, "%31s %63s %d", type_name, l7_protocol->name, &l7_protocol->protocol_id); assert(ret==3); HASH_FIND(hh, name2lpi, l7_protocol->name, strlen(l7_protocol->name), out); if(out==NULL) { //MESA_handle_runtime_log(g_app_proto_para->logger, RLOG_LV_FATAL, "INIT_HASH", "Protocol %s identified without registered LPI ID", l7_protocol->name); free(l7_protocol); continue; } l7_protocol->lpi_protocol=out->lpi_protocol; HASH_ADD(hh, g_app_proto_para->name_by_id, lpi_protocol, sizeof(int), l7_protocol); switch(out->lpi_protocol) { case LPI_PROTO_DNS: set_lpi_same_name(g_app_proto_para->name_by_id, l7_protocol, LPI_PROTO_UDP_DNS); break; case LPI_PROTO_SIP: set_lpi_same_name(g_app_proto_para->name_by_id, l7_protocol, LPI_PROTO_UDP_SIP); break; case LPI_PROTO_SOCKS4: set_lpi_same_name(g_app_proto_para->name_by_id, l7_protocol, LPI_PROTO_SOCKS5); break; case LPI_PROTO_FTP_CONTROL: set_lpi_same_name(g_app_proto_para->name_by_id, l7_protocol, LPI_PROTO_FTP_DATA); break; case LPI_PROTO_OPENVPN: set_lpi_same_name(g_app_proto_para->name_by_id, l7_protocol, LPI_PROTO_UDP_OPENVPN); break; case LPI_PROTO_LDAP: set_lpi_same_name(g_app_proto_para->name_by_id, l7_protocol, LPI_PROTO_TCP_LDAP_AD); set_lpi_same_name(g_app_proto_para->name_by_id, l7_protocol, LPI_PROTO_UDP_LDAP_AD); break; case LPI_PROTO_HTTP: set_lpi_same_name(g_app_proto_para->name_by_id, l7_protocol, LPI_PROTO_HTTP_BADPORT); set_lpi_same_name(g_app_proto_para->name_by_id, l7_protocol, LPI_PROTO_HTTP_TUNNEL); set_lpi_same_name(g_app_proto_para->name_by_id, l7_protocol, LPI_PROTO_NONSTANDARD_HTTP); break; case LPI_PROTO_STUN: set_lpi_same_name(g_app_proto_para->name_by_id, l7_protocol, LPI_PROTO_UDP_STUN); break; case LPI_PROTO_NETBIOS: set_lpi_same_name(g_app_proto_para->name_by_id, l7_protocol, LPI_PROTO_UDP_NETBIOS); break; case LPI_PROTO_QQ: set_lpi_same_name(g_app_proto_para->name_by_id, l7_protocol, LPI_PROTO_UDP_QQ); break; case LPI_PROTO_WECHAT: set_lpi_same_name(g_app_proto_para->name_by_id, l7_protocol, LPI_PROTO_UDP_WECHAT); break; default: break; } memset(line, 0, sizeof(line)); } fclose(fp); fp=NULL; HASH_CLEAR(hh, name2lpi); #if 0 HASH_ITER(hh, g_app_proto_para->name_by_id, out ,tmp) { MESA_handle_runtime_log(g_app_proto_para->logger, RLOG_LV_DEBUG, "ID_MAPPER", "%s lpi_protocol built-in ID is %d and TSG ID is %d", out->name, out->lpi_protocol, out->protocol_id ); } #endif return ret; } static void free_l7_protocol_mapper(struct l7_protocol_hash *hash) { if(hash==NULL) { return ; } struct l7_protocol_hash *out=NULL, *tmp=NULL; HASH_ITER(hh, hash, out ,tmp) { if(out!=NULL) { HASH_DEL(hash, out); free(out); out=NULL; } } } int lpi_update_dpkt(lpi_data_t *data, struct session *sess, const char *scan_data, int scan_data_len, char tsproto, uint32_t is_c2s) { uint32_t dir = 0; if(is_c2s == 1) { dir = 0; } else { dir = 1; } uint32_t four_bytes; if (data->observed[dir] > 32 * 1024) return 0; data->observed[dir] += scan_data_len; if (data->trans_proto == 0)data->trans_proto = tsproto; if (scan_data == NULL)return 0; if (scan_data_len <= 0)return 0; if (scan_data_len < 4) { memcpy((char *)&four_bytes, scan_data, scan_data_len); four_bytes = (ntohl(four_bytes)) >> (8 * (4 - scan_data_len)); four_bytes = htonl(four_bytes << (8 * (4 - scan_data_len))); } else { four_bytes = (*(uint32_t *)scan_data); } data->payload[dir] = four_bytes; data->payload_len[dir] = scan_data_len; uint16_t source=0; uint16_t dest=0; get_host_order_port(sess,&source ,&dest); data->client_port = source; data->server_port = dest; // DONE: no need to set saddr and daddr /* if (pstream != NULL && data->ips[0] == 0 && (pstream->addr.addrtype == __ADDR_TYPE_IP_PAIR_V4 || pstream->addr.addrtype == ADDR_TYPE_IPV4)) { if (dir == 1) { data->ips[0] = pstream->addr.ipv4->saddr; data->ips[1] = pstream->addr.ipv4->daddr; } else { data->ips[1] = pstream->addr.ipv4->saddr; data->ips[0] = pstream->addr.ipv4->daddr; } } */ return 1; } static int app_glimpse_detector(struct session *sess, struct traffic_context *context, struct glimpse_detector_schema *g_app_proto_para, const char *scan_data, const int scan_data_len, int l4_proto) { int ret=0,is_update=0; //unsigned short sport=0, dport=0; lpi_module_t modify_lpi_result={(lpi_protocol_t)0, (lpi_category_t)0, NULL, 0, NULL}; unsigned short new_protocol_id=0; struct l7_protocol_label *l7_protocol=NULL; //const struct packet *raw_packet=session_get0_current_packet(sess); //int cur_pkt_dir= packet_get_direction(raw_packet); int cur_pkt_dir=session_get_current_flow_direction(sess); context->pkt_cnt++; (cur_pkt_dir==FLOW_DIRECTION_C2S) ? (context->c2s_pkt++) : (context->s2c_pkt++); int is_c2s_pkt=((cur_pkt_dir==FLOW_DIRECTION_C2S) ? 1 : 0); ret=lpi_update_dpkt(&(context->lpi_data), sess, scan_data, scan_data_len, l4_proto, is_c2s_pkt); if(!ret) { return 1; } lpi_module_t *plpi_mod=lpi_guess_protocol(&(context->lpi_data)); if(plpi_mod==NULL) { return 1; } if((plpi_mod->protocol==LPI_PROTO_UNKNOWN || plpi_mod->protocol==LPI_PROTO_UDP) && (context->pkt_cntmax_pkts || context->is_identify==1)) { ret=revise_lpi_result(sess, scan_data, scan_data_len, &modify_lpi_result, context, (l4_proto==6?1:0), (cur_pkt_dir==FLOW_DIRECTION_C2S?1:0)); if(ret==0) { return 1; } plpi_mod=&modify_lpi_result; } if (plpi_mod->protocol == LPI_PROTO_FTP_CONTROL && context->is_first_payload == 1 && cur_pkt_dir == FLOW_DIRECTION_S2C) { if ((((scan_data_len >= 4 && (memcmp(scan_data, "220-", 4) == 0)) || memcmp(scan_data, "220 ", 4) == 0)) && (((scan_data_len >= 7 && (memmem(scan_data, scan_data_len, " ESMTP ", 7) != NULL)) || memmem(scan_data, scan_data_len, " esmtp ", 7) != NULL))) { // lpi_smtp modify_lpi_result.protocol = LPI_PROTO_SMTP; modify_lpi_result.category = LPI_CATEGORY_MAIL; modify_lpi_result.priority = 2; modify_lpi_result.name = "SMTP"; plpi_mod = &modify_lpi_result; } } if (plpi_mod->protocol == LPI_PROTO_SMTP && context->is_first_payload == 1 && cur_pkt_dir == FLOW_DIRECTION_S2C) { if ( (scan_data_len >= 4) && (memcmp(scan_data, "220 ", 4) == 0 || memcmp(scan_data, "220-", 4) == 0) && (memmem(scan_data, scan_data_len, "FTPd", 4) != NULL || memmem(scan_data, scan_data_len, "ftpd", 4) != NULL || memmem(scan_data, scan_data_len, "FTPD", 4) != NULL)) { // lpi_ftpcontrol modify_lpi_result.protocol = LPI_PROTO_FTP_CONTROL; modify_lpi_result.category = LPI_CATEGORY_FILES; modify_lpi_result.priority = 3; modify_lpi_result.name = "FTP_Control"; plpi_mod = &modify_lpi_result; } } new_protocol_id=get_protocol_id(g_app_proto_para->name_by_id, plpi_mod); #if 0 if(new_protocol_id==(unsigned short)-1) { if(plpi_mod->protocol!=LPI_PROTO_UNKNOWN && plpi_mod->protocol!=LPI_PROTO_UDP && plpi_mod->protocol!=LPI_PROTO_UNSUPPORTED) { MESA_handle_runtime_log(g_app_proto_para->logger, RLOG_LV_INFO, "UNDEFINE", "Protocol Name: %s identified without registered LPI ID=%d, category: %s priority: %d addr: %s", plpi_mod->name, plpi_mod->protocol, lpi_print_category(plpi_mod->category), plpi_mod->priority, session_get0_readable_addr(sess) ); } return 1; } else { MESA_handle_runtime_log(g_app_proto_para->logger, RLOG_LV_INFO, "DEFINE", "Protocol Name: %s identified registered LPI ID(%d), category: %s priority: %d addr: %s", plpi_mod->name, plpi_mod->protocol, lpi_print_category(plpi_mod->category), plpi_mod->priority, session_get0_readable_addr(sess) ); } #endif l7_protocol = (struct l7_protocol_label *)session_exdata_get(sess, g_app_proto_para->l7_app_id_exdata_idx); if(l7_protocol==NULL) { l7_protocol=CALLOC(struct l7_protocol_label, 1); l7_protocol->continue_scan_flag = 1; session_exdata_set(sess, g_app_proto_para->l7_app_id_exdata_idx, l7_protocol); } is_update=update_protocol_id(l7_protocol->protocol_id, &(l7_protocol->protocol_id_num), new_protocol_id); if(is_update==1) { context->is_identify=1; struct app_id_message *msg=app_id_messgae_create(l7_protocol->protocol_id, l7_protocol->protocol_id_num); if(session_mq_publish_message(sess, g_app_proto_para->topic_id, msg) < 0) { FREE(msg); } //MESA_handle_runtime_log(g_app_proto_para->logger, RLOG_LV_DEBUG, "ADD_PROJECT", "%s identified, ID %d addr: %s", plpi_mod->name, new_protocol_id, session_get0_readable_addr(sess)); } if (context->pkt_cnt >= g_app_proto_para->max_pkts || (plpi_mod->category != LPI_CATEGORY_TUNNELLING && plpi_mod->category != LPI_CATEGORY_NAT && plpi_mod->protocol != LPI_PROTO_RDP && plpi_mod->protocol != LPI_PROTO_UDP_RDP && plpi_mod->protocol != LPI_PROTO_UDP_RTP && plpi_mod->protocol != LPI_PROTO_UDP_RTCP)) { l7_protocol->continue_scan_flag=0; return 0; } return 1; } static void glimpse_detector_on_session_msg(struct session *sess, int topic_id __unused, const void *msg, void *per_session_ctx __unused, void *plugin_env) { assert(plugin_env!=NULL); if(msg==NULL)return; struct glimpse_detector_schema *glimpse_detector_env=(struct glimpse_detector_schema *)plugin_env; int identify_continue=0; struct traffic_context *context = (struct traffic_context *)session_exdata_get(sess, glimpse_detector_env->plugin_exdata_idx); if(context==NULL) { context= CALLOC(struct traffic_context, 1); context->is_first_payload=1; session_exdata_set(sess, glimpse_detector_env->plugin_exdata_idx, context); } //size_t payload_len=0; //const char *payload=session_get0_current_payload(sess, &payload_len); uint16_t payload_len=packet_get_payload_len((struct packet*)msg); const char *payload=packet_get_payload((struct packet*)msg); if (payload!=NULL && payload_len>0 && context->pkt_cntmax_pkts) { int l4_proto=0; enum session_type type= session_get_type(sess); if(type == SESSION_TYPE_TCP) { l4_proto=6; } if(type == SESSION_TYPE_UDP) { l4_proto=17; } identify_continue=app_glimpse_detector(sess, context, glimpse_detector_env, payload, payload_len, l4_proto); context->is_first_payload=0; } else { identify_continue=1; } if (identify_continue==0) { if(context->is_identify==0) { //MESA_handle_runtime_log(glimpse_detector_env->logger, RLOG_LV_INFO, "UNKNOWN", "addr: %s", session_get0_readable_addr(sess)); } FREE(context); session_exdata_set(sess, glimpse_detector_env->plugin_exdata_idx, NULL); stellar_session_plugin_dettach_current_session(sess); } return; } extern "C" void APP_GLIMPSE_DETECTOR_UNLOAD(void *plugin_env) { if(plugin_env) { struct glimpse_detector_schema *glimpse_detector_env=(struct glimpse_detector_schema *)plugin_env; lpi_free_library(); free_l7_protocol_mapper(glimpse_detector_env->name_by_id); //if(glimpse_detector_env->logger) //{ // MESA_destroy_runtime_log_handle(glimpse_detector_env->logger); //} FREE(plugin_env); } } extern "C" void * APP_GLIMPSE_DETECTOR_LOAD(struct stellar *st) { int ret=0; struct glimpse_detector_schema *glimpse_detector_env=CALLOC(struct glimpse_detector_schema, 1); glimpse_detector_env->st=st; //MESA_load_profile_short_def(g_app_proto_conffile, "PROTO_IDENTIFY", "LOG_LEVEL", (short *)&glimpse_detector_env->level, 30); glimpse_detector_env->max_pkts=16; strcpy(glimpse_detector_env->l7_bridge_name,"APP_IDENTIFY_RESULT_BRIDGE"); strcpy( glimpse_detector_env->l7_protocol_file, l7_protocol_file); //MESA_load_profile_int_def(g_app_proto_conffile, "PROTO_IDENTIFY", "MAX_IDENTIFY_PACKETS", &glimpse_detector_env->max_pkts, 16); //MESA_load_profile_string_def(g_app_proto_conffile, "PROTO_IDENTIFY", "LOG_PATH", glimpse_detector_env->log_path, sizeof(glimpse_detector_env->log_path), log_path); //MESA_load_profile_string_def(g_app_proto_conffile, "SYSTEM", "APP_IDENTIFY_RESULT_BRIDGE", glimpse_detector_env->l7_bridge_name, sizeof(glimpse_detector_env->l7_bridge_name), "APP_IDENTIFY_RESULT_BRIDGE"); //MESA_load_profile_string_def(g_app_proto_conffile, "SYSTEM", "L7_PROTOCOL_FILE", glimpse_detector_env->l7_protocol_file, sizeof(glimpse_detector_env->l7_protocol_file), l7_protocol_file); //glimpse_detector_env->logger=MESA_create_runtime_log_handle(glimpse_detector_env->log_path, glimpse_detector_env->level); //if(glimpse_detector_env->logger==NULL) //{ // goto INIT_ERROR; //} ret=lpi_init_library(1); // 1, 2 or 3 if(ret<0) { goto INIT_ERROR; } ret=l7_protocol_mapper(glimpse_detector_env,glimpse_detector_env->l7_protocol_file); if(ret<0) { goto INIT_ERROR; } glimpse_detector_env->plugin_id=stellar_session_plugin_register(st, NULL, NULL, glimpse_detector_env); if(glimpse_detector_env->plugin_id < 0) { goto INIT_ERROR; } glimpse_detector_env->tcp_topic_id=stellar_mq_get_topic_id(st, TOPIC_TCP); glimpse_detector_env->udp_topic_id=stellar_mq_get_topic_id(st, TOPIC_UDP); if(glimpse_detector_env->tcp_topic_id < 0 || glimpse_detector_env->udp_topic_id < 0) { perror("get tcp or udp topic id failed\n"); exit(-1); } stellar_session_mq_subscribe(st, glimpse_detector_env->tcp_topic_id, glimpse_detector_on_session_msg, glimpse_detector_env->plugin_id); stellar_session_mq_subscribe(st, glimpse_detector_env->udp_topic_id, glimpse_detector_on_session_msg, glimpse_detector_env->plugin_id); glimpse_detector_env->plugin_exdata_idx = stellar_exdata_new_index(st, "EXDATA_LPI", stellar_exdata_free_default, NULL); glimpse_detector_env->l7_app_id_exdata_idx = stellar_exdata_new_index(st, "L7_PROTOCOL", stellar_exdata_free_default, NULL); glimpse_detector_env->topic_id=stellar_mq_get_topic_id(st, APP_ID_MESSAGE_TOPIC); if(glimpse_detector_env->topic_id < 0) { glimpse_detector_env->topic_id=stellar_mq_create_topic(st, APP_ID_MESSAGE_TOPIC, stellar_msg_free_default, NULL); } return glimpse_detector_env; INIT_ERROR: APP_GLIMPSE_DETECTOR_UNLOAD(glimpse_detector_env); exit(-1); return NULL; }