Как правильно воспроизвести трехстороннее рукопожатие по протоколу TCP с необработанными сокетами? - PullRequest
2 голосов
/ 14 декабря 2010

Я имитирую трехстороннее рукопожатие по протоколу tcp в c ++ вместе с wireshark во время выполнения моего кода.Мой код обрабатывает заголовки на слоях ip и tcp, упаковывает их, затем отправляет на http-сервер с установленным в 1. 1

* 1002 флагом SYN флагом заголовка tcp.Хорошо.Кажется, без ошибок.Мой процесс связывает сокет с тем же адресом и портом, которые указаны в заголовке уже отправленного пакета.

Wireshark показывает, что пакет успешно отправлен, но нет никакого дохода от сервера, подтверждающего мой SYN.Что я делаю не так?

Я нахожусь на Ubuntu 10.10, 2.6.35-23.

Код грязный, извините за это.Это только для тестирования.

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 ...

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;

1 Ответ

3 голосов
/ 14 декабря 2010

Вы еще не дошли до этого, но вам нужно будет настроить брандмауэр локального порта, который вы используете, чтобы ядро ​​не отвечало на SYN / ACK с RST.

...