tcp客户端在接收端C/TCP/RawSockets/Networking/Linux的数据包中获取不同的目的端口客户端地址

问题描述

我正在尝试使用原始套接字制作 tcp 服务器。通过这种方式,我可以了解更多关于 tcp 的信息。我的 tcp 服务器的问题是我在接收端(客户端)获得了不同的目标端口。服务器(源端口)正确,但目标端口不同。所以我的 telnet/nc 客户端一直在尝试连接。它无法连接并向拒绝连接的客户端提供错误。问题是我在目标系统上收到带有 SYN+ACK 的数据包,但端口不是客户端的源端口(我使用wireshark 在客户端上检查过)某些东西正在改变目标端口地址(客户端端口地址),或者我不是在原始套接字发送之前在原始服务器上正确分配它。我认为问题可能出在这条线上。我正在运行代码(客户端和服务器)在两个虚拟机 Linux 上

  temp->dest=tcp->source;

tcp 是服务器端从客户端接收到的数据包的 tcp 头 temp->dest 是从服务器向客户端发送数据包的 tcp 客户端端口地址

//下面是main方法,它监听请求

    // Packet length
    #define PCKT_LEN 8192


    int main(int argc,char *argv[])
    {
        int sd;
        char buffer[PCKT_LEN];
        int one = 1;
        const int *val = &one;
        memset(buffer,PCKT_LEN);
        sd = socket(PF_INET,SOCK_RAW,IPPROTO_TCP);
        if(sd < 0)
        {
        perror("socket() error");
        exit(-1);
        }
        else
        printf("socket()-SOCK_RAW and tcp protocol is OK.\n");
        if(setsockopt(sd,IPPROTO_IP,IP_HDRINCL,val,sizeof(one)) < 0)
        {
        perror("setsockopt() error");
        exit(-1);
        }
        else
        printf("setsockopt() is OK\n");
        struct sockaddr_in sa;
        sa.sin_family=AF_INET;
        sa.sin_port=htons(80);
        sa.sin_addr.s_addr=inet_addr("0.0.0.0");
        if(bind(sd,&sa,sizeof (sa))==0){
            printf("Port Bound\n");
        }
        unsigned int count;

        while(1)

        {
             char buffer1[8192];
             struct sockaddr_in saddr;
             int in_len;
            if((recvfrom(sd,buffer1,sizeof (buffer1),&saddr,&in_len))!=-1){
               connect1(saddr,buffer1);
               sleep(5);

            }//if recvfrom()
            else{
            int err=errno;
            printf("recv error %s\n",errno);
            }

            sleep(2);


        }

        close(sd);

        return 0;

    }

//下面是发送响应(ACK+SYN)的方法

    #define PCKT_LEN 100
    void processBuffer(char buffer1[]);
    int connect1(struct sockaddr_in sa,char buffer[]) {
        printf("Connecting client...!\n");

        char *c=inet_ntoa(sa.sin_addr);
       // processBuffer(buffer);
        int cp=ntohl(sa.sin_port);
        printf("%s  (%d)\n",c,cp);
        struct iphdr *ip1=(struct iphdr *)buffer;
        struct tcphdr *tcp=(struct tcphdr *)buffer;
        sa.sin_port=tcp->source;
        printf("%d %d --------- \n",tcp->source,ntohl(tcp->source));
        printf("%d \n",ntohs(sa.sin_port));
      int sd;

        int one = 1;
        const int *val = &one;

       sd = socket(PF_INET,IPPROTO_TCP);


        if(sd < 0)
        {
        perror("Connecting --socket() error");
        exit(-1);
        }
        else
        printf("socket()-SOCK_RAW and tcp protocol is OK.\n");
        if(setsockopt(sd,sizeof(one)) < 0)
        {
        perror("Connecting--setsockopt() error");
        exit(-1);
        }
        else
        printf("Connecting setsockopt() is OK\n");


        if(bind(sd,sizeof (sa))==0){
        printf("Port Bound\n");
        }
        char b[PCKT_LEN];
        struct iphdr *i=(struct iphdr *)b;
        struct tcphdr *t=(struct tcphdr *)(b+sizeof (struct iphdr));
        ip(ip1,i);
        sync_ack(tcp,t);
        int ret=sendto(sd,&b,sizeof (b),sizeof (sa));
        strerror("Error: ");
     printf("%d\n",errno);

        printf("%d\n",ret);

        return 0;
    }

//这就是我制作ip header的方式

      int id=121333;
      struct iphdr * ip(struct iphdr * ip,struct iphdr *temp)
        {
        temp->saddr=ip->daddr;
        temp->daddr=ip->saddr;
        temp->ihl=5;
        temp->version=4;
        temp->tos=0;
        temp->tot_len = sizeof (struct ip) + sizeof (struct tcphdr);
        temp->id=htons(id);id++;
        temp->frag_off = htons(16384);
        temp->ttl = 64;
        temp->protocol=IPPROTO_TCP;
        temp->check=0;
        temp->check = csum ((unsigned short *) temp,temp->tot_len >> 1);
        return temp;
    }

//接下来是我正在制作tcp header ACK+SYN

      int seq=1105024978; 
      struct tcphdr * sync_ack(struct tcphdr * tcp,struct tcphdr *temp)
        {

        temp->source=htonl(80);
        temp->dest=tcp->source;
        temp->seq=htonl(seq);seq++;
        temp->ack_seq=htonl(ntohl(tcp->seq)+1);
        temp->doff = sizeof(struct tcphdr) / 4;
        temp->fin=0;
        temp->syn=1;
        temp->ack=1;
        temp->th_ack=tcp->seq;
        temp->rst=0;
        temp->psh=0;
        temp->urg=0;
        temp->window=htons ( 14600 );
        temp->check = 0;
        temp->urg_ptr = 0;
        temp->check = csum( (unsigned short*) temp,sizeof (struct tcphdr));

        return temp;
    }

请检查代码有什么问题。我将处理重新传输,但我没有通过第一个数据包进入正确的端口地址。任何帮助将不胜感激

我在 Linux(特别是 Debian 5.9 版操作系统)上运行它

我之前就这个作品问过一个问题。 DOES router or linux kernel change the tcp headers and ip headers of packets 我怀疑这条线

  temp->dest=tcp->source;

这是在服务器收到的wireshark信息,0.11是客户端ip,0.14是服务器ip。 80是服务器端口

enter image description here

enter image description here

这是客户端的wireshark

enter image description here

iptables 更改后,syn+ack 正在发送,但客户端收到的数据包中的客户端端口不同。客户端端口线鲨鱼显示60 和之前问题更新图片

 # iptables -A OUTPUT -p tcp --tcp-flags RST RST -j DROP

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)