背景:
当加速器(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\n",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数据包的内容:\n");
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\n",inet_ntoa(ad));
58 printf("src_port:%d\n",ntohs(udp->source));
59
60 ad.s_addr = ip->daddr;
61 printf("des_ip:%s\n",inet_ntoa(ad));
62 printf("des_port:%d\n",ntohs(udp->dest));
63 printf("data:%s\ndata len:%d\n",(recv_message+28),len);
64
65 close(server_sockfd);
66 return 0;
67 }
udp_client.c
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\n",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\n",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 }
make_message.c
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的包已经出发!\n");
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!\n");
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\n",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\n",recv_mesg,len);
137
138 //现在将end_server给我的包拼接好后发给client_server.
139 printf("client:%d\n",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 }
udp_mid_server.c
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\n",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\n",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 }
make_message.c
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!\n");
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\n", 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回应的包已经出发!\n");
53 }
54 return 0;
55 }
udp_end_server.c
监听中间服务器显示的结果:
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