raw socket模擬TCP三次握手

2021-07-25 02:39:25 字數 2888 閱讀 4338

今天花了一天時間,研究了一下如何利用原始套接字模擬tcp的三次握手。因為前幾天一直在關於linux下c語言的socket程式設計,也看的差不多了,今天就敲了一天的**。但是遇到了乙個問題,當我利用raw socket傳送syn報文請求連線後,也能收到對方發來的syn+ack報文,當我傳送ack之前,本機系統會自動傳送乙個rst報文。然後,我在網上搜了一下,也有人遇到我這樣的情況,有人給出如下解決方法:

一、反編譯核心,提取connect的資訊,進行分析,看怎麼記錄連線資訊的,自己加連線資訊,我暈,不太好辦。

二、做個ip報文***,直接過濾掉rst報文。nnd太暴了:),咱是文化人,不能用這招。

三、不讓tcp層收到ack響應,那麼我們就可以攔截這個報文並且把它過濾掉,這種方案也是可行的。

也不知道這些法子到底可不可以,這兩天再看看查閱別的資料試試,或者問問老師看看。

下面貼出我的實驗**供大家分享:

#include#include#include#include#include#include#include#include#define dst "202.196.64.206" //目的ip

#define src "192.168.230.135" //源ip

#define sport 6666 //源埠號

#define dport 80 //目的埠

struct iphead;

struct tcphead;

struct psdhead;

unsigned short cksum(unsigned char packet, int len)

int conn(int sendsockfd, int recsockfd, struct sockaddr_in seraddr)

unsigned char rec[1024];

int n = recvfrom(recsockfd, rec, 1024, 0, null, null); //接收syn和ack報文

printf("receive %d bytes:\n", n); //將接受的ip資料報輸出

for(int i=0; i> 4; //因為tcp報文長度只佔該位元組的高四位,需要取出該四位的值

tcpheadlen *= 4; //以四個位元組為單位

printf("tcpheadlen:%d\n", tcpheadlen);

buffer[11] = tcpheadlen; //將tcp長度存入

for(int i=0; iip_hl = 5;

ip->ip_version = 4;

ip->ip_tos = 0;

ip->ip_len = htons(sizeof(struct iphead) + sizeof(struct tcphead));

ip->ip_id = htons(13543); // random()

ip->ip_off = htons(0x4000);

ip->ip_ttl = 64;

ip->ip_pro = ipproto_tcp;

ip->ip_src = inet_addr(src);

ip->ip_dst = inet_addr(dst);

ip->ip_sum = cksum(packet, 20); //計算ip首部的校驗和,必須在其他欄位都賦值後再賦值該欄位,賦值前為0

/*設定tcp首部*/

my_seq ++;

tcp->tcp_sport = htons(sport);

tcp->tcp_dport = htons(dport);

tcp->tcp_seq = htonl(my_seq);

printf("op_seq:%d\n", op_seq);

tcp->tcp_ack = ntohl(op_seq+1);

tcp->tcp_len = 5; //傳送syn報文段時,設定tcp首部長度為20位元組

tcp->tcp_off = 0;

tcp->tcp_flag = 0x10; //syn置位

tcp->tcp_win = htons(1000);

tcp->tcp_urp = htons(0);

/*設定tcp偽首部,用於計算tcp報文段校驗和*/

// struct psdhead psd;

psd.saddr = inet_addr(src); //源ip位址

psd.daddr = inet_addr(dst); //目的ip位址

psd.mbz = 0;

psd.ptcl = 6;

psd.tcpl = htons(20);

unsigned char buffer[1000]; //用於儲存tcp偽首部和tcp報文,計算校驗碼

memcpy(buffer, &psd, sizeof(psd));

memcpy(buffer+sizeof(psd), tcp, sizeof(struct tcphead));

tcp->tcp_sum = cksum(buffer, sizeof(psd) + sizeof(struct tcphead)); //計算檢驗碼

/*傳送syn報文段*/

int send = sendto(sendsockfd, packet, htons(ip->ip_len), 0,(struct sockaddr *)&seraddr, sizeof(seraddr));

if(send < 0)

printf("已傳送ack報文,已建立tcp連線\n");

n = recvfrom(recsockfd, rec, 1024, 0, null, null); //接收ip資料報

printf("receive %d bytes:\n", n); //將接受的ip資料報輸出

for(int i=0; i

TCP模擬實現

封裝tcpsocket類,向外提供更加輕便的tcp套接字介面 1.建立套接字 socket 2.繫結位址資訊 bind std string ip,uint16 t port 3.服務端開始監聽,客戶端向服務端發起連線請求 listen int backlog 5 connet std string...

TCP協議詳解(三) TCP狀態轉移

tcp連線的任意一端在任一時刻都處於某種狀態,當前狀態可以通過netstat命令檢視。下圖為完整的tcp狀態轉移圖,它描繪了所有的tcp狀態以及可能的狀態轉換。圖中的粗虛線表示典型的伺服器端連線的狀態轉移 粗實線表示典型的客戶端連線的狀態轉移。closed是乙個假想的起始點,並不是乙個實際狀態。這裡...

TCP協議詳解(三)

首先我們來回顧下我們以前了解過的,tcp頭部結構有6個標識位 以上就是我們講到以下內容的時候需要用到的知識點 開始介紹一下三次握手的過程 三次握手建立後,客戶端與伺服器開始傳送資料。三次握手示意圖 接下來,我們來介紹下四次握手關閉 四次握手示意圖 在tcp詳解 二 中,提到過,當客戶端收到伺服器的結...