今天花了一天時間,研究了一下如何利用原始套接字模擬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詳解 二 中,提到過,當客戶端收到伺服器的結...