如何正确地重现TCP协议3次握手与原始套接字? [英] How to reproduce TCP protocol 3-way handshake with raw sockets correctly?
问题描述
Im模拟tcp协议的c ++中的3次握手,以及我的代码运行时的wireshark。
我的代码工艺在ip和tcp层的头,打包它们,然后发送到http服务器tcp头的SYN标志设置为1。
Im simulating tcp protocol's 3-way handshake in c++, along with wireshark as my code runs. My code crafts the headers at ip and tcp layers, packs them, then send it to an http server with tcp header's SYN flag set to 1.
I可以看到在wireshark完整的数据报与ip和tcp头确定。似乎是没有错误。
我的进程绑定一个与已经发送的包头中包含的地址和端口相同的套接字。
I can see on wireshark the full datagram with both ip and tcp headers ok. Seems to be no errors. My process bind a socket with the same address and port as contained in the already sent packet's header.
Wireshark显示包已成功发送,但没有任何从服务器的收入包确认我的SYN。
我做错了什么?
Wireshark shows packet successfully sent but there isn't any income packet from the server acknowledging my SYN. What am i doing wrong?
我在Ubuntu 10.10,2.6.35-23。
I am on Ubuntu 10.10, 2.6.35-23.
代码很乱,对不起。它只是用于测试。
The code is messy, sorry for that. Its just for testing.
main.cpp:
char host[100],buf[1000],*data=NULL,source_ip[20]; //buf is the complete packet
sockaddr_in dest;
hostent *server;
IPV4_HDR *v4hdr=NULL;
TCP_HDR *tcphdr=NULL;
memset(&buf, 0, sizeof(buf));
cout << "Creating RAW socket..." << endl;
int s;
if ((s = socket(AF_INET, SOCK_RAW, IPPROTO_TCP)) == -1) {
cout << "Error creating socket: " << errno << endl;
return 1;
}
cout << "Setting the socket in RAW mode..." << endl;
int optval = 1;
if ((setsockopt(s, IPPROTO_IP, IP_HDRINCL, &optval, sizeof(optval))) == -1) {
cout << "Failed to set socket in RAW mode..." << endl;
return 1;
}
cout << "Successful.\n";
cout << "nResolving Hostname..." << endl;
if((server=gethostbyname("www.site.com"))==0)
{
cout << "Unable to resolve." << endl;
return 1;
}
dest.sin_family = AF_INET;
dest.sin_port = htons(50000);
memcpy(&dest.sin_addr.s_addr,server->h_addr,server->h_length);
cout << "Resolved." << endl;
v4hdr = (IPV4_HDR *)buf; //lets point to the ip header portion
v4hdr->ip_version=4;
v4hdr->ip_header_len=5;
v4hdr->ip_tos = 16;
v4hdr->ip_total_length = htons ( sizeof(IPV4_HDR) + sizeof(TCP_HDR) );
v4hdr->ip_id = htons(2);
v4hdr->ip_frag_offset = 0;
v4hdr->ip_frag_offset1 = 0;
v4hdr->ip_reserved_zero = 0;
v4hdr->ip_dont_fragment = 1;
v4hdr->ip_more_fragment = 0;
v4hdr->ip_ttl = 64;
v4hdr->ip_protocol = IPPROTO_TCP;
v4hdr->ip_srcaddr = inet_addr("192.168.0.103");
v4hdr->ip_destaddr = inet_addr(inet_ntoa(dest.sin_addr));
v4hdr->ip_checksum = 0;
tcphdr = (TCP_HDR *)&buf[sizeof(IPV4_HDR)]; //get the pointer to the tcp header in the packet
tcphdr->source_port = htons(52000);
tcphdr->dest_port = htons(80);
tcphdr->window = htons(5840);
tcphdr->acknowledge = 0;
tcphdr->data_offset = 8;
tcphdr->urg=0;
tcphdr->ack=0;
tcphdr->psh=0;
tcphdr->rst=0;
tcphdr->syn=1;
tcphdr->fin=0;
tcphdr->options1=htonl(0x020405b4);
tcphdr->options2=htonl(0x04020103);
tcphdr->options3=htonl(0x03060000);
cout << sizeof(*tcphdr) << endl;
//tcphdr->ns=0;
tcphdr->checksum = csum((unsigned short *) buf, (sizeof(ip_hdr) + sizeof(tcp_header)));;
int bytes = 0;
if((bytes = sendto(s , buf , sizeof(IPV4_HDR)+sizeof(TCP_HDR), 0,
(sockaddr *)&dest, sizeof(dest)))==-1)
{
cout << "Error sending packet: " << errno << endl;
return 1;
}
cout << bytes << " bytes sent!" << endl;
close(s);
//这是tcp.h ...
// This is on tcp.h...
typedef struct ip_hdr
{
unsigned char ip_header_len:4; // 4-bit header length (in 32-bit words)
// normally=5 (Means 20 Bytes may be 24 also)
unsigned char ip_version :4; // 4-bit IPv4 version
unsigned char ip_tos; // IP type of service
unsigned short ip_total_length; // Total length
unsigned short ip_id; // Unique identifier
unsigned char ip_frag_offset :5; // Fragment offset field
unsigned char ip_more_fragment :1;
unsigned char ip_dont_fragment :1;
unsigned char ip_reserved_zero :1;
unsigned char ip_frag_offset1; //fragment offset
unsigned char ip_ttl; // Time to live
unsigned char ip_protocol; // Protocol(TCP,UDP etc)
unsigned short ip_checksum; // IP checksum
unsigned int ip_srcaddr; // Source address
unsigned int ip_destaddr; // Source address
} IPV4_HDR;
// TCP header
typedef struct tcp_header
{
unsigned short source_port; // source port
unsigned short dest_port; // destination port
unsigned int sequence; // sequence number - 32 bits
unsigned int acknowledge; // acknowledgement number - 32 bits
unsigned char reserved_part1:4; //according to rfc
unsigned char data_offset:4; /*The number of 32-bit words
in the TCP header.
This indicates where the data begins.
The length of the TCP header
is always a multiple
of 32 bits.*/
unsigned char fin :1; //Finish Flag
unsigned char syn :1; //Synchronise Flag
unsigned char rst :1; //Reset Flag
unsigned char psh :1; //Push Flag
unsigned char ack :1; //Acknowledgement Flag
unsigned char urg :1; //Urgent Flag
unsigned char reserved_part2:2;
unsigned short window :16; // window
//unsigned char ns :1; //Nonce Sum Flag Added in RFC 3540.
//unsigned char ecn :1; //ECN-Echo Flag
//unsigned char cwr :1; //Congestion Window Reduced Flag
////////////////////////////////
unsigned short checksum; // checksum
unsigned short urgent_pointer; // urgent pointer
unsigned int options1;
unsigned int options2;
unsigned int options3;
} TCP_HDR;
推荐答案
将需要防火墙使用的本地端口,以便内核不用RST响应SYN / ACK。
You haven't gotten this far yet, but you will need to firewall the local port you are using so that the kernel doesn't reply to SYN/ACK with a RST.
这篇关于如何正确地重现TCP协议3次握手与原始套接字?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!