背景:
当加速器(client)拦截了游戏客户端发送的完整数据包(package)时,将package传给中间服务器(mid_server),经过自己的链路传输数据之后,中间服务器模拟游戏客户端将数据发给游戏服务器(end_server),目的服务器收到请求后回应,回应的包以同样的方式返回,直到游戏客户端收到数据包。
原理及实现:
1.我们需要三个主机来模拟这个请求:
client_server: IP:192.168.11.104
mid_server: IP:192.168.11.105
end_server: IP:192.168.11.106
程序的流程图:
其中:
1.client_server只是充当普通的udp客户端,不同的是我们发送的数据是一个完整的udp类型的IP数据包
2.end_server模拟的是一台普通的游戏服务器,当有客户请求的时候,它就会回应
3.mid_server代替游戏客户端的请求,将数据包中替换了请求IP和port后发给游戏服务器,获得服务。
当游戏服务器回应数据后,同样再次将数据封装成一个完整的udp的IP数据包,填入相应的服务器IP,服务器端口,客户端IP,客户端端口,将这个数据包作为数据发给client_server
4.client_server将完整的数据包发给游戏服务器。
代码实现:
1.client_server部分:
1 /* 2 ============================================================================ 3 Name : udp_client.c 4 Author : huh 5 Version : 6 Copyright : ---notice--- 7 Description : Hello World in C, Ansi-style 8 ============================================================================ 9 */ 10 11 #include <sys/types.h> 12 #include <sys/socket.h> 13 #include <stdio.h> 14 #include <netinet/in.h> 15 #include <arpa/inet.h> 16 #include <unistd.h> 17 #include <stdlib.h> 18 #include <string.h> 19 #include <netinet/ip_icmp.h> 20 #include <netinet/udp.h> 21 22 #define MAXLINE 1024*10 23 24 int make_message(char *mesg, char sendbuf[], int send_buf_len, uint32_t src_ip, u_int16_t src_port, uint32_t des_ip, u_int16_t des_port); 25 26 27 int main() 28 { 29 int server_sockfd; 30 char send_message[MAXLINE]; 31 char recv_message[MAXLINE]; 32 struct sockaddr_in server_address; 33 34 server_sockfd = socket(AF_INET, SOCK_DGRAM, 0); 35 36 bzero(&server_address,sizeof(server_address)); 37 server_address.sin_family = AF_INET; 38 server_address.sin_addr.s_addr = inet_addr("192.168.11.105"); 39 server_address.sin_port = htons(8600); 40 41 int mesg_len; 42 bzero(&send_message, MAXLINE); 43 mesg_len = make_message("hello world!", send_message, MAXLINE, inet_addr("192.168.11.104"), 2525, inet_addr("192.168.11.106"), 8686); 44 45 //printf("send message len:%d ",strlen(send_message)); 46 sendto(server_sockfd, send_message, mesg_len, 0, (struct sockaddr *)&server_address, sizeof(server_address)); //将包发出去 47 48 bzero(&recv_message, sizeof(recv_message)); 49 int len = recvfrom(server_sockfd, recv_message, MAXLINE, 0, NULL, NULL); 50 printf("当前收到的IP数据包的内容: "); 51 struct iphdr *ip; 52 ip = (struct iphdr *)recv_message; 53 struct udphdr *udp; 54 udp = (struct udphdr *)(recv_message + sizeof(struct iphdr)); 55 struct in_addr ad; 56 ad.s_addr = ip->saddr; 57 printf("src_ip:%s ",inet_ntoa(ad)); 58 printf("src_port:%d ",ntohs(udp->source)); 59 60 ad.s_addr = ip->daddr; 61 printf("des_ip:%s ",inet_ntoa(ad)); 62 printf("des_port:%d ",ntohs(udp->dest)); 63 printf("data:%s data len:%d ",(recv_message+28),len); 64 65 close(server_sockfd); 66 return 0; 67 }
1 /* 2 * make_message.c 3 * 4 * Created on: 2015年11月18日 5 * Author: root 6 */ 7 8 #include <sys/types.h> 9 #include <sys/socket.h> 10 #include <stdio.h> 11 #include <netinet/in.h> 12 #include <arpa/inet.h> 13 #include <unistd.h> 14 #include <stdlib.h> 15 #include <string.h> 16 #include <netinet/ip_icmp.h> 17 #include <netinet/udp.h> 18 19 #define MAXLINE 1024*10 20 21 struct udp_front //udp 22 { 23 uint32_t srcip; 24 uint32_t desip; 25 u_int8_t zero; 26 u_int8_t protocol; 27 u_int16_t len; 28 }; 29 30 u_int16_t in_chksum(u_int16_t *addr, int len); 31 u_int16_t udp_check(char *sendbuf, int len, const struct udp_front front); 32 int make_message(char *mesg, char sendbuf[], int send_buf_len, uint32_t src_ip, u_int16_t src_port, uint32_t des_ip, u_int16_t des_port); 33 34 35 //拼接IP数据报 36 int make_message(char *mesg, char sendbuf[], int send_buf_len, uint32_t src_ip, u_int16_t src_port, uint32_t des_ip, u_int16_t des_port) 37 { 38 char message[MAXLINE]; 39 bzero(message, sizeof(message)); 40 strcpy(message,mesg); 41 printf("message len:%d ",strlen(message)); 42 struct iphdr *ip; 43 ip = (struct iphdr *)sendbuf; 44 ip->ihl = sizeof(struct iphdr) >> 2; //首部长度 45 ip->version = 4; //ip协议版本 46 ip->tos = 0; //服务类型字段 47 ip->tot_len = 0; //总长度 48 ip->id = 1000; // 49 ip->frag_off = 0; 50 ip->ttl = 128; 51 ip->protocol = IPPROTO_UDP; 52 ip->check = 0; //内核会算相应的效验和 53 ip->saddr = src_ip; 54 ip->daddr = des_ip; 55 56 struct udp_front front; 57 front.srcip = src_ip; 58 front.desip = des_ip; 59 front.len = htons(8+strlen(message)); 60 front.protocol = 17; 61 front.zero = 0; 62 63 struct udphdr *udp; 64 udp = (struct udphdr *)(sendbuf + sizeof(struct iphdr)); 65 udp->source = htons(src_port); //源端口 66 udp->dest = htons(des_port); //目的端口 67 udp->check = 0; //效验和,效验整个udp数据报 68 strcpy((sendbuf+20+8), message); 69 udp->len = htons(8+strlen(message)); //udp数据报总长度 70 71 udp->check = udp_check((sendbuf+20), 8+strlen(message), front); 72 73 ip->tot_len = (20 + 8 + strlen(message)); //总长度 74 printf("ip->tot_len:%d ",ip->tot_len); 75 ip->check = in_chksum((unsigned short *)sendbuf, 20); 76 77 return (ip->tot_len); 78 } 79 80 //计算udp效验和 81 unsigned short udp_check(char *sendbuf, int len, const struct udp_front front) 82 { 83 char str[MAXLINE]; 84 bzero(&str, MAXLINE); 85 bcopy(&front, str, sizeof(front)); 86 bcopy(sendbuf, str+sizeof(front), len); 87 struct udp_front *ptr; 88 ptr = (struct udp_front *)str; 89 char *s; 90 s = (str+20); 91 return in_chksum((unsigned short *)str, sizeof(front)+len); 92 } 93 94 //效验和算法 95 uint16_t in_chksum(uint16_t *addr, int len) 96 { 97 int nleft = len; 98 uint32_t sum = 0; 99 uint16_t *w = addr; 100 uint16_t answer = 0; 101 //把ICMP报头二进制数据以2字节为单位累加起来 102 while (nleft > 1) 103 { 104 sum += *w++; 105 nleft -= 2; 106 } 107 if (nleft == 1) 108 { 109 *(unsigned char *)(&answer) = *(unsigned char *)w; 110 sum += answer; 111 } 112 sum = (sum>>16) + (sum&0xffff); 113 sum += (sum>>16); 114 answer = ~sum; 115 return answer; 116 }
2.mid_server部分:
1 /* 2 ============================================================================ 3 Name : udp_mid_server.c 4 Author : huh 5 Version : 6 Copyright : ---notice--- 7 Description : Hello World in C, Ansi-style 8 ============================================================================ 9 */ 10 11 #include <sys/types.h> 12 #include <sys/socket.h> 13 #include <stdio.h> 14 #include <netinet/in.h> 15 #include <arpa/inet.h> 16 #include <unistd.h> 17 #include <stdlib.h> 18 #include <string.h> 19 #include <netinet/ip_icmp.h> 20 #include <netinet/udp.h> 21 22 #define MAXLINE 1024*50 23 24 #define SERVER_IP "192.168.11.105" //本服务器IP 25 #define TO_CLI_PORT 8600 //本服务器监听client_server端口 26 #define TO_END_PORT 8601 //本服务器监听end_server端口 27 28 #define END_SERVER_IP "192.168.11.106" //end_server的ip 29 #define END_SERVER_PORT 8686 //end_server的port 30 31 struct udp_front //udp 32 { 33 uint32_t srcip; 34 uint32_t desip; 35 u_int8_t zero; 36 u_int8_t protocol; 37 u_int16_t len; 38 }; 39 40 uint32_t client_ip; 41 int client_port; 42 43 extern u_int16_t in_chksum(u_int16_t *addr, int len); 44 extern u_int16_t udp_check(char *sendbuf, int len, const struct udp_front front); 45 extern int make_message(char *mesg, char sendbuf[], int send_buf_len, uint32_t src_ip, u_int16_t src_port, uint32_t des_ip, u_int16_t des_port); 46 47 48 void change_src(char sendbuf[], int len, uint32_t src_ip, int src_port) 49 { 50 struct iphdr *ip; 51 ip = (struct iphdr *)sendbuf; 52 ip->check = 0; //内核会算相应的效验和 53 client_ip = ip->saddr; 54 ip->saddr = src_ip; 55 ip->check = in_chksum((unsigned short *)sendbuf, 20); 56 ; 57 struct udp_front front; 58 front.srcip = src_ip; 59 front.desip = ip->daddr; 60 front.len = htons(len-20); 61 front.protocol = 17; 62 front.zero = 0; 63 64 struct udphdr *udp; 65 udp = (struct udphdr *)(sendbuf + sizeof(struct iphdr)); 66 client_port = ntohs(udp->source); 67 udp->source = htons(src_port); //源端口 68 udp->check = 0; //效验和,效验整个udp数据报 69 udp->check = udp_check((sendbuf+20), len-20, front); 70 } 71 72 void send_1(int raw_sockfd, char *send_message, int len) 73 { 74 struct sockaddr_in server_addr; 75 bzero(&server_addr,sizeof(server_addr)); 76 server_addr.sin_family = AF_INET; 77 server_addr.sin_addr.s_addr = inet_addr(END_SERVER_IP); 78 79 change_src(send_message, len, inet_addr(SERVER_IP), TO_END_PORT); 80 sendto(raw_sockfd, send_message, len, 0, (struct sockaddr *) &server_addr, sizeof(server_addr)); //将包发出去 81 printf("前往end_server的包已经出发! "); 82 } 83 84 int main() 85 { 86 int size = 1024*50; 87 int server_len, client_len; 88 struct sockaddr_in server_address; 89 struct sockaddr_in client_address; 90 91 //接收client_server端数据的套接字 92 //监听端口:8600 93 int server_sockfd; 94 server_sockfd = socket(AF_INET, SOCK_DGRAM, 0); 95 bzero(&server_address,sizeof(server_address)); 96 server_address.sin_family = AF_INET; 97 server_address.sin_addr.s_addr = inet_addr(SERVER_IP); 98 server_address.sin_port = htons(TO_CLI_PORT); 99 server_len = sizeof(server_address); 100 bind(server_sockfd, (struct sockaddr *)&server_address, server_len); 101 102 //发送给end_server的原始套接字 103 int raw_sockfd; 104 raw_sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_UDP); 105 setsockopt(raw_sockfd, IPPROTO_IP, IP_HDRINCL, &size, sizeof(size)); 106 107 //接收end_server端数据的套接字 108 //监听端口:8601 109 int end_sockfd; 110 end_sockfd = socket(AF_INET, SOCK_DGRAM, 0); 111 bzero(&server_address,sizeof(server_address)); 112 server_address.sin_family = AF_INET; 113 server_address.sin_addr.s_addr = inet_addr(SERVER_IP); 114 server_address.sin_port = htons(TO_END_PORT); 115 server_len = sizeof(server_address); 116 bind(end_sockfd, (struct sockaddr *)&server_address, server_len); 117 118 char recv_mesg[MAXLINE]; 119 char send_mesg[MAXLINE]; 120 for( ; ; ) 121 { 122 int len; 123 client_len = sizeof(struct sockaddr_in); 124 printf("server waiting! "); 125 //接收来自client_server的包 126 bzero(&client_address, sizeof(client_address)); 127 len = recvfrom(server_sockfd, recv_mesg, MAXLINE, 0, (struct sockaddr *) &client_address, (socklen_t *) &client_len); 128 printf("来自client_server的IP数据包的长度为:%d ",len); 129 130 //将接收到的数据作为一个完整的IP包发给end_server 131 send_1(raw_sockfd, recv_mesg, len); 132 133 //接收来自end_server的回应包,并将数据存在recv_mesg里面 134 bzero(recv_mesg, sizeof(recv_mesg)); 135 len = recvfrom(end_sockfd, recv_mesg, MAXLINE, 0, NULL, NULL); 136 printf("收到来自end_server的应答:%s,长度:%d ",recv_mesg,len); 137 138 //现在将end_server给我的包拼接好后发给client_server. 139 printf("client:%d ",client_port); 140 bzero(send_mesg,sizeof(send_mesg)); 141 int mesg_len = make_message(recv_mesg, send_mesg, MAXLINE, inet_addr(END_SERVER_IP), END_SERVER_PORT, client_ip, client_port); 142 sendto(server_sockfd, send_mesg, mesg_len, 0, (struct sockaddr *) &client_address, client_len); 143 144 } 145 return 0; 146 }
1 /* 2 * make_message.c 3 * 4 * Created on: 2015年11月18日 5 * Author: root 6 */ 7 8 #include <sys/types.h> 9 #include <sys/socket.h> 10 #include <stdio.h> 11 #include <netinet/in.h> 12 #include <arpa/inet.h> 13 #include <unistd.h> 14 #include <stdlib.h> 15 #include <string.h> 16 #include <netinet/ip_icmp.h> 17 #include <netinet/udp.h> 18 19 #define MAXLINE 1024*10 20 21 struct udp_front //udp 22 { 23 uint32_t srcip; 24 uint32_t desip; 25 u_int8_t zero; 26 u_int8_t protocol; 27 u_int16_t len; 28 }; 29 30 u_int16_t in_chksum(u_int16_t *addr, int len); 31 u_int16_t udp_check(char *sendbuf, int len, const struct udp_front front); 32 33 34 //拼接IP数据报 35 int make_message(char *mesg, char sendbuf[], int send_buf_len, uint32_t src_ip, u_int16_t src_port, uint32_t des_ip, u_int16_t des_port) 36 { 37 char message[MAXLINE]; 38 bzero(message, sizeof(message)); 39 strcpy(message,mesg); 40 printf("message len:%d ",strlen(message)); 41 struct iphdr *ip; 42 ip = (struct iphdr *)sendbuf; 43 ip->ihl = sizeof(struct iphdr) >> 2; //首部长度 44 ip->version = 4; //ip协议版本 45 ip->tos = 0; //服务类型字段 46 ip->tot_len = 0; //总长度 47 ip->id = 1000; // 48 ip->frag_off = 0; 49 ip->ttl = 128; 50 ip->protocol = IPPROTO_UDP; 51 ip->check = 0; //内核会算相应的效验和 52 ip->saddr = src_ip; 53 ip->daddr = des_ip; 54 55 struct udp_front front; 56 front.srcip = src_ip; 57 front.desip = des_ip; 58 front.len = htons(8+strlen(message)); 59 front.protocol = 17; 60 front.zero = 0; 61 62 struct udphdr *udp; 63 udp = (struct udphdr *)(sendbuf + sizeof(struct iphdr)); 64 udp->source = htons(src_port); //源端口 65 udp->dest = htons(des_port); //目的端口 66 udp->check = 0; //效验和,效验整个udp数据报 67 strcpy((sendbuf+20+8), message); 68 udp->len = htons(8+strlen(message)); //udp数据报总长度 69 70 udp->check = udp_check((sendbuf+20), 8+strlen(message), front); 71 72 ip->tot_len = (20 + 8 + strlen(message)); //总长度 73 printf("ip->tot_len:%d ",ip->tot_len); 74 ip->check = in_chksum((unsigned short *)sendbuf, 20); 75 76 return (ip->tot_len); 77 } 78 79 //计算udp效验和 80 unsigned short udp_check(char *sendbuf, int len, const struct udp_front front) 81 { 82 char str[MAXLINE]; 83 bzero(&str, MAXLINE); 84 bcopy(&front, str, sizeof(front)); 85 bcopy(sendbuf, str+sizeof(front), len); 86 struct udp_front *ptr; 87 ptr = (struct udp_front *)str; 88 char *s; 89 s = (str+20); 90 return in_chksum((unsigned short *)str, sizeof(front)+len); 91 } 92 93 //效验和算法 94 uint16_t in_chksum(uint16_t *addr, int len) 95 { 96 int nleft = len; 97 uint32_t sum = 0; 98 uint16_t *w = addr; 99 uint16_t answer = 0; 100 //把ICMP报头二进制数据以2字节为单位累加起来 101 while (nleft > 1) 102 { 103 sum += *w++; 104 nleft -= 2; 105 } 106 if (nleft == 1) 107 { 108 *(unsigned char *)(&answer) = *(unsigned char *)w; 109 sum += answer; 110 } 111 sum = (sum>>16) + (sum&0xffff); 112 sum += (sum>>16); 113 answer = ~sum; 114 return answer; 115 }
3.end_srever部分:
1 /* 2 ============================================================================ 3 Name : udp_end_server.c 4 Author : huh 5 Version : 6 Copyright : ---notice--- 7 Description : Hello World in C, Ansi-style 8 ============================================================================ 9 */ 10 11 #include <sys/types.h> 12 #include <sys/socket.h> 13 #include <stdio.h> 14 #include <netinet/in.h> 15 #include <arpa/inet.h> 16 #include <unistd.h> 17 #include <stdlib.h> 18 #include <string.h> 19 20 #define MAXLINE 1024*50 21 22 #define SERVER_IP "192.168.11.106" //本服务器IP 23 #define SERVER_PORT 8686 //本服务器监听端口 24 25 int main() 26 { 27 int server_sockfd; 28 char recv_mesg[MAXLINE]; 29 int server_len, client_len; 30 struct sockaddr_in server_address; 31 struct sockaddr_in client_address; 32 33 server_sockfd = socket(AF_INET, SOCK_DGRAM, 0); 34 server_address.sin_family = AF_INET; 35 server_address.sin_addr.s_addr = inet_addr(SERVER_IP); 36 server_address.sin_port = htons(SERVER_PORT); 37 server_len = sizeof(server_address); 38 bind(server_sockfd, (struct sockaddr *)&server_address, server_len); 39 40 //我们会将收到的数据加上"by end server!",再返回给客户端 41 while(1) 42 { 43 int len; 44 client_len = sizeof(struct sockaddr_in); 45 printf("end server waiting! "); 46 bzero(recv_mesg, sizeof(recv_mesg)); 47 len = recvfrom(server_sockfd, recv_mesg, MAXLINE, 0, (struct sockaddr *) &client_address, (socklen_t *) &client_len); 48 printf("收到mid_server包的长度为:%d,内容为:%s ", len, recv_mesg); 49 strcpy(recv_mesg+len," by end_server!"); 50 len = strlen(recv_mesg); 51 sendto(server_sockfd, recv_mesg, len, 0, (struct sockaddr *) &client_address, client_len); //将包发出去 52 printf("往mid_server回应的包已经出发! "); 53 } 54 return 0; 55 }
监听中间服务器显示的结果:
1 [root@mid_server ~]# tcpdump -nn udp and host 192.168.11.105 2 tcpdump: verbose output suppressed, use -v or -vv for full protocol decode 3 listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes 4 22:25:24.085794 IP 192.168.11.104.45375 > 192.168.11.105.8600: UDP, length 40 5 22:25:24.086092 IP 192.168.11.105.8601 > 192.168.11.106.8686: UDP, length 12 6 22:25:24.086632 IP 192.168.11.106.8686 > 192.168.11.105.8601: UDP, length 27 7 22:25:24.086891 IP 192.168.11.105.8600 > 192.168.11.104.45375: UDP, length 55