Linux C 原始套接字 TCP 握手

Fra*_*ank 5 c tcp

我正在尝试使用 C 中的原始套接字(在 Debian 系统上)创建 TCP 连接,但我很难让它工作。它会发送一个数据包,但我没有从服务器得到任何响应。我已经测试并比较了该数据包与从 nmap 发送的数据包,我看不到任何重大差异。

\n\n

这是服务器端收到的TCP数据包,服务器端从不发送SYN ACK数据包(我在服务器端使用Wireshark进行监控)

\n\n
No.     Time           Source                Destination           Protocol Length Info\n     75 1.893700000    192.168.1.129         192.168.1.114         TCP      74         56540\xe2\x86\x92445 [SYN] Seq=0 Win=1024 Len=0 MSS=1460 SACK_PERM=1 WS=128 TSval=863195 TSecr=0\n\nFrame 75: 74 bytes on wire (592 bits), 74 bytes captured (592 bits) on interface 0\nEthernet II, Src: Vmware_77:f0:a0 (00:0c:29:77:f0:a0), Dst: IntelCor_07:f9:e5     (e8:b1:fc:07:f9:e5)\nInternet Protocol Version 4, Src: 192.168.1.129 (192.168.1.129), Dst: 192.168.1.114 (192.168.1.114)\nVersion: 4\nHeader Length: 20 bytes\nDifferentiated Services Field: 0x00 (DSCP 0x00: Default; ECN: 0x00: Not-ECT (Not ECN-Capable Transport))\nTotal Length: 60\nIdentification: 0xb88d (47245)\nFlags: 0x00\nFragment offset: 0\nTime to live: 255\nProtocol: TCP (6)\nHeader checksum: 0x7eea [validation disabled]\nSource: 192.168.1.129 (192.168.1.129)\nDestination: 192.168.1.114 (192.168.1.114)\n[Source GeoIP: Unknown]\n[Destination GeoIP: Unknown]\nTransmission Control Protocol, Src Port: 56540 (56540), Dst Port: 445 (445), Seq: 0, Len: 0\nSource Port: 56540 (56540)\nDestination Port: 445 (445)\n[Stream index: 3]\n[TCP Segment Len: 0]\nSequence number: 0    (relative sequence number)\nAcknowledgment number: 0\nHeader Length: 40 bytes\n.... 0000 0000 0010 = Flags: 0x002 (SYN)\nWindow size value: 1024\n[Calculated window size: 1024]\nChecksum: 0x7ff8 [validation disabled]\nUrgent pointer: 0\nOptions: (20 bytes), Maximum segment size, SACK permitted, Window scale, No-Operation (NOP), Timestamps\n    Maximum segment size: 1460 bytes\n        Kind: Maximum Segment Size (2)\n        Length: 4\n        MSS Value: 1460\n    TCP SACK Permitted Option: True\n        Kind: SACK Permitted (4)\n        Length: 2\n    Window scale: 7 (multiply by 128)\n        Kind: Window Scale (3)\n        Length: 3\n        Shift count: 7\n        [Multiplier: 128]\n    No-Operation (NOP)\n        Type: 1\n    Timestamps: TSval 863195, TSecr 0\n        Kind: Time Stamp Option (8)\n        Length: 10\n        Timestamp value: 863195\n        Timestamp echo reply: 0\n\n0000  e8 b1 fc 07 f9 e5 00 0c 29 77 f0 a0 08 00 45 00   ........)w....E.\n0010  00 3c b8 8d 00 00 ff 06 7e ea c0 a8 01 81 c0 a8   .<......~.......\n0020  01 72 dc dc 01 bd db 0f 13 02 00 00 00 00 a0 02   .r..............\n0030  04 00 7f f8 00 00 02 04 05 b4 04 02 03 03 07 01   ................\n0040  08 0a 00 0d 2b db 00 00 00 00                     ....+.....\n
Run Code Online (Sandbox Code Playgroud)\n\n

这是我的代码,我知道它很混乱,我只是想学习如何使用原始套接字

\n\n
#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <sys/types.h>\n#include <sys/socket.h>\n#include <netdb.h>\n#include <arpa/inet.h>\n#include <netinet/in.h>\n#include <unistd.h>\n#include <time.h>\n\nstruct ipheader {\n unsigned char          iph_ihl:4, /* Little-endian */\n                        iph_ver:4;\n unsigned char          iph_tos;\n unsigned short int     iph_len;\n unsigned short int     iph_ident;\n unsigned short int     iph_offset:13,  /* Little-endian*/\n                        iph_flags:3;\n unsigned char          iph_ttl;\n unsigned char          iph_protocol;\n unsigned short int     iph_chksum;\n unsigned int           iph_sourceip;\n unsigned int           iph_destip;\n};\n\nstruct tcpheader {\n u_int16_t      tcph_srcport;\n u_int16_t      tcph_destport;\n u_int32_t      tcph_seqnum;\n u_int32_t      tcph_acknum;\n u_int16_t\n                tcph_ns:1,\n                tcph_reserved:3,\n                tcph_offset:4,\n                tcph_fin:1,\n                tcph_syn:1,\n                tcph_rst:1,\n                tcph_psh:1,\n                tcph_ack:1,\n                tcph_urg:1,\n                tcph_ece:1,\n                tcph_cwr:1;\n u_int16_t      tcph_win;\n u_int16_t      tcph_chksum;\n u_int16_t      tcph_urgptr;\n};\n\nstruct tcpheaderOptions\n{\n\n    u_int16_t \n        tcph_mssOpt:8,\n        tcph_mssLen:8;\n    u_int16_t\n        tcph_mss;\n    u_int16_t\n        tcph_sack:8,\n        tcph_sackLen:8;\n    u_int16_t\n        tcph_winOpt:8,\n        tcph_winLen:8;\n    u_int32_t\n        tcph_win:8,\n        tcph_winNOP:8,\n        tcph_timeOpt:8,\n        tcph_timeLen:8;\n    u_int32_t tcph_time;\n    u_int32_t tcph_timeEcho;\n};\n\nunsigned short          /* this function generates header checksums */\ncsum (unsigned short *buf, int nwords)\n{\n  unsigned long sum;\n  for (sum = 0; nwords > 0; nwords--)\n    sum += *buf++;\n  sum = (sum >> 16) + (sum & 0xffff);\n  sum += (sum >> 16);\n  return ~sum;\n}\n\n\n\nint main(void)\n{\n  char datagram[4096];\n  char data[] = "Hello my name is Keith, this is my first packet";\n  memset(datagram,0,4096);\n  struct ipheader *IPInfo = (struct ipheader *) datagram;\n  struct tcpheader *TCPHeader = (struct tcpheader *) (datagram + sizeof(struct ipheader));\n  struct tcpheaderOptions *TCPOptions = (struct tcpheaderOptions *) (datagram + sizeof(struct tcpheader) + sizeof(struct ipheader));\n  struct sockaddr_in sin;               //Te destination\n  sin.sin_family = AF_INET;\n  sin.sin_port = htons(4);\n  sin.sin_addr.s_addr = inet_addr("192.168.1.114");\n\n  IPInfo->iph_ver       = 4;            //What IP version are we using? v4\n  IPInfo->iph_ihl       = 5;            //The IP header size in bytes\n  IPInfo->iph_tos       = 0;            //The IP header type of service 0x00 is normal\n  IPInfo->iph_len       = sizeof(struct ipheader) + sizeof(struct tcpheader) + sizeof(struct tcpheaderOptions);            //The IP length of the IP datagram\n  IPInfo->iph_ident     = htonl(54321);         //The IP header ID (used when fragmented)\n  IPInfo->iph_offset    = 0;            //IP fragment offset\n  IPInfo->iph_ttl       = 255;          //The IP TTL\n  IPInfo->iph_protocol          = 6;            //The transport layer protocol (6 for TCP, 1 for ICMP, 17 for UDP)\n  IPInfo->iph_chksum    = 0;            //Checksum\n  IPInfo->iph_sourceip  = inet_addr("192.168.1.129"); //source\n//  IPInfo->iph_destip = sin.sin_addr.s_addr;\n  IPInfo->iph_destip    = inet_addr("192.168.1.114");\nchar source[20];\nchar dest[20];\ninet_ntop(AF_INET, &(IPInfo->iph_sourceip), source, 20);\ninet_ntop(AF_INET, &(IPInfo->iph_destip), dest, 20);\nprintf("Source: %s\\n", source);\nprintf("Dest: %s\\n", dest);\n  //IPInfo->ip_dst.s_addr       = inet_addr("192.168.1.114");\n  TCPHeader->tcph_srcport       = htons(56540);           //The source port\n  TCPHeader->tcph_destport      = htons(445);          //The destination port\n  srand(time(NULL));\n  TCPHeader->tcph_seqnum        = rand();          //the sequence number\n  TCPHeader->tcph_acknum        = 0;                 //ACK packet\n  TCPHeader->tcph_reserved      = 0;                    //Not used\n  TCPHeader->tcph_offset        = 10;                 //\n  TCPHeader->tcph_cwr           = 0;\n  TCPHeader->tcph_ns            = 0;\n  TCPHeader->tcph_syn           = 1;\n  TCPHeader->tcph_rst           = 0;\n  TCPHeader->tcph_psh           = 0;\n  TCPHeader->tcph_ack           = 0;\n  TCPHeader->tcph_urg           = 0;\n  TCPHeader->tcph_ece           = 0;\n  TCPHeader->tcph_cwr           = 0;\n  TCPHeader->tcph_ns            = 0;\n  TCPHeader->tcph_win           = htons(1024);\n  TCPHeader->tcph_chksum        = 0;\n  TCPHeader->tcph_urgptr        = 0;\n  TCPOptions->tcph_mssOpt       = 2;\n  TCPOptions->tcph_mssLen       = 4;\n  TCPOptions->tcph_winOpt       = 3;\n  TCPOptions->tcph_winLen       = 3;\n  TCPOptions->tcph_sack         = 4;\n  TCPOptions->tcph_sackLen      = 2;\n  TCPOptions->tcph_win          = 7;\n  TCPOptions->tcph_winNOP       = 1;\n  TCPOptions->tcph_mss          = htons(1460);\n  TCPOptions->tcph_timeOpt      = 8;\n  TCPOptions->tcph_timeLen      = 10;\n  TCPOptions->tcph_time         = 0xdb2b0d00;\n  //Adding the data\n  //strcpy(datagram + sizeof(struct ipheader) + sizeof(struct tcpheader),data);\n  TCPHeader->tcph_chksum = csum((unsigned short *) datagram,TCPHeader->tcph_offset >> 1);\n  IPInfo->iph_chksum = csum((unsigned short *) datagram, IPInfo->iph_len >> 1);\n\n\n  int sockfd = socket(PF_INET, SOCK_RAW, IPPROTO_TCP);\n  if(sockfd == -1) {\n    perror("sockfd");\n    exit(1);\n  }\n\n  //Setting IP_HDRINCL so that the system doesnt add headers to my packets\n  {\n    int one = 1;\n    const int *val = &one;\n    if(setsockopt(sockfd,IPPROTO_IP, IP_HDRINCL, val, sizeof(one)) < 0) {\n      perror("setsockopt");\n      return -1;\n    }\n    else\n      printf("Using your own header\\n");\n  }\n  //Creating a raw socket to send info on\n    if(sendto(sockfd, datagram, IPInfo->iph_len, 0, (struct sockaddr *) &sin, sizeof (sin)) < 0)\n      perror("send");\n    else\n      printf("sending\\n");\n\n  printf("Sent sequence number: %d\\n",TCPHeader->tcph_seqnum);\n\n        //Now we will wait to receive a message back\n        memset(datagram,0,4096);\n        int results = recv(sockfd,datagram,sizeof(datagram),0);\n        printf("Results: %d\\n",results);\n        IPInfo = (struct ipheader *) datagram;\n        TCPHeader = (struct tcpheader * ) (datagram + (IPInfo->iph_ihl * 4));\n        printf("Packet: IPInfo->iph_ihl %d\\n",IPInfo->iph_ihl);\n        printf("ACK num = %d\\n",TCPHeader->tcph_ack);\n\nchar source1[20];\nchar dest1[20];\ninet_ntop(AF_INET, &(IPInfo->iph_sourceip), source, 20);\ninet_ntop(AF_INET, &(IPInfo->iph_destip), dest, 20);    \n\n    printf("Source: %s\\n",source1);\n    printf("Dest: %s\\n",dest1);\n\n    printf("Size of ipheader %d\\n",sizeof(struct ipheader));\n    printf("size of tcpheader %d\\n",sizeof(struct tcpheader));\n\n  return 0;\n}\n
Run Code Online (Sandbox Code Playgroud)\n

Arm*_*ali 0

在wireshark中启用校验和验证,这样你至少可以确定你没有计算错误的校验和(在IP或TCP标头中)\xe2\x80\x93 nos

\n\n

谢谢,我的 TCP 校验和无效 \xe2\x80\x93 Keith

\n