#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "forge_socket.h" #include "stream.h" #include "MESA_prof_load.h" #include "MESA_handle_logger.h" #include "MESA_htable.h" #include "MESA_list_queue.h" #include "Maat_rule.h" #include "kni.h" int g_kni_version_VERSION_20180620; struct kni_var_comm g_kni_comminfo; struct kni_var_struct g_kni_structinfo; struct kni_var_maat g_kni_maatinfo; extern int g_iThreadNum; extern "C" int sendpacket_do_checksum(unsigned char* buf,int protocol,int len); extern "C" int sendpacket_build_ethernet(unsigned char* dst,unsigned char* src,unsigned short type,const unsigned char* payload,int payload_s,unsigned char* buf); extern "C" unsigned char MESA_dir_reverse(unsigned char route_dir); /******************************************************************************************************************** name: function: return: *********************************************************************************************************************/ int kni_debug_info_v4(char* module,int state_flag,struct ip* a_packet) { int iplen=ntohs(a_packet->ip_len); struct tcphdr* tcphdr=(struct tcphdr*)((char*)a_packet+4*(a_packet->ip_hl)); unsigned int seq=ntohl(tcphdr->seq); unsigned short sport=0; unsigned short dport=0; char saddr_v4[INET_ADDRSTRLEN]={0}; char daddr_v4[INET_ADDRSTRLEN]={0}; sport=ntohs(tcphdr->source); dport=ntohs(tcphdr->dest); inet_ntop(AF_INET, (void *)&((a_packet->ip_src).s_addr), saddr_v4, INET_ADDRSTRLEN); inet_ntop(AF_INET, (void *)&((a_packet->ip_dst).s_addr), daddr_v4, INET_ADDRSTRLEN); MESA_handle_runtime_log(g_kni_comminfo.logger,RLOG_LV_DEBUG,module,"addr:%s,%d,%s,%d,state_flag:%d,ip_len:%d,seq:%u",saddr_v4,sport,daddr_v4,dport,state_flag,iplen,seq); return 0; } /**************************************************************************** if(sportip_hl)); sport=ntohs(tcphdr->source); dport=ntohs(tcphdr->dest); if((sportip_src).s_addr)ip_dst).s_addr)))) { reverse_flag=1; } if(reverse_flag==1) { ipaddr->saddr=(iphdr->ip_dst).s_addr; ipaddr->daddr=(iphdr->ip_src).s_addr; ipaddr->source=tcphdr->dest; ipaddr->dest=tcphdr->source; } else { ipaddr->saddr=(iphdr->ip_src).s_addr; ipaddr->daddr=(iphdr->ip_dst).s_addr; ipaddr->source=tcphdr->source; ipaddr->dest=tcphdr->dest; } return reverse_flag; } /**************************************************************************** if(sportsource); dport=ntohs(tcphdr->dest); if(sportsaddr,ipv6_hdr->ip6_dst.s6_addr32,IPV6_ADDR_LEN); memcpy(ipaddr->daddr,ipv6_hdr->ip6_src.s6_addr32,IPV6_ADDR_LEN); ipaddr->source=tcphdr->dest; ipaddr->dest=tcphdr->source; } else { memcpy(ipaddr->saddr,ipv6_hdr->ip6_src.s6_addr32,IPV6_ADDR_LEN); memcpy(ipaddr->daddr,ipv6_hdr->ip6_dst.s6_addr32,IPV6_ADDR_LEN); ipaddr->source=tcphdr->source; ipaddr->dest=tcphdr->dest; } return reverse_flag; } static void kni_send_fds(int socket, int *fds, int n) // send fd by socket { struct msghdr msg = {0}; struct cmsghdr *cmsg; char buf[CMSG_SPACE(n * sizeof(int))], dup[256]; memset(buf, 0, sizeof(buf)); struct iovec io = { .iov_base = &dup, .iov_len = sizeof(dup) }; msg.msg_iov = &io; msg.msg_iovlen = 1; msg.msg_control = buf; msg.msg_controllen = sizeof(buf); cmsg = CMSG_FIRSTHDR(&msg); cmsg->cmsg_level = SOL_SOCKET; cmsg->cmsg_type = SCM_RIGHTS; cmsg->cmsg_len = CMSG_LEN(n * sizeof(int)); memcpy ((int *) CMSG_DATA(cmsg), fds, n * sizeof (int)); if (sendmsg (socket, &msg, 0) < 0) { MESA_handle_runtime_log(g_kni_comminfo.logger, RLOG_LV_FATAL,"kni_send_fds","sendmsg()error,errno:%d",errno); return; } return; } int tun_set_queue(int fd, int enable) { struct ifreq ifr; memset(&ifr, 0, sizeof(ifr)); if (enable) ifr.ifr_flags = IFF_ATTACH_QUEUE; else ifr.ifr_flags = IFF_DETACH_QUEUE; return ioctl(fd, TUNSETQUEUE, (void *)&ifr); } int tun_error(int i,int* fds) { for (--i; i >= 0; i--) { close(fds[i]); } return 0; } /* Flags: IFF_TUN - TUN device (no Ethernet headers) * IFF_TAP - TAP device * * IFF_NO_PI - Do not provide packet information * IFF_MULTI_QUEUE - Create a queue of multiqueue device */ int tun_alloc_mq(char *dev, int queues, int *fds) { int i=0; int err=0; int fd; struct ifreq ifr; char *clonedev = (char*)"/dev/net/tun"; memset(&ifr, 0, sizeof(ifr)); ifr.ifr_flags = IFF_TUN | IFF_NO_PI | IFF_MULTI_QUEUE; if (*dev) { strncpy(ifr.ifr_name, dev, IFNAMSIZ); } for (i = 0; i < queues; i++) { if ((fd = open(clonedev, O_RDWR)) < 0) { MESA_handle_runtime_log(g_kni_comminfo.logger, RLOG_LV_FATAL,KNI_MODULE_INIT,"tun_alloc_mq():open error,errno is:%d,action:%s",errno,KNI_ACTION_EXIT); tun_error(i,fds); return -1; } err = ioctl(fd, TUNSETIFF, (void *)&ifr); if (err) { MESA_handle_runtime_log(g_kni_comminfo.logger, RLOG_LV_FATAL,KNI_MODULE_INIT,"tun_alloc_mq():ioctl error,errno is:%d,action:%s",errno,KNI_ACTION_EXIT); close(fd); tun_error(i,fds); return -1; } fds[i] = fd; } return 0; } int tun_alloc(char *dev, int flags) { struct ifreq ifr; int fd, err; char *clonedev = (char*)"/dev/net/tun"; /* open the clone device */ if( (fd = open(clonedev, O_RDWR)) < 0 ) { return fd; } /* preparation of the struct ifr, of type "struct ifreq" */ memset(&ifr, 0, sizeof(ifr)); ifr.ifr_flags = flags; /* IFF_TUN or IFF_TAP, plus maybe IFF_NO_PI */ if (*dev) { strncpy(ifr.ifr_name, dev, IFNAMSIZ); } /* try to create the device */ if( (err = ioctl(fd, TUNSETIFF, (void *) &ifr)) < 0 ) { close(fd); return err; } strcpy(dev, ifr.ifr_name); return fd; } /******************************************************************************************************************** name: function: args: return: *********************************************************************************************************************/ int tun_read_data(int fd,char* recv_buf,int max_buflen) { int recv_len=0; recv_len = read(fd, recv_buf, KNI_MAX_BUFLEN); if(recv_len <0) { printf("tun_read_data error,msg is: %s\n",strerror(errno)); } return recv_len; } /******************************************************************************************************************** name: function: return: *********************************************************************************************************************/ int tun_write_data(int fd,char* send_buf,int send_buflen,struct stream_tuple4_v4* ipv4_addr) { int succ_sendlen=0; succ_sendlen = write(fd, send_buf,send_buflen); if(succ_sendlen<0) { MESA_handle_runtime_log(g_kni_comminfo.logger, RLOG_LV_FATAL,KNI_MODULE_WRITETUN,"write() error!msg is %s",strerror(errno)); } else if(succ_sendlenroute_dir=datainfo->route_dir; ret_data->mss=datainfo->mss; ret_data->state_flag=datainfo->state_flag; memcpy(ret_data->smac,datainfo->smac,MAC_ADDR_LEN); memcpy(ret_data->dmac,datainfo->dmac,MAC_ADDR_LEN); result=1; } return result; } int kni_process_readdata(int thread_seq,int buflen,char* buf) { // int ret=0; int iprever_flag=0; // unsigned char routdir=0; long result=0; struct datainfo_to_tun datainfo; struct ip* iphdr=(struct ip*)buf; struct stream_tuple4_v4 ipv4_addr; struct stream_tuple4_v6 ipv6_addr; if(iphdr->ip_v==4) { iprever_flag=kni_get_ipaddr_v4((void*)buf,&ipv4_addr); kni_debug_info_v4((char*)KNI_MODULE_READTUN,STAT_FLAG_SSL_NOBMD,(struct ip*)buf); MESA_htable_search_cb(g_kni_structinfo.htable_to_tun_v4,(unsigned char*)&ipv4_addr,sizeof(struct stream_tuple4_v4),kni_readtun_htable_cb_v4,(void*)&datainfo,&result); if(result==1) { if(iprever_flag==1) { // routdir=MESA_dir_reverse(datainfo.route_dir); } kni_sendpkt_eth(thread_seq,buflen,buf,&ipv4_addr,iprever_flag,datainfo.smac,datainfo.dmac); } } else { iprever_flag=kni_get_ipaddr_v6((void*)buf,&ipv6_addr); } return 0; } /******************************************************************************************************************** name: function: return: *********************************************************************************************************************/ void* kni_read_tun(void* arg) { int i=0; int recv_len=0; char recv_buf[KNI_MAX_BUFLEN] = {0}; while(1) { for(i=0;itstamp_ok = 0; st->sack_ok = 0; st->wscale_ok = 0; st->ecn_ok = 0; st->snd_wscale = 0; st->rcv_wscale = 0; st->snd_wnd = 0x1000; st->rcv_wnd = 0x1000; st->inet_ttl=-1; //make sure you set snd_una = seq (TODO: fix this in module) return st; } /******************************************************************************************************************** name: function: return: *********************************************************************************************************************/ int fs_set_state(int sock, struct tcp_state *st) { struct sockaddr_in sin; sin.sin_family = AF_INET; sin.sin_addr.s_addr = st->src_ip; sin.sin_port = st->sport; st->snd_una = st->seq; int value = 1; if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &value, sizeof(value)) < 0) { perror("setsockopt SO_REUSEADDR"); return -1; } if (setsockopt(sock, SOL_IP, IP_TRANSPARENT, &value, sizeof(value)) < 0) { perror("setsockopt IP_TRANSPARENT"); return -1; } if (bind(sock, (struct sockaddr *)&sin, sizeof(sin)) < 0) { perror("bind"); return -1; } if (setsockopt(sock, IPPROTO_TCP, TCP_STATE, st, sizeof(struct tcp_state)) < 0) { perror("setsockopt TCP_STATE"); return -1; } return 0; } //default:a_packet is c2s; /******************************************************************************************************************** name: function: return: *********************************************************************************************************************/ int fs_get_modify_state(struct tcp_state* fake_client,struct tcp_state* fake_server,void* a_packet,unsigned int mss) { struct ip* iphdr=(struct ip*)a_packet; struct tcphdr* tcphdr=(struct tcphdr*)((char*)a_packet+4*(iphdr->ip_hl)); fake_client->src_ip=(iphdr->ip_src).s_addr; fake_client->sport=tcphdr->source; fake_client->dst_ip=(iphdr->ip_dst).s_addr; fake_client->dport =tcphdr->dest; fake_client->seq=ntohl(tcphdr->seq); fake_client->ack=ntohl(tcphdr->ack_seq); fake_client->snd_una = fake_client->seq; fake_client->snd_wnd = 0x1000; fake_client->rcv_wnd = 0x1000; fake_client->mss_clamp=mss; fake_server->src_ip=(iphdr->ip_dst).s_addr; fake_server->sport=tcphdr->dest; fake_server->dst_ip=(iphdr->ip_src).s_addr; fake_server->dport =tcphdr->source; fake_server->seq=ntohl(tcphdr->ack_seq); fake_server->ack=ntohl(tcphdr->seq); fake_server->snd_una = fake_server->seq; fake_server->snd_wnd = 0x1000; fake_server->rcv_wnd = 0x1000; fake_server->mss_clamp=mss; return 0; } /******************************************************************************************************************** name:kni_process_fs() function: return: 0:succ -1:error *********************************************************************************************************************/ int kni_process_fs(void* a_packet,unsigned int mss) { // int ret=0; // int val = 1; int fds[2]={0}; fds[KNI_FDS_INDEX_CLIENT]=socket(AF_INET, SOCK_FORGE, 0); fds[KNI_FDS_INDEX_SERVER]=socket(AF_INET, SOCK_FORGE, 0); if (fds[KNI_FDS_INDEX_CLIENT] < 0 || fds[KNI_FDS_INDEX_SERVER]< 0) { perror("SOCK_FORGE socket"); fprintf(stderr, "(Did you insmod forge_socket.ko?)\n"); return -1; } struct tcp_state* fake_client=fs_get_default_state(); struct tcp_state* fake_server=fs_get_default_state(); fs_get_modify_state(fake_client,fake_server,a_packet,mss); fs_set_state(fds[KNI_FDS_INDEX_CLIENT],fake_server); fs_set_state(fds[KNI_FDS_INDEX_SERVER],fake_client); kni_send_fds(g_kni_comminfo.fd_domain,fds,2); kni_debug_info_v4((char*)KNI_MODULE_SENDFD,STAT_FLAG_SSL_NOBMD,(struct ip*)a_packet); close(fds[KNI_FDS_INDEX_CLIENT]); close(fds[KNI_FDS_INDEX_SERVER]); return 0; } /*************************************************************************************** return :state_flag kni_bmd:STAT_FLAG_SNIBMD not kni_bmd:STAT_FLAG_SSL_NOBMD ***************************************************************************************/ int kni_judge_sni(char* sni,int sni_len,int thread_seq) { int state_flag=STAT_FLAG_SSL_NOBMD; int string_scan_num=0; int found_pos; scan_status_t mid=NULL; struct Maat_rule_t maat_result[KNI_MAX_CFGNUM]; string_scan_num=Maat_full_scan_string(g_kni_maatinfo.maat_feather,g_kni_maatinfo.tableid_snibmd,CHARSET_GBK,sni,sni_len,maat_result,&found_pos,KNI_MAX_CFGNUM,&mid,thread_seq); Maat_clean_status(&mid); if(string_scan_num>0) { state_flag=STAT_FLAG_SNIBMD; } return state_flag; } /*************************************************************************************** return :state_flag ssl:STAT_FLAG_SSL_NOBMD not ssl:STAT_FLAG_NOTSSL ***************************************************************************************/ int kni_judge_ssl(char* tcp_data,int tcp_datalen,char* sni,int* sni_len) { // int state_flag=STAT_FLAG_NONE; return STAT_FLAG_SSL_NOBMD; int ssl_header_len=0; char* ssl_header=NULL; unsigned char content_type=0; unsigned short version_in_header=0; unsigned short len_in_header=0; int ssl_body_len=0; char* ssl_body=NULL; unsigned char handshark_type=0; unsigned int len_in_body=0; unsigned short version_in_body=0; unsigned char session_id_len=0; unsigned short ciphersuite_len=0; unsigned char compression_method_len=0; int ssl_extention_len=0; char* ssl_extention=NULL; unsigned short extension_len_less=0; unsigned short type_in_extension=0; unsigned short len_in_extension=0; //ssl header ssl_header=tcp_data; content_type=*(unsigned char*)&ssl_header[ssl_header_len]; if(content_type!=SSL_CONTENTTYPE_HANDSHAKE) { return STAT_FLAG_NOTSSL; } ssl_header_len+=1; version_in_header=ntohs(*(unsigned short*)&(ssl_header[ssl_header_len])); if((version_in_header!=SSL_VERSION_TLS1_0)&&(version_in_header!=SSL_VERSION_TLS1_1)&&(version_in_header!=SSL_VERSION_TLS1_2)) { return STAT_FLAG_NOTSSL; } ssl_header_len+=2; len_in_header=ntohs(*(unsigned short*)&(ssl_header[ssl_header_len])); if(len_in_header!=tcp_datalen-SSL_HEADER_LEN) { return STAT_FLAG_NOTSSL; } ssl_header_len+=2; //ssl body ssl_body=ssl_header+ssl_header_len; handshark_type=*(unsigned char*)&(ssl_body[ssl_body_len]); if(handshark_type!=SSL_HANDSHAR_TYPE_CLIENTHELLO) { return STAT_FLAG_NOTSSL; } ssl_body_len+=1; // memcpy(&len_in_body,&ssl_body[ssl_body_len],3); len_in_body=*(unsigned char*)&ssl_body[ssl_body_len+2]+256*(*(unsigned char*)&ssl_body[ssl_body_len+1])+65536*(*(unsigned char*)&ssl_body[ssl_body_len]); if(len_in_body!=(len_in_header-SSL_BODY_LEN)) { return STAT_FLAG_NOTSSL; } ssl_body_len+=3; version_in_body=ntohs(*(unsigned short*)&(ssl_body[ssl_body_len])); if((version_in_body!=SSL_VERSION_TLS1_0)&&(version_in_body!=SSL_VERSION_TLS1_1)&&(version_in_body!=SSL_VERSION_TLS1_2)) { return STAT_FLAG_NOTSSL; } ssl_body_len+=2; ssl_body_len+=32; //4byte time,28bytes random session_id_len=*(unsigned char*)&(ssl_body[ssl_body_len]); ssl_body_len+=1; ssl_body_len+=session_id_len; ciphersuite_len=ntohs(*(unsigned short*)&(ssl_body[ssl_body_len])); ssl_body_len+=2; ssl_body_len+=ciphersuite_len; compression_method_len=*(unsigned char*)&(ssl_body[ssl_body_len]); ssl_body_len+=1; ssl_body_len+=compression_method_len; //ssl extention ssl_extention=ssl_body+ssl_body_len; extension_len_less=ntohs(*(unsigned short*)&ssl_extention[ssl_extention_len]); if(extension_len_less!=len_in_body-2-32-1-session_id_len-2-ciphersuite_len-1-compression_method_len-2) { return STAT_FLAG_NOTSSL; } ssl_extention_len+=2; while(ssl_extention_lenKNI_SNI_MAXLEN) { //error return STAT_FLAG_NOTSSL; } memcpy(sni,&ssl_extention[ssl_extention_len],len_in_extension); *sni_len=len_in_extension; return STAT_FLAG_SSL_NOBMD; } else { ssl_extention_len+=len_in_extension; continue; } } return STAT_FLAG_NOTSSL; } /*************************************************************************************** return :state_flag ipbmd:STAT_FLAG_IPBMD not ipbmd:STAT_FLAG_NONE ***************************************************************************************/ int kni_judge_ipbmd(struct ipaddr* addr,int thread_seq) { int state_flag=STAT_FLAG_NONE; int ipscan_num=0; scan_status_t mid=NULL; struct Maat_rule_t maat_result[KNI_MAX_CFGNUM]; ipscan_num=Maat_scan_proto_addr(g_kni_maatinfo.maat_feather,g_kni_maatinfo.tableid_ipbmd,addr,PROTO_TYPE_TCP,maat_result,KNI_MAX_CFGNUM,&mid,thread_seq); Maat_clean_status(&mid); if(ipscan_num>0) { state_flag=STAT_FLAG_IPBMD; } return state_flag; } unsigned short kni_get_mss(struct kni_tcp_hdr* tcphdr,int tcp_hdr_len) { unsigned short mss=KNI_DEFAULT_MSS; return mss; int remain_len=tcp_hdr_len; struct kni_tcp_opt* tcp_opt=NULL; if((tcp_hdr_len<=20)||(tcp_hdr_len>64)) { return mss; } tcp_opt=(struct kni_tcp_opt*)((char*)tcphdr+TCPHDR_DEFAULT_LEN); remain_len-=TCPHDR_DEFAULT_LEN; while(remain_len) { if(tcp_opt->type==2) //MSS { mss=*(unsigned short*)(tcp_opt->content); return mss; } else if((tcp_opt->type==0)||(tcp_opt->type==1)) { remain_len-=1; tcp_opt=(struct kni_tcp_opt*)((char*)tcp_opt+1); } else { remain_len-=tcp_opt->len; tcp_opt=(struct kni_tcp_opt*)((char*)tcp_opt+tcp_opt->len); } } return mss; } long kni_state_htable_cb_v4(void* data,const unsigned char* key,unsigned int size,void* user_arg) { // unsigned short mss=KNI_DEFAULT_MSS; long state_flag=STAT_FLAG_NONE; int sni_len=0; char sni[KNI_MAX_BUFLEN]={0}; struct ipaddr addr_ipbmd; struct datainfo_to_tun* datainfo=(struct datainfo_to_tun*)data; struct args_to_tun* arg=(struct args_to_tun*)user_arg; struct ip* iphdr=(struct ip*)(arg->a_packet); struct kni_tcp_hdr* tcphdr=(struct kni_tcp_hdr*)((char*)iphdr+4*(iphdr->ip_hl)); struct layer_addr_mac* mac_addr=(struct layer_addr_mac*)((char*)iphdr-KNI_ETHER_LEN); //first stream pkt and syn and not syn/ack // if((datainfo==NULL)&&(tcphdr->th_flags&TH_SYN)&&!(tcphdr->th_flags&TH_ACK)) if(datainfo==NULL) { datainfo=(struct datainfo_to_tun*)malloc(sizeof(struct datainfo_to_tun)); datainfo->route_dir=arg->routdir; memset(&addr_ipbmd,0,sizeof(struct ipaddr)); addr_ipbmd.addrtype=ADDR_TYPE_IPV4; addr_ipbmd.v4=(struct stream_tuple4_v4*)key; datainfo->state_flag=kni_judge_ipbmd(&addr_ipbmd,arg->thread_seq); datainfo->mss=kni_get_mss(tcphdr,ntohs(iphdr->ip_len)-4*(iphdr->ip_hl)-arg->tcpdata_len); //for sendpkt test if(arg->iprevers==0) { memcpy(datainfo->smac,mac_addr->src_mac,MAC_ADDR_LEN); memcpy(datainfo->dmac,mac_addr->dst_mac,MAC_ADDR_LEN); } else { memcpy(datainfo->smac,mac_addr->dst_mac,MAC_ADDR_LEN); memcpy(datainfo->dmac,mac_addr->src_mac,MAC_ADDR_LEN); } //end MESA_htable_add(g_kni_structinfo.htable_to_tun_v4, key,size,(void*)datainfo); } if(datainfo==NULL) { return state_flag; } /* if((datainfo->state_flag==STAT_FLAG_NONE)&&(tcphdr->th_flags&TH_SYN)&&(tcphdr->th_flags&TH_ACK)) { mss=kni_get_mss(tcphdr,ntohs(iphdr->ip_len)-4*(iphdr->ip_hl)-arg->tcpdata_len); datainfo->mss=(datainfo->mssmss:mss; } */ //only process full stream pkt,star from syn,double dir; if((datainfo->state_flag==STAT_FLAG_NONE)&&(arg->tcpdata_len>0)) { datainfo->state_flag=kni_judge_ssl(arg->tcpdata,arg->tcpdata_len,sni,&sni_len); if(datainfo->state_flag==STAT_FLAG_SSL_NOBMD) { datainfo->state_flag=kni_judge_sni(sni,sni_len,arg->thread_seq); if(datainfo->state_flag==STAT_FLAG_SSL_NOBMD) { kni_process_fs(arg->a_packet,datainfo->mss); } } } return datainfo->state_flag;; } long kni_state_htable_cb_v6(void* data,const unsigned char* key,unsigned int size,void* user_arg) { struct ipaddr addr_ipbmd; // struct stream_tuple4_v6* ipv4_addr=(struct stream_tuple4_v6*)key; struct datainfo_to_tun* datainfo=(struct datainfo_to_tun*)data; struct args_to_tun* arg=(struct args_to_tun*)user_arg; if(datainfo==NULL) { datainfo=(struct datainfo_to_tun*)malloc(sizeof(struct datainfo_to_tun)); memset(datainfo,0,sizeof(struct datainfo_to_tun)); MESA_htable_add(g_kni_structinfo.htable_to_tun_v4, key,size,(void*)datainfo); memset(&addr_ipbmd,0,sizeof(struct ipaddr)); addr_ipbmd.addrtype=ADDR_TYPE_IPV6; addr_ipbmd.v4=(struct stream_tuple4_v4*)key; datainfo->state_flag=kni_judge_ipbmd(&addr_ipbmd,arg->thread_seq); } return datainfo->state_flag; } extern "C" int kni_ip_entry(struct streaminfo* f_stream,unsigned char routedir,int thread_seq,struct ip* a_packet) { printf("kni_ip_entry!\n"); char ret=APP_STATE_FAWPKT; //ip/tcp info int iplen=ntohs(a_packet->ip_len); struct tcphdr* tcphdr=(struct tcphdr*)((char*)a_packet+4*(a_packet->ip_hl)); char* tcpdata=(char*)tcphdr+4*tcphdr->doff; int tcplen=iplen-4*a_packet->ip_hl-4*tcphdr->doff; unsigned short sport=ntohs(tcphdr->source); unsigned short dport=ntohs(tcphdr->dest); if((sport!=80)&&(sport!=443)&&(dport!=80)&&(dport!=443)) { printf("kni_ip_entry return,ret:%d\n",ret); return ret; } //htable info long state_flag=0; struct stream_tuple4_v4 ipv4_addr; struct args_to_tun usr_arg; usr_arg.a_packet=(void*)a_packet; usr_arg.tcpdata=tcpdata; usr_arg.tcpdata_len=tcplen; usr_arg.thread_seq=thread_seq; usr_arg.iprevers=kni_get_ipaddr_v4(a_packet,&ipv4_addr); if(usr_arg.iprevers==0) { usr_arg.routdir=routedir; } else { usr_arg.routdir=MESA_dir_reverse(routedir); } MESA_htable_search_cb(g_kni_structinfo.htable_to_tun_v4,(unsigned char*)&ipv4_addr,sizeof(struct stream_tuple4_v4),kni_state_htable_cb_v4,(void*)&usr_arg,&state_flag); if(state_flag==STAT_FLAG_SSL_NOBMD) { tun_write_data(g_kni_comminfo.fd_tun[thread_seq],(char*)a_packet,iplen,&ipv4_addr); ret= APP_STATE_DROPPKT; } kni_debug_info_v4((char*)KNI_MODULE_IPENTRY,state_flag,a_packet); printf("kni_ip_entry return,ret:%d\n",ret); return ret; } char kni_ipv6_entry(struct streaminfo *pstream,unsigned char routedir,int thread_seq,void *a_packet) { // int ret; int ip_reverse=0; struct kni_ipv6_hdr* ipv6_hdr=(struct kni_ipv6_hdr*)a_packet; long state_flag=0; struct args_to_tun usr_arg; struct stream_tuple4_v6 ipv6_addr; if(ipv6_hdr->ip6_nex_hdr!=PROTO_TYPE_TCP) { return APP_STATE_DROPME; } ip_reverse=kni_get_ipaddr_v6(a_packet,&ipv6_addr); memset(&usr_arg,0,sizeof(struct args_to_tun)); usr_arg.a_packet=(struct ip*)a_packet; usr_arg.thread_seq=thread_seq; if(ip_reverse==0) { usr_arg.routdir=routedir; } else { usr_arg.routdir=routedir^0x80; } MESA_htable_search_cb(g_kni_structinfo.htable_to_tun_v6,(unsigned char*)&ipv6_addr,sizeof(struct stream_tuple4_v6),kni_state_htable_cb_v6,&usr_arg,&state_flag); if(state_flag==STAT_FLAG_IPBMD) { return APP_STATE_DROPPKT; } tun_write_data_v6(g_kni_comminfo.fd_tun[thread_seq],(char*)a_packet,ntohl(ipv6_hdr->ip6_payload_len)); return APP_STATE_DROPPKT; } int init_profile_info(int* logger_level,char* logger_filepath,int* maat_json_switch,char* table_info_path,char* inc_cfg_dir,char* full_cfg_dir ) { MESA_load_profile_int_def((char*)KNI_CONF_FILENAME,(char*)KNI_CONF_MODE,(char*)"thread_num",&(g_kni_comminfo.thread_num),1); MESA_load_profile_int_def((char*)KNI_CONF_FILENAME,(char*)KNI_CONF_MODE,(char*)"logger_level",logger_level,RLOG_LV_INFO); MESA_load_profile_int_def((char*)KNI_CONF_FILENAME,(char*)KNI_CONF_MODE,(char*)"maat_json_switch",maat_json_switch,0); MESA_load_profile_string_def((char*)KNI_CONF_FILENAME,(char*)KNI_CONF_MODE,(char*)"logger_filepath",logger_filepath,KNI_CONF_MAXLEN,"./log/kni.log"); MESA_load_profile_string_def((char*)KNI_CONF_FILENAME,(char*)KNI_CONF_MODE,(char*)"table_info_path",table_info_path,KNI_CONF_MAXLEN,KNI_TABLEINFO_PATH); MESA_load_profile_string_def((char*)KNI_CONF_FILENAME,(char*)KNI_CONF_MODE,(char*)"inc_cfg_dir",inc_cfg_dir,KNI_CONF_MAXLEN,KNI_INCCFG_FILEPATH); MESA_load_profile_string_def((char*)KNI_CONF_FILENAME,(char*)KNI_CONF_MODE,(char*)"full_cfg_dir",full_cfg_dir,KNI_CONF_MAXLEN,KNI_FULLCFG_FILEPATH); return 0; } int init_domain_fd() { int i_fd = 0; struct sockaddr_un addr; char serverpath[32] = "/home/server_unixsocket_file"; int i_addr_len = sizeof( struct sockaddr_un ); // if ( ( i_fd = socket( AF_UNIX, SOCK_STREAM, 0 ) ) < 0 ) if ( ( i_fd = socket( AF_UNIX, SOCK_DGRAM, 0 ) ) < 0 ) { MESA_handle_runtime_log(g_kni_comminfo.logger, RLOG_LV_FATAL,KNI_MODULE_INIT,"init_domain_fd():socket error,errno is %d,action:%s",errno,KNI_ACTION_EXIT); return -1; } //fill socket adress structure with server's address memset( &addr, 0, sizeof( addr ) ); addr.sun_family = AF_UNIX; strncpy( addr.sun_path, serverpath, sizeof( addr.sun_path ) - 1 ); if ( connect( i_fd, ( struct sockaddr * )&addr, i_addr_len ) < 0 ) { MESA_handle_runtime_log(g_kni_comminfo.logger, RLOG_LV_FATAL,KNI_MODULE_INIT,"init_domain_fd():connect error,errno is %d,action:%s",errno,KNI_ACTION_EXIT); return -1; } return i_fd; } int init_kni_stat_htable() { MESA_htable_create_args_t hash_frags; memset(&hash_frags,0,sizeof(MESA_htable_create_args_t)); hash_frags.thread_safe=KNI_THREAD_SAFE; hash_frags.recursive=1; hash_frags.hash_slot_size=KNI_HTABLE_SIZE; hash_frags.max_elem_num=KNI_HTABLE_MAXNUM; hash_frags.eliminate_type=HASH_ELIMINATE_ALGO_FIFO; hash_frags.expire_time=0; hash_frags.key_comp=NULL; hash_frags.key2index=NULL; hash_frags.data_free=NULL; hash_frags.data_expire_with_condition=NULL; g_kni_structinfo.htable_to_tun_v4=MESA_htable_create(&hash_frags,sizeof(MESA_htable_create_args_t)); g_kni_structinfo.htable_to_tun_v6=MESA_htable_create(&hash_frags,sizeof(MESA_htable_create_args_t)); if((g_kni_structinfo.htable_to_tun_v4==NULL)||(g_kni_structinfo.htable_to_tun_v6==NULL)) { MESA_handle_runtime_log(g_kni_comminfo.logger, RLOG_LV_FATAL,KNI_MODULE_INIT,"MESA_htable_create() error!action:%s",KNI_ACTION_EXIT); return -1; } return 0; } extern "C" char kni_init() { int i=0; int ret=0; char __tun_symbol[512] = "tun0"; int logger_level; char logger_filepath[KNI_CONF_MAXLEN]={0}; int maat_json_switch=0; char table_info_path[KNI_CONF_MAXLEN]={0}; char full_cfg_dir[KNI_CONF_MAXLEN]={0}; char inc_cfg_dir[KNI_CONF_MAXLEN]={0}; // pthread_t pid_write_tun; pthread_t pid_read_tun; inet_aton((const char *)&LOCAL_IP_ADDR,(struct in_addr*)&g_kni_comminfo.local_ip); //init profile init_profile_info(&logger_level,logger_filepath,&maat_json_switch,table_info_path,inc_cfg_dir,full_cfg_dir); //init runtime log g_kni_comminfo.logger=MESA_create_runtime_log_handle(logger_filepath,logger_level); if(g_kni_comminfo.logger==NULL) { printf("MESA_create_runtime_log_handle() error!exit...\n"); return -1; } //sendpkt init // wangyan_send_fake_pkt_init(); //maat g_kni_maatinfo.maat_feather=Maat_feather(g_iThreadNum,table_info_path,g_kni_comminfo.logger); if(g_kni_maatinfo.maat_feather==NULL) { MESA_handle_runtime_log(g_kni_comminfo.logger, RLOG_LV_FATAL,KNI_MODULE_INIT,"Maat_feather() error!table_info_path:%s,action:%s",table_info_path,KNI_ACTION_EXIT); return -1; } if(maat_json_switch==1) { Maat_set_feather_opt(g_kni_maatinfo.maat_feather,MAAT_OPT_JSON_FILE_PATH, KNI_MAATJSON_FILEPATH,strlen(KNI_MAATJSON_FILEPATH)); } else { Maat_set_feather_opt(g_kni_maatinfo.maat_feather,MAAT_OPT_FULL_CFG_DIR,full_cfg_dir,strlen(full_cfg_dir)); Maat_set_feather_opt(g_kni_maatinfo.maat_feather,MAAT_OPT_INC_CFG_DIR,inc_cfg_dir,strlen(inc_cfg_dir)); } ret=Maat_initiate_feather(g_kni_maatinfo.maat_feather); if(ret<0) { MESA_handle_runtime_log(g_kni_comminfo.logger, RLOG_LV_FATAL,KNI_MODULE_INIT,"Maat_initiate_feather() error!action:%s",KNI_ACTION_EXIT); return -1; } g_kni_maatinfo.tableid_ipbmd=Maat_table_register(g_kni_maatinfo.maat_feather,KNI_TABLENAME_IPBMD); g_kni_maatinfo.tableid_snibmd=Maat_table_register(g_kni_maatinfo.maat_feather,KNI_TABLENAME_SNIBMD); if((g_kni_maatinfo.tableid_ipbmd<0)||(g_kni_maatinfo.tableid_snibmd<0)) { MESA_handle_runtime_log(g_kni_comminfo.logger, RLOG_LV_FATAL,KNI_MODULE_INIT,"Maat_table_register() error!ip_tableid:%d,sni_tableid:%d,action:%s",g_kni_maatinfo.tableid_ipbmd,g_kni_maatinfo.tableid_snibmd,KNI_ACTION_EXIT); return -1; } //init htable ret=init_kni_stat_htable(); if(ret<0) { return -1; } //init tun if(g_kni_comminfo.thread_num<=0) { MESA_handle_runtime_log(g_kni_comminfo.logger, RLOG_LV_FATAL,KNI_MODULE_INIT,"thread_num:%d,action:%s",g_kni_comminfo.thread_num,KNI_ACTION_EXIT); return -1; } g_kni_comminfo.fd_tun=(int*)malloc(g_kni_comminfo.thread_num*sizeof(int)); memset(g_kni_comminfo.fd_tun,0,sizeof(g_kni_comminfo.thread_num*sizeof(int))); ret=tun_alloc_mq(__tun_symbol,g_kni_comminfo.thread_num,g_kni_comminfo.fd_tun); if(ret<0) { return -1; } system("ifconfig tun0 192.168.100.1 up"); system("route add default dev tun0"); system("iptables -t mangle -A PREROUTING -p tcp -i tun0 -j TPROXY --tproxy-mark 0x1/0x1 --on-port 50080"); //init domain g_kni_comminfo.fd_domain=init_domain_fd(); if(g_kni_comminfo.fd_domain<0) { MESA_handle_runtime_log(g_kni_comminfo.logger, RLOG_LV_FATAL,KNI_MODULE_INIT,"init_domain_fd()error,action:%s",KNI_ACTION_EXIT); return -1; } //test init raw_socket g_kni_comminfo.ipv4_fd=(int*)malloc(g_kni_comminfo.thread_num*sizeof(int)); for(i=0;i