From 01b5b4a9f693ea24149da65224b5efc26192a206 Mon Sep 17 00:00:00 2001 From: liuyang Date: Tue, 19 Jun 2018 11:47:26 +0800 Subject: [PATCH] =?UTF-8?q?=E5=88=9D=E7=89=88=EF=BC=8C=E5=8F=AF=E4=BB=A5?= =?UTF-8?q?=E4=B8=8ETFE=E8=BF=9B=E8=A1=8C=E6=95=B0=E6=8D=AE=E4=BA=A4?= =?UTF-8?q?=E4=BA=92=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Makefile | 29 + kni.c | 1380 +++++++++++++++++++++++++++++++++++++++++++++ kni.h | 228 ++++++++ libforge_socket.c | 78 +++ libforge_socket.h | 9 + 5 files changed, 1724 insertions(+) create mode 100644 Makefile create mode 100644 kni.c create mode 100644 kni.h create mode 100644 libforge_socket.c create mode 100644 libforge_socket.h diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..422db9f --- /dev/null +++ b/Makefile @@ -0,0 +1,29 @@ +#CC = gcc +CC = g++ +CFLAGS = -g -Wall -fPIC -shared +OBJECTS = kni.o libforge_socket.o +TARGET = kni.so + +INCS = -I./inc +INCS += -I/opt/MESA/include/ +INCS += -I/opt/MESA/include/MESA +LD_DICTATOR =-L/opt/MESA/lib + +MODULES = -lMESA_htable -lMESA_prof_load -lMESA_handle_logger -lrulescan -lmaatframe -lpcre -lssl + + +.c.o: + $(CC) -c -o $@ $(CFLAGS) $(INCS) $< + +.PHONY: all clean +all: $(TARGET) +$(TARGET):$(OBJECTS) + $(CC) -o $(TARGET) $(CFLAGS) $(OBJECTS) $(MODULES) $(LD_DICTATOR) +# $(CC) -o $(TARGET) $(CFLAGS) $(OBJECTS) $(MODULES) -Wl,--whole-archive $(WHOLE_MODULES) -wL,--NO-WHOLE-ARCHIVE $(LD_DICTATOR) + +kni.o:kni.c +libforge_socket.o:libforge_socket.c + +clean: + rm -f $(TARGET) $(OBJECTS) + diff --git a/kni.c b/kni.c new file mode 100644 index 0000000..b584111 --- /dev/null +++ b/kni.c @@ -0,0 +1,1380 @@ +#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" + + +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); + } + + ret=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}; + int client_fd=0; + int server_fd=0; + + client_fd=socket(AF_INET, SOCK_FORGE, 0); + server_fd=socket(AF_INET, SOCK_FORGE, 0); + if (client_fd < 0 || server_fd< 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(client_fd,fake_server); + fs_set_state(server_fd,fake_client); + + fds[KNI_FDS_INDEX_CLIENT]=client_fd; + fds[KNI_FDS_INDEX_SERVER]=server_fd; + + + 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(client_socket); +// close(server_socket); + + 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 ) + { + 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 defines" +# endif + unsigned char th_flags; + unsigned short th_win; + unsigned short thsum; + unsigned short th_urp; +}; + +struct kni_tcp_opt +{ + char type; + char len; + char content[32]; +}; + + +#endif diff --git a/libforge_socket.c b/libforge_socket.c new file mode 100644 index 0000000..ef7b1c7 --- /dev/null +++ b/libforge_socket.c @@ -0,0 +1,78 @@ +#include +#include +#include +#include +#include "forge_socket.h" +#include +#include + +// TODO: one day, we should actually add a libforge_socket to the forge_socket/userspace + +// Fills in all but the src/dst ip/port and seq/ack numbers +// with some sane defaults +struct tcp_state *forge_socket_get_default_state() +{ + struct tcp_state *st; + st = (struct tcp_state *)malloc(sizeof(struct tcp_state)); + if (st == NULL) { + return NULL; + } + st->tstamp_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; + //make sure you set snd_una = seq (TODO: fix this in module) + + return st; +} + + +int forge_socket_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; + + // TODO: maybe not everyone wants this? + st->snd_una = st->seq; + +/* + // TOOD: do we need/want this? + if (setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, iface, strlen(iface)) < 0) { + perror("setsockopt SO_BINDTODEVICE"); + return -1; + } +*/ + + 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; +} + + + + diff --git a/libforge_socket.h b/libforge_socket.h new file mode 100644 index 0000000..fde3642 --- /dev/null +++ b/libforge_socket.h @@ -0,0 +1,9 @@ +#ifndef FORGE_SOCKET_H +#define FORGE_SOCKET_H +#include "forge_socket.h" + + +struct tcp_state *forge_socket_get_default_state(); +int forge_socket_set_state(int sock, struct tcp_state *st); + +#endif