006.udp转发包并代理访问服务器总结

摘要:
当游戏服务器回应数据后,同样再次将数据封装成一个完整的udp的IP数据包,填入相应的服务器IP,服务器端口,客户端IP,客户端端口,将这个数据包作为数据发给client_server4.client_server将完整的数据包发给游戏服务器。

背景:

当加速器(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

程序的流程图:

006.udp转发包并代理访问服务器总结第1张

其中:

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部分:

006.udp转发包并代理访问服务器总结第2张006.udp转发包并代理访问服务器总结第3张
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[], intsend_buf_len, uint32_t src_ip, u_int16_t src_port, uint32_t des_ip, u_int16_t des_port);
25 
26 
27 intmain()
28 {
29     intserver_sockfd;
30     charsend_message[MAXLINE];
31     charrecv_message[MAXLINE];
32     structsockaddr_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     intmesg_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(structiphdr));
55     structin_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 }
udp_client.c
006.udp转发包并代理访问服务器总结第4张006.udp转发包并代理访问服务器总结第5张
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, intlen);
31 u_int16_t udp_check(char *sendbuf, int len, const structudp_front front);
32 int make_message(char *mesg, char sendbuf[], intsend_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[], intsend_buf_len, uint32_t src_ip, u_int16_t src_port, uint32_t des_ip, u_int16_t des_port)
37 {
38     charmessage[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     structudp_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(structiphdr));
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 structudp_front front)
82 {
83     charstr[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, intlen)
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     returnanswer;
116 }
make_message.c

2.mid_server部分:

006.udp转发包并代理访问服务器总结第6张006.udp转发包并代理访问服务器总结第7张
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 intclient_port;
42 
43 extern u_int16_t in_chksum(u_int16_t *addr, intlen);
44 extern u_int16_t udp_check(char *sendbuf, int len, const structudp_front front);
45 extern int make_message(char *mesg, char sendbuf[], intsend_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, intsrc_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     structudp_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(structiphdr));
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, intlen)
73 {
74         structsockaddr_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 intmain()
85 {
86         int size = 1024*50;
87     intserver_len, client_len;
88     structsockaddr_in server_address;
89     structsockaddr_in client_address;
90 
91     //接收client_server端数据的套接字
92     //监听端口:8600
93     intserver_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     intraw_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     intend_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     charrecv_mesg[MAXLINE];
119     charsend_mesg[MAXLINE];
120     for( ; ; )
121 {
122                 intlen;
123                 client_len = sizeof(structsockaddr_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 }
udp_mid_server.c
006.udp转发包并代理访问服务器总结第8张006.udp转发包并代理访问服务器总结第9张
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, intlen);
31 u_int16_t udp_check(char *sendbuf, int len, const structudp_front front);
32 
33 
34 //拼接IP数据报
35 int make_message(char *mesg, char sendbuf[], intsend_buf_len, uint32_t src_ip, u_int16_t src_port, uint32_t des_ip, u_int16_t des_port)
36 {
37     charmessage[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     structudp_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(structiphdr));
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 structudp_front front)
81 {
82     charstr[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, intlen)
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     returnanswer;
115 }
make_message.c

3.end_srever部分:

006.udp转发包并代理访问服务器总结第10张006.udp转发包并代理访问服务器总结第11张
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 intmain()
26 {
27     intserver_sockfd;
28     charrecv_mesg[MAXLINE];
29     intserver_len, client_len;
30     structsockaddr_in server_address;
31     structsockaddr_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         intlen;
44         client_len = sizeof(structsockaddr_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 }
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

免责声明:文章转载自《006.udp转发包并代理访问服务器总结》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇Redis的cluster集群一起谈.NET技术,ASP.NET MVC3 基础教程 – Web Pages 1.0 狼人:下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

C语言基础:C语言指针(6)

上一节我们讲到了指针和数组, 这次我们来讲解一下指针和字符串, 这次的内容和上一节有相似的地方, 也有全新学习的地方, 让我们一起来看看吧~~下面我们来看一个小例子: #include <stdio.h> int main() { char name[] = "abcde"; name[0] = 'A';...

记一次ORACLE的UNDO表空间爆满分析过程

  这篇文章是记录一次ORACLE数据库UNDO表空间爆满的分析过程,主要整理、梳理了同事分析的思路。具体过程如下所示: 早上收到一数据库服务器的UNDO表空间的告警邮件,最早一封是7:55发出的(监控作业是15分钟一次),从告警邮件分析,好像是UNDO表空间突然一下子被耗尽了。   DB Tablespace Allocated Free Use...

2、Java数据类型框图和自动转化框图

Java数据类型 自动类型转化    特别注意:byte和char类型之间不能相互转换 1 C:Userslenovo>jshell 2 | 欢迎使用 JShell -- 版本 11.0.2 3 | 要大致了解该版本, 请键入: /help intro 4 5 jshell> byte a=1 6 a ==> 1 7...

go 创建携程池,开启并发

地址;https://github.com/panjf2000/ants 采用蚂蚁池开源的SDK,ants 是一个高性能且低损耗的 goroutine 池 package mainimport ("fmt""sync""sync/atomic""time""github.com/panjf2000/ants")var sum int32func myFun...

WireShark抓包分析(二)

简述:本文介绍了抓包数据含义,有TCP报文、Http报文、DNS报文。如有错误,欢迎指正。 1、TCP报文 TCP:(TCP是面向连接的通信协议,通过三次握手建立连接,通讯完成时要拆除连接,由于TCP 是面向连接的所以只能用于点对点的通讯)源IP地址:发送包的IP地址;目的IP地址:接收包的IP地址;源端口:源系统上的连接的端口;目的端口:目的系统上的连...

gprof的使用介绍

转于:http://blog.chinaunix.net/uid-25194149-id-3215487.html #不知道这是在哪里找的了,感谢各位~性能分析工具gprof介绍Ver:1.0目录1. GPROF介绍 42. 使用步骤 43. 使用举例 43.1 测试环境 43.2 测试代码 43.3 数据分析 53.3.1 flat profile模式...