Browse Source

implemented mssfix

wangyu- 8 năm trước cách đây
mục cha
commit
ae735dee13
3 tập tin đã thay đổi với 181 bổ sung4 xóa
  1. 1 1
      UDPspeeder
  2. 7 1
      main.cpp
  3. 173 2
      tun_dev.cpp

+ 1 - 1
UDPspeeder

@@ -1 +1 @@
-Subproject commit 1e00ff7c8723b80e88f79a9dea4472bf99c6f07b
+Subproject commit bd323be9c4d5ae5827a2a961d27574622e3f7cf7

+ 7 - 1
main.cpp

@@ -52,6 +52,9 @@ static void print_help()
 //	printf("    --disable-xor         <number>        disable xor\n");
 
 	printf("developer options:\n");
+	printf("    --tun-mtu             <number >       mtu of the tun interface,most time you shouldnt change this\n");
+	printf("    --disable-mssfix      <number >       disable mssfix for tcp connection\n");
+	printf("    -i,--interval         imin:imax       similiar to -i above, but scatter randomly between imin and imax\n");
 	printf("    --fifo                <string>        use a fifo(named pipe) for sending commands to the running program, so that you\n");
 	printf("                                          can change fec encode parameters dynamically, check readme.md in repository for\n");
 	printf("                                          supported commands.\n");
@@ -114,7 +117,10 @@ int main(int argc, char *argv[])
 		sprintf(tun_dev,"tun%u",get_true_random_number()%1000);
 	}
 	mylog(log_info,"using interface %s\n",tun_dev);
-
+	/*if(tun_mtu==0)
+	{
+		tun_mtu=g_fec_mtu;
+	}*/
 	if(client_or_server==client_mode)
 	{
 		tun_dev_client_event_loop();

+ 173 - 2
tun_dev.cpp

@@ -10,6 +10,12 @@
 #include "log.h"
 #include "misc.h"
 
+#include <netinet/tcp.h>   //Provides declarations for tcp header
+#include <netinet/udp.h>
+#include <netinet/ip.h>    //Provides declarations for ip header
+#include <netinet/if_ether.h>
+
+
 my_time_t last_keep_alive_time=0;
 
 int keep_alive_interval=1000;//1000ms
@@ -148,6 +154,167 @@ int from_fec_to_normal2(conn_info_t & conn_info,dest_t &dest,char * data,int len
 
 	return 0;
 }
+int do_mssfix(char * s,int len)
+{
+	if(mssfix==0)
+	{
+		return 0;
+	}
+	if(len<20)
+	{
+		mylog(log_debug,"packet from tun len=%d <20\n",len);
+		return -1;
+	}
+	iphdr *  iph;
+	iph = (struct iphdr *) s;
+	if(iph->protocol!=IPPROTO_TCP)
+	{
+		//mylog(log_trace,"not tcp");
+		return 0;
+	}
+
+    if (!(iph->ihl > 0 && iph->ihl <=60)) {
+    	mylog(log_debug,"iph ihl error ihl= %u\n",(u32_t)iph->ihl);
+        return -1;
+    }
+    int ip_len=ntohs(iph->tot_len);
+    int ip_hdr_len=iph->ihl*4;
+    if(len<ip_hdr_len)
+    {
+    	mylog(log_debug,"len<ip_hdr_len,%d %d\n",len,ip_hdr_len);
+    	return -1;
+    }
+    if(len<ip_len)
+    {
+    	mylog(log_debug,"len<ip_len,%d %d\n",len,ip_len);
+    	return -1;
+    }
+    if(ip_hdr_len>ip_len)
+    {
+    	mylog(log_debug,"ip_hdr_len<ip_len,%d %d\n",ip_hdr_len,ip_len);
+    	return -1;
+    }
+
+    if( ( ntohs(iph->frag_off) &(short)(0x1FFF) ) !=0 )
+    {
+    	//not first segment
+
+    	//printf("line=%d %x  %x \n",__LINE__,(u32_t)ntohs(iph->frag_off),u32_t( ntohs(iph->frag_off) &0xFFF8));
+    	return 0;
+    }
+    if( ( ntohs(iph->frag_off) &(short)(0x80FF) )  !=0 )
+    {
+    	//not whole segment
+      	//printf("line=%d   \n",__LINE__);
+    	return 0;
+    }
+
+    char * tcp_begin=s+ip_hdr_len;
+    int tcp_len=ip_len-ip_hdr_len;
+
+    if(tcp_len<20)
+    {
+    	mylog(log_debug,"tcp_len<20,%d\n",tcp_len);
+    	return -1;
+    }
+
+    tcphdr * tcph=(struct tcphdr*)tcp_begin;
+
+    if(int(tcph->syn)==0)  //fast fail
+    {
+    	mylog(log_trace,"tcph->syn==0\n");
+    	return 0;
+    }
+
+    int tcp_hdr_len = tcph->doff*4;
+
+    if(tcp_len<tcp_hdr_len)
+    {
+    	mylog(log_debug,"tcp_len <tcp_hdr_len, %d %d\n",tcp_len,tcp_hdr_len);
+    	return -1;
+    }
+
+    /*
+    if(tcp_hdr_len==20)
+    {
+    	//printf("line=%d\n",__LINE__);
+    	mylog(log_trace,"no tcp option\n");
+    	return 0;
+    }*/
+
+    char *ptr=tcp_begin+20;
+    char *option_end=tcp_begin+tcp_hdr_len;
+    while(ptr<option_end)
+    {
+    	if(*ptr==0)
+    	{
+    		return  0;
+    	}
+    	else if(*ptr==1)
+    	{
+    		ptr++;
+    	}
+    	else if(*ptr==2)
+    	{
+    		if(ptr+1>=option_end)
+    		{
+    			mylog(log_debug,"invaild option ptr+1==option_end,for mss\n");
+    			return -1;
+    		}
+    		if(*(ptr+1)!=4)
+    		{
+    			mylog(log_debug,"invaild mss len\n");
+    			return -1;
+    		}
+    		if(ptr+3>=option_end)
+    		{
+    			mylog(log_debug,"ptr+4>option_end for mss\n");
+    			return -1;
+    		}
+    		int mss= read_u16(ptr+2);//uint8_t(ptr[2])*256+uint8_t(ptr[3]);
+    		int new_mss=mss;
+    		if(new_mss>g_fec_mtu-40)
+    		{
+    			new_mss=g_fec_mtu-40;
+    		}
+    		write_u16(ptr+2,(unsigned short)new_mss);
+
+    	    pseudo_header psh;
+
+    	    psh.source_address =iph->saddr;
+    	    psh.dest_address = iph->daddr;
+    	    psh.placeholder = 0;
+    	    psh.protocol = iph->protocol;
+    	    psh.tcp_length = htons(tcp_len);
+
+
+    	    tcph->check=0;
+    	    tcph->check=tcp_csum(psh,(unsigned short *)tcph,tcp_len);
+
+    		mylog(log_trace,"mss=%d  syn=%d ack=%d, changed mss to %d \n",mss,(int)tcph->syn,(int)tcph->ack,new_mss);
+
+    		//printf("test=%x\n",u32_t(1));
+    		//printf("frag=%x\n",u32_t( ntohs(iph->frag_off) ));
+
+    		return 0;
+    	}
+    	else
+    	{
+    		if(ptr+1>=option_end)
+    		{
+    			mylog(log_debug,"invaild option ptr+1==option_end\n");
+    			return -1;
+    		}
+    		else
+    		{
+    			//omit check
+    			ptr+=*(ptr+1);
+    		}
+    	}
+    }
+
+	return 0;
+}
 int do_keep_alive(dest_t & dest)
 {
 	if(get_current_time()-last_keep_alive_time>u64_t(keep_alive_interval))
@@ -180,7 +347,7 @@ int tun_dev_client_event_loop()
 	assert(new_connected_socket(remote_fd,remote_ip_uint32,remote_port)==0);
 	remote_fd64=fd_manager.create(remote_fd);
 
-	assert(set_if(tun_dev,htonl((ntohl(sub_net_uint32)&0xFFFFFF00)|2),htonl((ntohl(sub_net_uint32)&0xFFFFFF00 )|1),1500)==0);
+	assert(set_if(tun_dev,htonl((ntohl(sub_net_uint32)&0xFFFFFF00)|2),htonl((ntohl(sub_net_uint32)&0xFFFFFF00 )|1),tun_mtu)==0);
 
 	epoll_fd = epoll_create1(0);
 	assert(epoll_fd>0);
@@ -335,6 +502,8 @@ int tun_dev_client_event_loop()
 					continue;
 				}
 
+				do_mssfix(data,len);
+
 				mylog(log_trace,"Received packet from tun,len: %d\n",len);
 
 				char header=(got_feed_back==0?header_new_connect:header_normal);
@@ -449,7 +618,7 @@ int tun_dev_server_event_loop()
 	assert(tun_fd>0);
 
 	assert(new_listen_socket(local_listen_fd,local_ip_uint32,local_port)==0);
-	assert(set_if(tun_dev,htonl((ntohl(sub_net_uint32)&0xFFFFFF00)|1),htonl((ntohl(sub_net_uint32)&0xFFFFFF00 )|2),1500)==0);
+	assert(set_if(tun_dev,htonl((ntohl(sub_net_uint32)&0xFFFFFF00)|1),htonl((ntohl(sub_net_uint32)&0xFFFFFF00 )|2),tun_mtu)==0);
 
 	epoll_fd = epoll_create1(0);
 	assert(epoll_fd>0);
@@ -694,6 +863,8 @@ int tun_dev_server_event_loop()
 					continue;
 				}
 
+				do_mssfix(data,len);
+
 				mylog(log_trace,"Received packet from tun,len: %d\n",len);
 
 				if(udp_dest.inner.fd64_ip_port.ip_port.to_u64()==0)