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


    背景:

        当加速器(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 }
    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
    ",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 }
    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的包已经出发!
    ");
     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 }
    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
    ",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 }
    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!
    ");
    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

      

  • 相关阅读:
    nginx服务与nfs服务
    linux基础(3)
    Linux基础(4)
    Linux命令基础(2)
    Linux命令基础(1)
    HTML——表单验证、正则表达式、事件
    css修改鼠标指针的形状
    ajax请求tab切换重新渲染Echarts图表
    5种状态下的HTTP状态码
    vue&Angular&React的优缺点
  • 原文地址:https://www.cnblogs.com/ruo-yu/p/4983273.html
Copyright © 2020-2023  润新知