如何正确地重现TCP协议3次握手与原始套接字? [英] How to reproduce TCP protocol 3-way handshake with raw sockets correctly?

查看:200
本文介绍了如何正确地重现TCP协议3次握手与原始套接字?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆