From ee787e0d4a453c66712b2bae763ca8e23758a628 Mon Sep 17 00:00:00 2001 From: wangyu Date: Mon, 15 Jul 2019 08:36:06 -0400 Subject: [PATCH] added --fix-gro --- client.cpp | 145 +++++++++++++++++++++++++++---------------------- common.h | 8 ++- connection.cpp | 95 ++++++++++++++++++++++++++++---- connection.h | 7 ++- encrypt.cpp | 8 ++- encrypt.h | 3 +- makefile | 5 ++ misc.cpp | 5 ++ network.cpp | 21 ++++++- network.h | 1 - server.cpp | 29 +++++++--- 11 files changed, 234 insertions(+), 93 deletions(-) diff --git a/client.cpp b/client.cpp index ac5e40c..3876688 100644 --- a/client.cpp +++ b/client.cpp @@ -307,6 +307,77 @@ int client_on_timer(conn_info_t &conn_info) //for client. called when a timer is } return 0; } +int client_on_raw_recv_hs2_or_ready(conn_info_t &conn_info,char type,char *data,int data_len) +{ + packet_info_t &send_info=conn_info.raw_info.send_info; + packet_info_t &recv_info=conn_info.raw_info.recv_info; + + if(!recv_info.new_src_ip.equal(send_info.new_dst_ip)||recv_info.src_port!=send_info.dst_port) + { + mylog(log_warn,"unexpected adress %s %s %d %d,this shouldnt happen.\n",recv_info.new_src_ip.get_str1(),send_info.new_dst_ip.get_str2(),recv_info.src_port,send_info.dst_port); + return -1; + } + + if(conn_info.state.client_current_state==client_handshake2) + { + mylog(log_info,"changed state from to client_handshake2 to client_ready\n"); + conn_info.state.client_current_state=client_ready; + conn_info.last_hb_sent_time=0; + conn_info.last_hb_recv_time=get_current_time(); + conn_info.last_oppsite_roller_time=conn_info.last_hb_recv_time; + client_on_timer(conn_info); + } + if(data_len>=0&&type=='h') + { + mylog(log_debug,"[hb]heart beat received,oppsite_roller=%d\n",int(conn_info.oppsite_roller)); + conn_info.last_hb_recv_time=get_current_time(); + return 0; + } + else if(data_len>= int( sizeof(u32_t))&&type=='d') + { + mylog(log_trace,"received a data from fake tcp,len:%d\n",data_len); + + if(hb_mode==0) + conn_info.last_hb_recv_time=get_current_time(); + + u32_t tmp_conv_id; + memcpy(&tmp_conv_id,&data[0],sizeof(tmp_conv_id)); + tmp_conv_id=ntohl(tmp_conv_id); + + if(!conn_info.blob->conv_manager.c.is_conv_used(tmp_conv_id)) + { + mylog(log_info,"unknow conv %d,ignore\n",tmp_conv_id); + return 0; + } + + conn_info.blob->conv_manager.c.update_active_time(tmp_conv_id); + + //u64_t u64=conn_info.blob->conv_manager.c.find_data_by_conv(tmp_conv_id); + address_t tmp_addr=conn_info.blob->conv_manager.c.find_data_by_conv(tmp_conv_id); + + //sockaddr_in tmp_sockaddr={0}; + + //tmp_sockaddr.sin_family = AF_INET; + //tmp_sockaddr.sin_addr.s_addr=(u64>>32u); + + //tmp_sockaddr.sin_port= htons(uint16_t((u64<<32u)>>32u)); + + + int ret=sendto(udp_fd,data+sizeof(u32_t),data_len -(sizeof(u32_t)),0,(struct sockaddr *)&tmp_addr.inner,tmp_addr.get_len()); + + if(ret<0) + { + mylog(log_warn,"sento returned %d,%s,%02x,%s\n",ret,get_sock_error(),int(tmp_addr.get_type()),tmp_addr.get_str()); + //perror("ret<0"); + } + } + else + { + mylog(log_warn,"unknown packet,this shouldnt happen.\n"); + return -1; + } + return 0; +} int client_on_raw_recv(conn_info_t &conn_info) //called when raw fd received a packet. { char* data;int data_len; @@ -427,75 +498,21 @@ int client_on_raw_recv(conn_info_t &conn_info) //called when raw fd received a p } else if(conn_info.state.client_current_state==client_handshake2||conn_info.state.client_current_state==client_ready)//received heartbeat or data { - char type; - if(recv_safer(conn_info,type,data,data_len)!=0) + vector type_vec; + vector data_vec; + if(recv_safer_multi(conn_info,type_vec,data_vec)!=0) { mylog(log_debug,"recv_safer failed!\n"); return -1; } - if(!recv_info.new_src_ip.equal(send_info.new_dst_ip)||recv_info.src_port!=send_info.dst_port) - { - mylog(log_warn,"unexpected adress %s %s %d %d,this shouldnt happen.\n",recv_info.new_src_ip.get_str1(),send_info.new_dst_ip.get_str2(),recv_info.src_port,send_info.dst_port); - return -1; - } - if(conn_info.state.client_current_state==client_handshake2) - { - mylog(log_info,"changed state from to client_handshake2 to client_ready\n"); - conn_info.state.client_current_state=client_ready; - conn_info.last_hb_sent_time=0; - conn_info.last_hb_recv_time=get_current_time(); - conn_info.last_oppsite_roller_time=conn_info.last_hb_recv_time; - client_on_timer(conn_info); - } - if(data_len>=0&&type=='h') - { - mylog(log_debug,"[hb]heart beat received,oppsite_roller=%d\n",int(conn_info.oppsite_roller)); - conn_info.last_hb_recv_time=get_current_time(); - return 0; - } - else if(data_len>= int( sizeof(u32_t))&&type=='d') - { - mylog(log_trace,"received a data from fake tcp,len:%d\n",data_len); - if(hb_mode==0) - conn_info.last_hb_recv_time=get_current_time(); - - u32_t tmp_conv_id; - memcpy(&tmp_conv_id,&data[0],sizeof(tmp_conv_id)); - tmp_conv_id=ntohl(tmp_conv_id); - - if(!conn_info.blob->conv_manager.c.is_conv_used(tmp_conv_id)) - { - mylog(log_info,"unknow conv %d,ignore\n",tmp_conv_id); - return 0; - } - - conn_info.blob->conv_manager.c.update_active_time(tmp_conv_id); - - //u64_t u64=conn_info.blob->conv_manager.c.find_data_by_conv(tmp_conv_id); - address_t tmp_addr=conn_info.blob->conv_manager.c.find_data_by_conv(tmp_conv_id); - - //sockaddr_in tmp_sockaddr={0}; - - //tmp_sockaddr.sin_family = AF_INET; - //tmp_sockaddr.sin_addr.s_addr=(u64>>32u); - - //tmp_sockaddr.sin_port= htons(uint16_t((u64<<32u)>>32u)); - - - int ret=sendto(udp_fd,data+sizeof(u32_t),data_len -(sizeof(u32_t)),0,(struct sockaddr *)&tmp_addr.inner,tmp_addr.get_len()); - - if(ret<0) - { - mylog(log_warn,"sento returned %d,%s,%02x,%s\n",ret,get_sock_error(),int(tmp_addr.get_type()),tmp_addr.get_str()); - //perror("ret<0"); - } - } - else - { - mylog(log_warn,"unknown packet,this shouldnt happen.\n"); - return -1; - } + for(int i=0;i<(int)type_vec.size();i++) + { + char type=type_vec[i]; + char *data=(char *)data_vec[i].c_str(); //be careful, do not append data to it + int data_len=data_vec[i].length(); + client_on_raw_recv_hs2_or_ready(conn_info, type, data,data_len); + } return 0; } diff --git a/common.h b/common.h index b01b3a1..3390977 100644 --- a/common.h +++ b/common.h @@ -159,6 +159,8 @@ const int max_addr_len=100; extern int force_socket_buf; +extern int g_fix_gro; + /* struct ip_port_t { @@ -345,10 +347,12 @@ struct not_copy_able_t } }; - -const int max_data_len=1800; +const int single_max_data_len=1800; +const int max_data_len=single_max_data_len*10; const int buf_len=max_data_len+400; +//const int max_data_len_gro=max_data_len*10; +//const int buf_len_gro=max_data_len_gro+400; //const int max_address_len=512; u64_t get_current_time(); diff --git a/connection.cpp b/connection.cpp index 63e5654..d2b9d1b 100644 --- a/connection.cpp +++ b/connection.cpp @@ -11,8 +11,6 @@ int disable_anti_replay=0;//if anti_replay windows is diabled - - const int disable_conn_clear=0;//a raw connection is called conn. conn_manager_t conn_manager; @@ -462,12 +460,9 @@ int send_safer(conn_info_t &conn_info,char type,const char* data,int len) //saf } - char send_data_buf[buf_len]; //buf for send data and send hb char send_data_buf2[buf_len]; - - my_id_t n_tmp_id=htonl(conn_info.my_id); memcpy(send_data_buf,&n_tmp_id,sizeof(n_tmp_id)); @@ -488,10 +483,25 @@ int send_safer(conn_info_t &conn_info,char type,const char* data,int len) //saf int new_len=len+sizeof(n_seq)+sizeof(n_tmp_id)*2+2; - if(my_encrypt(send_data_buf,send_data_buf2,new_len)!=0) - { - return -1; - } + if(g_fix_gro==0) + { + if (my_encrypt(send_data_buf, send_data_buf2, new_len) != 0) + { + return -1; + } + } + else + { + if (my_encrypt(send_data_buf, send_data_buf2+2, new_len) != 0) + { + return -1; + } + write_u16(send_data_buf2,new_len); + send_data_buf2[0]^=gro_xor[0]; + send_data_buf2[1]^=gro_xor[1]; + new_len+=2; + } + if(send_raw0(conn_info.raw_info,send_data_buf2,new_len)!=0) return -1; @@ -602,19 +612,82 @@ int reserved_parse_safer(conn_info_t &conn_info,const char * input,int input_len return 0; } -int recv_safer(conn_info_t &conn_info,char &type,char* &data,int &len)///safer transfer function with anti-replay,when mutually verification is done. +int recv_safer_notused(conn_info_t &conn_info,char &type,char* &data,int &len)///safer transfer function with anti-replay,when mutually verification is done. { packet_info_t &send_info=conn_info.raw_info.send_info; packet_info_t &recv_info=conn_info.raw_info.recv_info; char * recv_data;int recv_len; - static char recv_data_buf[buf_len]; + //static char recv_data_buf[buf_len]; if(recv_raw0(conn_info.raw_info,recv_data,recv_len)!=0) return -1; return reserved_parse_safer(conn_info,recv_data,recv_len,type,data,len); } +int recv_safer_multi(conn_info_t &conn_info,vector &type_arr,vector &data_arr)///safer transfer function with anti-replay,when mutually verification is done. +{ + packet_info_t &send_info=conn_info.raw_info.send_info; + packet_info_t &recv_info=conn_info.raw_info.recv_info; + + char * recv_data;int recv_len; + assert(type_arr.empty()); + assert(data_arr.empty()); + + if(recv_raw0(conn_info.raw_info,recv_data,recv_len)!=0) return -1; + + char type; + char *data; + int len; + + if(g_fix_gro==0) + { + int ret = reserved_parse_safer(conn_info, recv_data, recv_len, type, data, len); + if(ret==0) + { + type_arr.push_back(type); + data_arr.emplace_back(data,data+len); + //std::copy(data,data+len,data_arr[0]); + } + return ret; + } else + { + while(recv_len>2) + { + recv_len-=2; + int single_len; + recv_data[0]^=gro_xor[0]; + recv_data[1]^=gro_xor[1]; + single_len=read_u16(recv_data); + recv_data+=2; + if(single_len > recv_len) + { + mylog(log_debug,"illegal single_len %d, recv_len %d left,dropped\n",single_len,recv_len); + break; + } + if(single_len> single_max_data_len ) + { + mylog(log_warn,"single_len %d > %d\n",single_len,single_max_data_len); + } + + int ret = reserved_parse_safer(conn_info, recv_data, single_len, type, data, len); + + if(ret!=0) + { + mylog(log_debug,"illegal single_len %d, recv_len %d left,dropped\n",single_len,recv_len); + } else{ + type_arr.push_back(type); + data_arr.emplace_back(data,data+len); + //std::copy(data,data+len,data_arr[data_arr.size()-1]); + } + recv_data+=single_len; + + } + return 0; + } +} + + void server_clear_function(u64_t u64)//used in conv_manager in server mode.for server we have to use one udp fd for one conv(udp connection), //so we have to close the fd when conv expires { diff --git a/connection.h b/connection.h index c8704aa..b581993 100644 --- a/connection.h +++ b/connection.h @@ -18,8 +18,6 @@ extern int disable_anti_replay; const int disable_conv_clear=0;//a udp connection in the multiplexer is called conversation in this program,conv for short. - - struct anti_replay_t //its for anti replay attack,similar to openvpn/ipsec 's anti replay window { u64_t max_packet_received; @@ -346,5 +344,8 @@ int send_handshake(raw_info_t &raw_info,my_id_t id1,my_id_t id2,my_id_t id3);// int send_safer(conn_info_t &conn_info,char type,const char* data,int len); //safer transfer function with anti-replay,when mutually verification is done. int send_data_safer(conn_info_t &conn_info,const char* data,int len,u32_t conv_num);//a wrap for send_safer for transfer data. //int reserved_parse_safer(conn_info_t &conn_info,const char * input,int input_len,char &type,char* &data,int &len);//subfunction for recv_safer,allow overlap -int recv_safer(conn_info_t &conn_info,char &type,char* &data,int &len);///safer transfer function with anti-replay,when mutually verification is done. + +//int recv_safer(conn_info_t &conn_info,char &type,char* &data,int &len);///safer transfer function with anti-replay,when mutually verification is done. + +int recv_safer_multi(conn_info_t &conn_info,vector &type_arr,vector &data_arr);//new api for handle gro #endif /* CONNECTION_H_ */ diff --git a/encrypt.cpp b/encrypt.cpp index c6f8063..7ee2e68 100755 --- a/encrypt.cpp +++ b/encrypt.cpp @@ -26,6 +26,8 @@ unsigned char hmac_key_decrypt[hmac_key_len + 100]; //key for hmac unsigned char cipher_key_encrypt[cipher_key_len + 100]; //key for aes etc. unsigned char cipher_key_decrypt[cipher_key_len + 100]; //key for aes etc. +char gro_xor[16+100];//dirty fix for gro + unordered_map auth_mode_tostring = {{auth_none, "none"}, {auth_md5, "md5"}, {auth_crc32, "crc32"},{auth_simple,"simple"},{auth_hmac_sha1,"hmac_sha1"},}; unordered_map cipher_mode_tostring={{cipher_none,"none"},{cipher_aes128cfb,"aes128cfb"},{cipher_aes128cbc,"aes128cbc"},{cipher_xor,"xor"},}; @@ -48,9 +50,10 @@ int my_init_keys(const char * user_passwd,int is_client) md5((uint8_t*)tmp,strlen(tmp),(uint8_t*)normal_key); + if(auth_mode==auth_hmac_sha1) is_hmac_used=1; - if(is_hmac_used) + if(is_hmac_used||g_fix_gro) { unsigned char salt[400]=""; char salt_text[400]="udp2raw_salt1"; @@ -82,6 +85,9 @@ int my_init_keys(const char * user_passwd,int is_client) assert( hkdf_sha256_expand( pbkdf2_output1,32, (unsigned char *)info_cipher_decrypt,strlen(info_cipher_decrypt), cipher_key_decrypt, cipher_key_len ) ==0); assert( hkdf_sha256_expand( pbkdf2_output1,32, (unsigned char *)info_hmac_encrypt,strlen(info_hmac_encrypt), hmac_key_encrypt, hmac_key_len ) ==0); assert( hkdf_sha256_expand( pbkdf2_output1,32, (unsigned char *)info_hmac_decrypt,strlen(info_hmac_decrypt), hmac_key_decrypt, hmac_key_len ) ==0); + + const char *gro_info="gro"; + assert( hkdf_sha256_expand( pbkdf2_output1,32, (unsigned char *)gro_info,strlen(gro_info), (unsigned char *)gro_xor, 16 ) ==0); } print_binary_chars(normal_key,16); diff --git a/encrypt.h b/encrypt.h index c9fd0d2..4bd556b 100755 --- a/encrypt.h +++ b/encrypt.h @@ -34,8 +34,7 @@ extern cipher_mode_t cipher_mode; extern unordered_map auth_mode_tostring; extern unordered_map cipher_mode_tostring; - - +extern char gro_xor[16+100]; int cipher_decrypt(const char *data,char *output,int &len,char * key);//internal interface ,exposed for test only int cipher_encrypt(const char *data,char *output,int &len,char * key);//internal interface ,exposed for test only diff --git a/makefile b/makefile index 387d74e..e758e68 100755 --- a/makefile +++ b/makefile @@ -8,6 +8,8 @@ cc_mips24kc_le=/toolchains/lede-sdk-17.01.2-ramips-mt7621_gcc-5.4.0_musl-1.1.16. cc_arm= /toolchains/arm-2014.05/bin/arm-none-linux-gnueabi-g++ #cc_arm=/toolchains/lede-sdk-17.01.2-brcm2708-bcm2708_gcc-5.4.0_musl-1.1.16_eabi.Linux-x86_64/staging_dir/toolchain-arm_arm1176jzf-s+vfp_gcc-5.4.0_musl-1.1.16_eabi/bin/arm-openwrt-linux-muslgnueabi-g++ #cc_bcm2708=/home/wangyu/raspberry/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian/bin/arm-linux-gnueabihf-g++ +cc_tmp= /home/wangyu/OpenWrt-SDK-15.05-x86-64_gcc-4.8-linaro_uClibc-0.9.33.2.Linux-x86_64/staging_dir/toolchain-x86_64_gcc-4.8-linaro_uClibc-0.9.33.2/bin/x86_64-openwrt-linux-uclibc-g++ + FLAGS= -std=c++11 -Wall -Wextra -Wno-unused-variable -Wno-unused-parameter -Wno-missing-field-initializers ${OPT} COMMON=main.cpp lib/md5.cpp lib/pbkdf2-sha1.cpp lib/pbkdf2-sha256.cpp encrypt.cpp log.cpp network.cpp common.cpp connection.cpp misc.cpp fd_manager.cpp client.cpp server.cpp -lpthread my_ev.cpp -isystem libev @@ -35,6 +37,9 @@ debug2: git_version dynamic: git_version ${cc_local} -o ${NAME}_$@ -I. ${SOURCES} ${FLAGS} -lrt -O3 +tmp:git_version + ${cc_tmp} -o ${NAME}_$@ -I. ${SOURCES} ${FLAGS} -lrt -lgcc_eh -static -O3 + mips24kc_be: git_version ${cc_mips24kc_be} -o ${NAME}_$@ -I. ${SOURCES} ${FLAGS} -lrt -lgcc_eh -static -O3 mips24kc_be_asm_aes: git_version diff --git a/misc.cpp b/misc.cpp index 60ea415..a317bad 100644 --- a/misc.cpp +++ b/misc.cpp @@ -298,6 +298,7 @@ void process_arg(int argc, char *argv[]) //process all options {"dev", required_argument, 0, 1}, {"dns-resolve", no_argument, 0, 1}, {"easy-tcp", no_argument, 0, 1}, + {"fix-gro", no_argument, 0, 1}, {NULL, 0, 0, 0} }; @@ -738,6 +739,10 @@ void process_arg(int argc, char *argv[]) //process all options use_tcp_dummy_socket=1; mylog(log_info,"--easy-tcp enabled, now a dummy tcp socket will be created for handshake and block rst\n"); } + else if(strcmp(long_options[option_index].name,"fix-gro")==0) + { + g_fix_gro=0; + } else { mylog(log_warn,"ignored unknown long option ,option_index:%d code:<%x>\n",option_index, optopt); diff --git a/network.cpp b/network.cpp index 3fbae28..41f3a18 100644 --- a/network.cpp +++ b/network.cpp @@ -9,6 +9,8 @@ #include "log.h" #include "misc.h" +int g_fix_gro=1; + int raw_recv_fd=-1; int raw_send_fd=-1; u32_t link_level_header_len=0;//set it to 14 if SOCK_RAW is used in socket(PF_PACKET, SOCK_RAW, htons(ETH_P_IP)); @@ -839,10 +841,27 @@ int pre_recv_raw_packet() if(g_packet_buf_len==max_data_len+1) { - mylog(log_warn,"huge packet, data_len > %d,dropped\n",max_data_len); + mylog(log_warn,"huge packet, data_len %d > %d(max_data_len),dropped\n",g_packet_buf_len,max_data_len); return -1; } + if(g_packet_buf_len> single_max_data_len+1) + { + if(g_fix_gro==0) + { + mylog(log_warn, "huge packet, data_len %d > %d(single_max_data_len) dropped\n", g_packet_buf_len, + single_max_data_len); + return -1; + } + else + { + mylog(log_debug, "huge packet, data_len %d > %d(single_max_data_len) dropped\n", g_packet_buf_len, + single_max_data_len); + return -1; + } + + } + if(g_packet_buf_len<0) { mylog(log_trace,"recv_len %d\n",g_packet_buf_len); diff --git a/network.h b/network.h index 5d925e1..f2ea947 100644 --- a/network.h +++ b/network.h @@ -31,7 +31,6 @@ extern char g_packet_buf[buf_len]; extern int g_packet_buf_len; extern int g_packet_buf_cnt; - struct my_iphdr { #ifdef UDP2RAW_LITTLE_ENDIAN diff --git a/server.cpp b/server.cpp index 50e8e29..b1cb859 100644 --- a/server.cpp +++ b/server.cpp @@ -411,7 +411,10 @@ int server_on_raw_recv_handshake1(conn_info_t &conn_info,char * ip_port,char * d } return 0; } - +int server_on_recv_safer_multi(conn_info_t &conn_info,char type,char *data,int data_len) +{ + return 0; +} int server_on_raw_recv_multi() //called when server received an raw packet { char dummy_buf[buf_len]; @@ -590,13 +593,23 @@ int server_on_raw_recv_multi() //called when server received an raw packet } if(conn_info.state.server_current_state==server_ready) { - char type; - //mylog(log_info,"before recv_safer\n"); - if (recv_safer(conn_info,type, data, data_len) != 0) { - return -1; - } - //mylog(log_info,"after recv_safer\n"); - return server_on_raw_recv_ready(conn_info,ip_port,type,data,data_len); + vector type_vec; + vector data_vec; + if(recv_safer_multi(conn_info,type_vec,data_vec)!=0) + { + mylog(log_debug,"recv_safer failed!\n"); + return -1; + } + + for(int i=0;i<(int)type_vec.size();i++) + { + char type=type_vec[i]; + char *data=(char *)data_vec[i].c_str(); //be careful, do not append data to it + int data_len=data_vec[i].length(); + server_on_raw_recv_ready(conn_info,ip_port,type,data,data_len); + } + return 0; + } if(conn_info.state.server_current_state==server_idle)