谢谢,我的 TCP 校验和无效 – KeithI'm trying to create a TCP connection using raw sockets in C (on a Debian system) but I'm having a hard time getting it working. It will send a packet but I dont get any response from the server. I have tested and compared the packet with a packet sent from nmap and I cant see any major differences.Here is the TCP packet received on the server side, the server side never sends a SYN ACK packet (I'm monitoring using Wireshark on the server side)No. Time Source Destination Protocol Length Info 75 1.893700000 192.168.1.129 192.168.1.114 TCP 74 56540→445 [SYN] Seq=0 Win=1024 Len=0 MSS=1460 SACK_PERM=1 WS=128 TSval=863195 TSecr=0Frame 75: 74 bytes on wire (592 bits), 74 bytes captured (592 bits) on interface 0Ethernet II, Src: Vmware_77:f0:a0 (00:0c:29:77:f0:a0), Dst: IntelCor_07:f9:e5 (e8:b1:fc:07:f9:e5)Internet Protocol Version 4, Src: 192.168.1.129 (192.168.1.129), Dst: 192.168.1.114 (192.168.1.114)Version: 4Header Length: 20 bytesDifferentiated Services Field: 0x00 (DSCP 0x00: Default; ECN: 0x00: Not-ECT (Not ECN-Capable Transport))Total Length: 60Identification: 0xb88d (47245)Flags: 0x00Fragment offset: 0Time to live: 255Protocol: TCP (6)Header checksum: 0x7eea [validation disabled]Source: 192.168.1.129 (192.168.1.129)Destination: 192.168.1.114 (192.168.1.114)[Source GeoIP: Unknown][Destination GeoIP: Unknown]Transmission Control Protocol, Src Port: 56540 (56540), Dst Port: 445 (445), Seq: 0, Len: 0Source Port: 56540 (56540)Destination Port: 445 (445)[Stream index: 3][TCP Segment Len: 0]Sequence number: 0 (relative sequence number)Acknowledgment number: 0Header Length: 40 bytes.... 0000 0000 0010 = Flags: 0x002 (SYN)Window size value: 1024[Calculated window size: 1024]Checksum: 0x7ff8 [validation disabled]Urgent pointer: 0Options: (20 bytes), Maximum segment size, SACK permitted, Window scale, No-Operation (NOP), Timestamps Maximum segment size: 1460 bytes Kind: Maximum Segment Size (2) Length: 4 MSS Value: 1460 TCP SACK Permitted Option: True Kind: SACK Permitted (4) Length: 2 Window scale: 7 (multiply by 128) Kind: Window Scale (3) Length: 3 Shift count: 7 [Multiplier: 128] No-Operation (NOP) Type: 1 Timestamps: TSval 863195, TSecr 0 Kind: Time Stamp Option (8) Length: 10 Timestamp value: 863195 Timestamp echo reply: 00000 e8 b1 fc 07 f9 e5 00 0c 29 77 f0 a0 08 00 45 00 ........)w....E.0010 00 3c b8 8d 00 00 ff 06 7e ea c0 a8 01 81 c0 a8 .<......~.......0020 01 72 dc dc 01 bd db 0f 13 02 00 00 00 00 a0 02 .r..............0030 04 00 7f f8 00 00 02 04 05 b4 04 02 03 03 07 01 ................0040 08 0a 00 0d 2b db 00 00 00 00 ....+.....And here is my code, i know it is messy, i'm just trying to learn how to use raw sockets#include <stdio.h>#include <stdlib.h>#include <string.h>#include <sys/types.h>#include <sys/socket.h>#include <netdb.h>#include <arpa/inet.h>#include <netinet/in.h>#include <unistd.h>#include <time.h>struct ipheader { unsigned char iph_ihl:4, /* Little-endian */ iph_ver:4; unsigned char iph_tos; unsigned short int iph_len; unsigned short int iph_ident; unsigned short int iph_offset:13, /* Little-endian*/ iph_flags:3; unsigned char iph_ttl; unsigned char iph_protocol; unsigned short int iph_chksum; unsigned int iph_sourceip; unsigned int iph_destip;};struct tcpheader { u_int16_t tcph_srcport; u_int16_t tcph_destport; u_int32_t tcph_seqnum; u_int32_t tcph_acknum; u_int16_t tcph_ns:1, tcph_reserved:3, tcph_offset:4, tcph_fin:1, tcph_syn:1, tcph_rst:1, tcph_psh:1, tcph_ack:1, tcph_urg:1, tcph_ece:1, tcph_cwr:1; u_int16_t tcph_win; u_int16_t tcph_chksum; u_int16_t tcph_urgptr;};struct tcpheaderOptions{ u_int16_t tcph_mssOpt:8, tcph_mssLen:8; u_int16_t tcph_mss; u_int16_t tcph_sack:8, tcph_sackLen:8; u_int16_t tcph_winOpt:8, tcph_winLen:8; u_int32_t tcph_win:8, tcph_winNOP:8, tcph_timeOpt:8, tcph_timeLen:8; u_int32_t tcph_time; u_int32_t tcph_timeEcho;};unsigned short /* this function generates header checksums */csum (unsigned short *buf, int nwords){ unsigned long sum; for (sum = 0; nwords > 0; nwords--) sum += *buf++; sum = (sum >> 16) + (sum & 0xffff); sum += (sum >> 16); return ~sum;}int main(void){ char datagram[4096]; char data[] = "Hello my name is Keith, this is my first packet"; memset(datagram,0,4096); struct ipheader *IPInfo = (struct ipheader *) datagram; struct tcpheader *TCPHeader = (struct tcpheader *) (datagram + sizeof(struct ipheader)); struct tcpheaderOptions *TCPOptions = (struct tcpheaderOptions *) (datagram + sizeof(struct tcpheader) + sizeof(struct ipheader)); struct sockaddr_in sin; //Te destination sin.sin_family = AF_INET; sin.sin_port = htons(4); sin.sin_addr.s_addr = inet_addr("192.168.1.114"); IPInfo->iph_ver = 4; //What IP version are we using? v4 IPInfo->iph_ihl = 5; //The IP header size in bytes IPInfo->iph_tos = 0; //The IP header type of service 0x00 is normal IPInfo->iph_len = sizeof(struct ipheader) + sizeof(struct tcpheader) + sizeof(struct tcpheaderOptions); //The IP length of the IP datagram IPInfo->iph_ident = htonl(54321); //The IP header ID (used when fragmented) IPInfo->iph_offset = 0; //IP fragment offset IPInfo->iph_ttl = 255; //The IP TTL IPInfo->iph_protocol = 6; //The transport layer protocol (6 for TCP, 1 for ICMP, 17 for UDP) IPInfo->iph_chksum = 0; //Checksum IPInfo->iph_sourceip = inet_addr("192.168.1.129"); //source// IPInfo->iph_destip = sin.sin_addr.s_addr; IPInfo->iph_destip = inet_addr("192.168.1.114");char source[20];char dest[20];inet_ntop(AF_INET, &(IPInfo->iph_sourceip), source, 20);inet_ntop(AF_INET, &(IPInfo->iph_destip), dest, 20);printf("Source: %s\n", source);printf("Dest: %s\n", dest); //IPInfo->ip_dst.s_addr = inet_addr("192.168.1.114"); TCPHeader->tcph_srcport = htons(56540); //The source port TCPHeader->tcph_destport = htons(445); //The destination port srand(time(NULL)); TCPHeader->tcph_seqnum = rand(); //the sequence number TCPHeader->tcph_acknum = 0; //ACK packet TCPHeader->tcph_reserved = 0; //Not used TCPHeader->tcph_offset = 10; // TCPHeader->tcph_cwr = 0; TCPHeader->tcph_ns = 0; TCPHeader->tcph_syn = 1; TCPHeader->tcph_rst = 0; TCPHeader->tcph_psh = 0; TCPHeader->tcph_ack = 0; TCPHeader->tcph_urg = 0; TCPHeader->tcph_ece = 0; TCPHeader->tcph_cwr = 0; TCPHeader->tcph_ns = 0; TCPHeader->tcph_win = htons(1024); TCPHeader->tcph_chksum = 0; TCPHeader->tcph_urgptr = 0; TCPOptions->tcph_mssOpt = 2; TCPOptions->tcph_mssLen = 4; TCPOptions->tcph_winOpt = 3; TCPOptions->tcph_winLen = 3; TCPOptions->tcph_sack = 4; TCPOptions->tcph_sackLen = 2; TCPOptions->tcph_win = 7; TCPOptions->tcph_winNOP = 1; TCPOptions->tcph_mss = htons(1460); TCPOptions->tcph_timeOpt = 8; TCPOptions->tcph_timeLen = 10; TCPOptions->tcph_time = 0xdb2b0d00; //Adding the data //strcpy(datagram + sizeof(struct ipheader) + sizeof(struct tcpheader),data); TCPHeader->tcph_chksum = csum((unsigned short *) datagram,TCPHeader->tcph_offset >> 1); IPInfo->iph_chksum = csum((unsigned short *) datagram, IPInfo->iph_len >> 1); int sockfd = socket(PF_INET, SOCK_RAW, IPPROTO_TCP); if(sockfd == -1) { perror("sockfd"); exit(1); } //Setting IP_HDRINCL so that the system doesnt add headers to my packets { int one = 1; const int *val = &one; if(setsockopt(sockfd,IPPROTO_IP, IP_HDRINCL, val, sizeof(one)) < 0) { perror("setsockopt"); return -1; } else printf("Using your own header\n"); } //Creating a raw socket to send info on if(sendto(sockfd, datagram, IPInfo->iph_len, 0, (struct sockaddr *) &sin, sizeof (sin)) < 0) perror("send"); else printf("sending\n"); printf("Sent sequence number: %d\n",TCPHeader->tcph_seqnum); //Now we will wait to receive a message back memset(datagram,0,4096); int results = recv(sockfd,datagram,sizeof(datagram),0); printf("Results: %d\n",results); IPInfo = (struct ipheader *) datagram; TCPHeader = (struct tcpheader * ) (datagram + (IPInfo->iph_ihl * 4)); printf("Packet: IPInfo->iph_ihl %d\n",IPInfo->iph_ihl); printf("ACK num = %d\n",TCPHeader->tcph_ack);char source1[20];char dest1[20];inet_ntop(AF_INET, &(IPInfo->iph_sourceip), source, 20);inet_ntop(AF_INET, &(IPInfo->iph_destip), dest, 20); printf("Source: %s\n",source1); printf("Dest: %s\n",dest1); printf("Size of ipheader %d\n",sizeof(struct ipheader)); printf("size of tcpheader %d\n",sizeof(struct tcpheader)); return 0;} 解决方案 Enable checksum validation in wireshark, so you're at least sure you're not calculating wrong checksums (in either the IP or TCP header) – nosThanks, my TCP checksum was invalid – Keith 这篇关于Linux C 原始套接字 TCP 握手的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持! 上岸,阿里云! 08-21 01:58