當前位置:編程學習大全網 - 編程語言 - 求syn掃描的源代碼及操作系統探測的相關資料

求syn掃描的源代碼及操作系統探測的相關資料

詳解SYN Flood攻擊原理與防範

SYN Flood是當前最流行的DoS(拒絕服務攻擊)與DDoS(分布式拒絕服務攻擊)的方式之壹,它是利用TCP協議缺陷,發送大量偽造的TCP連接請求,從而使得被攻擊方資源耗盡(CPU滿負荷或內存不足)的攻擊方式……

SYN Flood的基本原理

SYN Flood是當前最流行的DoS(拒絕服務攻擊)與DDoS(分布式拒絕服務攻擊)的方式之壹,它是利用TCP協議缺陷,發送大量偽造的TCP連接請求,從而使得被攻擊方資源耗盡(CPU滿負荷或內存不足)的攻擊方式,最終導致系統或服務器宕機。

在討論SYN Flood原理前,我們需要從TCP連接建立的過程開始說起:

TCP與UDP不同,它是基於連接的,為了在服務端和客戶端之間傳送TCP數據,必須先建立壹個虛擬電路,也就是TCP連接。也就是我們經常聽說的TCP協議中的三次握手(Three-way Handshake),建立TCP連接的標準過程如下:

首先,客戶端發送壹個包含SYN標誌的TCP報文,SYN即同步(Synchronize),同步報文會指明客戶端使用的端口以及TCP連接的初始序號;

其次,服務器在收到客戶端的SYN報文後,將返回壹個SYN+ACK(即確認Acknowledgement)的報文,表示客戶端的請求被接受,同時TCP初始序號自動加壹。

最後,客戶端也返回壹個確認報文ACK給服務器端,同樣TCP序列號被加壹,到此壹個TCP連接完成。

SYN Flood攻擊正是利用了TCP連接的三次握手,假設壹個用戶向服務器發送了SYN報文後突然死機或掉線,那麽服務器在發出SYN+ACK應答報文後是無法收到客戶端的ACK報文的(第三次握手無法完成),這種情況下服務器端壹般會重試(再次發送SYN+ACK給客戶端)並等待壹段時間後丟棄這個未完成的連接,這段時間的長度我們稱為SYN Timeout,壹般來說這個時間是分鐘的數量級(大約為30秒-2分鐘);壹個用戶出現異常導致服務器的壹個線程等待1分鐘並不會對服務器端造成什麽大的影響,但如果有大量的等待丟失的情況發生,服務器端將為了維護壹個非常大的半連接請求而消耗非常多的資源。我們可以想象大量的保存並遍歷也會消耗非常多的CPU時間和內存,再加上服務器端不斷對列表中的IP進行SYN+ACK的重試,服務器的負載將會變得非常巨大。如果服務器的TCP/IP棧不夠強大,最後的結果往往是堆棧溢出崩潰。相對於攻擊數據流,正常的用戶請求就顯得十分渺小,服務器疲於處理攻擊者偽造的TCP連接請求而無暇理睬客戶的正常請求,此時從正常客戶會表現為打開頁面緩慢或服務器無響應,這種情況就是我們常說的服務器端SYN Flood攻擊(SYN洪水攻擊)。

從防禦角度來講,存在幾種的解決方法:

第壹種是縮短SYN Timeout時間,由於SYN Flood攻擊的效果取決於服務器上保持的SYN半連接數,這個值=SYN攻擊的頻度 x SYN Timeout,所以通過縮短從接收到SYN報文到確定這個報文無效並丟棄改連接的時間,例如設置為20秒以下,可以成倍的降低服務器的負荷。但過低的SYN Timeout設置可能會影響客戶的正常訪問。

第二種方法是設置SYN Cookie,就是給每壹個請求連接的IP地址分配壹個Cookie,如果短時間內連續受到某個IP的重復SYN報文,就認定是受到了攻擊,並記錄地址信息,以後從這個IP地址來的包會被壹概丟棄。這樣做的結果也可能會影響到正常用戶的訪問。

上述的兩種方法只能對付比較原始的SYN Flood攻擊,縮短SYN Timeout時間僅在對方攻擊頻度不高的情況下生效,SYN Cookie更依賴於對方使用真實的IP地址,如果攻擊者以數萬/秒的速度發送SYN報文,同時利用SOCK_RAW隨機改寫IP報文中的源地址,以上的方法將毫無用武之地。

SYN Flood是當前最流行的DoS(拒絕服務攻擊)與DDoS(分布式拒絕服務攻擊)的方式之壹,它是利用TCP協議缺陷,發送大量偽造的TCP連接請求,從而使得被攻擊方資源耗盡(CPU滿負荷或內存不足)的攻擊方式……

SYN Flooder源碼解讀

下面我們來分析SYN Flooder的程序實現。

首先,我們來看壹下TCP報文的格式:

0 1 2 3 4 5 6

0 2 4 6 8 0 2 4 6 8 0 2 4 6 8 0 2 4 6 8 0 2 4 6 8 0 2 4 6 8 0 2 4

+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

| IP首部 | TCP首部 | TCP數據段 |

+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

圖壹 TCP報文結構

如上圖所示,壹個TCP報文由三個部分構成:20字節的IP首部、20字節的TCP首部與不定長的數據段,實際操作時可能會有可選的IP選項,這種情況下TCP首部向後順延,由於我們只是發送壹個SYN信號,並不傳遞任何數據,所以TCP數據段為空。TCP首部的數據結構為:

0 1 2 3

0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2

+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

| 十六位源端口號 | 十六位目標端口號 |

+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

| 三十二位序列號 |

+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

| 三十二位確認號 |

+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

| 四位 | |U|A|P|R|S|F| |

| 首部 |六位保留位 |R|C|S|S|Y|I| 十六位窗口大小 |

| 長度 | |G|K|H|T|N|N| |

+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

| 十六位校驗和 | 十六位緊急指針 |

+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

| 選項(若有) |

+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

| 數據(若有) |

+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

圖二 TCP首部結構

根據TCP報文格式,我們定義壹個結構TCP_HEADER用來存放TCP首部:

typedef struct _tcphdr

{

USHORT th_sport; //16位源端口

USHORT th_dport; //16位目的端口

unsigned int th_seq; //32位序列號

unsigned int th_ack; //32位確認號

unsigned char th_lenres; //4位首部長度+6位保留字中的4位

unsigned char th_flag; //2位保留字+6位標誌位

USHORT th_win; //16位窗口大小

USHORT th_sum; //16位校驗和

USHORT th_urp; //16位緊急數據偏移量

}TCP_HEADER;

通過以正確的數據填充這個結構並將TCP_HEADER.th_flag賦值為2(二進制的00000010)我們能制造壹個SYN的TCP報文,通過大量發送這個報文可以實現SYN Flood的效果。但是為了進行IP欺騙從而隱藏自己,也為了躲避服務器的SYN Cookie檢查,還需要直接對IP首部進行操作:

0 1 2 3

0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2

+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

| 版本 | 長度 | 八位服務類型 | 十六位總長度 |

+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

| 十六位標識 | 標誌| 十三位片偏移 |

+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

| 八位生存時間 | 八位協議 | 十六位首部校驗和 |

+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

| 三十二位源IP地址 |

+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

| 三十二位目的IP地址 |

+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

| 選項(若有) |

+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

| 數據 |

+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

圖三 IP首部結構

同樣定義壹個IP_HEADER來存放IP首部:

typedef struct _iphdr

{

unsigned char h_verlen; //4位首部長度+4位IP版本號

unsigned char tos; //8位服務類型TOS

unsigned short total_len; //16位總長度(字節)

unsigned short ident; //16位標識

unsigned short frag_and_flags; //3位標誌位

unsigned char ttl; //8位生存時間 TTL

unsigned char proto; //8位協議號(TCP, UDP 或其他)

unsigned short checksum; //16位IP首部校驗和

unsigned int sourceIP; //32位源IP地址

unsigned int destIP; //32位目的IP地址

}IP_HEADER;

然後通過SockRaw=WSASocket(AF_INET,SOCK_RAW,IPPROTO_RAW,NULL,0,WSA_FLAG_OVERLAPPED);

建立壹個原始套接口,由於我們的IP源地址是偽造的,所以不能指望系統幫我們計算IP校驗和,我們得在在setsockopt中設置IP_HDRINCL告訴系統自己填充IP首部並自己計算校驗和:

flag=TRUE;

setsockopt(SockRaw,IPPROTO_IP,IP_HDRINCL,(char *)&flag,sizeof(int));

IP校驗和的計算方法是:首先將IP首部的校驗和字段設為0(IP_HEADER.checksum=0),然後計算整個IP首部(包括選項)的二進制反碼的和,壹個標準的校驗和函數如下所示:

USHORT checksum(USHORT *buffer, int size)

{

unsigned long cksum=0;

while(size >1) {

cksum+=*buffer++;

size -=sizeof(USHORT);

}

if(size ) cksum += *(UCHAR*)buffer;

cksum = (cksum >> 16) + (cksum & 0xffff);

cksum += (cksum >>16);

return (USHORT)(~cksum);

}

這個函數並沒有經過任何的優化,由於校驗和函數是TCP/IP協議中被調用最多函數之壹,所以壹般說來,在實現TCP/IP棧時,會根據操作系統對校驗和函數進行優化。

TCP首部檢驗和與IP首部校驗和的計算方法相同,在程序中使用同壹個函數來計算。

需要註意的是,由於TCP首部中不包含源地址與目標地址等信息,為了保證TCP校驗的有效性,在進行TCP校驗和的計算時,需要增加壹個TCP偽首部的校驗和,定義如下:

struct

{

unsigned long saddr; //源地址

unsigned long daddr; //目的地址

char mbz; //置空

char ptcl; //協議類型

unsigned short tcpl; //TCP長度

}psd_header;

然後我們將這兩個字段復制到同壹個緩沖區SendBuf中並計算TCP校驗和:

memcpy(SendBuf,&psd_header,sizeof(psd_header));

memcpy(SendBuf+sizeof(psd_header),&tcp_header,sizeof(tcp_header));

tcp_header.th_sum=checksum((USHORT *)SendBuf,sizeof(psd_header)+sizeof(tcp_header));

計算IP校驗和的時候不需要包括TCP偽首部:

memcpy(SendBuf,&ip_header,sizeof(ip_header));

memcpy(SendBuf+sizeof(ip_header),&tcp_header,sizeof(tcp_header));

ip_header.checksum=checksum((USHORT *)SendBuf, sizeof(ip_header)+sizeof(tcp_header));

再將計算過校驗和的IP首部與TCP首部復制到同壹個緩沖區中就可以直接發送了:

memcpy(SendBuf,&ip_header,sizeof(ip_header));

sendto(SockRaw,SendBuf,datasize,0,(struct sockaddr*) &DestAddr,sizeof(DestAddr));

因為整個TCP報文中的所有部分都是我們自己寫入的,操作系統不會做任何幹涉,所以我們可以在IP首部中放置隨機的源IP地址,如果偽造的源IP地址確實有人使用,並有地址幫定時,在接收到服務器的SYN+ACK報文後會發送壹個RST報文(標誌位為00000100),通知服務器端不需要等待壹個無效的連接;但如果這個偽造IP並沒有綁定在任何的主機上,不會有任何設備去通知主機該連接是無效的,這就是我們所廣泛應用的TCP協議的SYN洪水攻擊,主機將不斷重復發送回執,直到SYN Timeout時間後才能丟棄這個無效的半連接。所以當攻擊者使用主機分布很稀疏的IP地址段進行偽裝IP的SYN Flood攻擊時,服務器主機承受的負荷會相當的高,根據測試,壹臺奔3 128MB+100Mbps的機器,使用經過初步優化的SYN Flooder程序可以以16,000包/秒的速度發送TCP SYN報文,這樣的攻擊力已經足以拖垮大部分WEB服務器了。

善於思考的用戶會發現,想對SYN Flooder程序進行優化是很簡單的,從程序構架來看,攻擊時循環內的代碼主要是進行校驗和計算與緩沖區的填充,壹般的思路是提高校驗和計算的速度,甚至精明的開發者會用匯編代碼編寫校驗和函數。實際上,還存在壹種可以輕松實現優化而又不需要高深的編程技巧和數學知識,我們仔細研究了兩個不同源地址的TCP SYN報文後發現,兩個報文的大部分字段相同(比如目的地址、協議等等),只有源地址和校驗和不同,如果我們事先計算好大量的源地址與校驗和的對應關系表,等計算完畢後,攻擊程序就只需要單純的組合緩沖區,用指針來直接操作緩沖區的特定位置,從事先計算好的對應關系表中讀出數據,替換緩沖區相應字段。這種簡單的工作完全取決於系統發送IP包的速度,與程序的效率沒有任何關系,這樣即使是CPU主頻較低的主機也能快速的發送大量TCP SYN攻擊包。如果考慮到緩沖區拼接的時間,甚至可以定義壹個很大的緩沖區數組,填充完畢後再發送。

SYN Flood是當前最流行的DoS(拒絕服務攻擊)與DDoS(分布式拒絕服務攻擊)的方式之壹,它是利用TCP協議缺陷,發送大量偽造的TCP連接請求,從而使得被攻擊方資源耗盡(CPU滿負荷或內存不足)的攻擊方式……

SYN Flood攻擊的監測與防禦初探

對於SYN Flood攻擊,特別是DDos,目前尚沒有很好的監測和防禦方法,不過如果系統管理員熟悉攻擊方法和系統架構,通過壹系列的設定,可以在最大程度上降低被攻擊系統的負荷,不會對系統的正常工作造成無法挽回的影響。如果壹臺主機負荷突然升高甚至失去響應,使用Netstat 命令能看到大量SYN_RCVD的半連接,可以認定,這臺主機遭到了SYN Flood攻擊。

遭到SYN Flood攻擊後,首先要做的是取證,通過在命令行下使用 Netstat ?Cn ?Cp tcp >resault.txt記錄目前所有TCP連接狀態是必要的,如果有嗅探器或TcpDump之類的工具,詳細記錄TCP SYN報文會更有助於追查和防禦,需要記錄的字段有:源地址、IP首部中的標識、TCP首部中的序列號、TTL值(Time to Life,生存周期)等,這些信息雖然很可能是攻擊者偽造的,但是用來分析攻擊攻擊程序不無幫助。特別是TTL值,如果大量的攻擊包似乎來自不同的IP但是TTL值卻相同,我們往往能推斷出攻擊者與我們之間的路由器距離,至少也可以通過過濾特定TTL值的報文降低被攻擊系統的負荷,確保TTL值與攻擊報文不同的用戶就可以恢復正常訪問。

對於Win2000系統,還可以通過修改註冊表降低SYN Flood的危害,在註冊表中作如下改動:

首先,打開regedit,找到[HKEY_LOCAL_MACHINE\Sytem\CurrentControlSet\Services\Tcpip\Parameters]

增加壹個SynAttackProtect的鍵值,類型為REG_DWORD,取值範圍是0-2,這個值決定了系統受到SYN攻擊時采取的保護措施,包括減少系統SYN+ACK的重試的次數等,默認值是0(沒有任何保護措施),推薦設置為2;

增加壹個TcpMaxHalfOpen的鍵值,類型為REG_DWORD,取值範圍是100-0xFFFF,這個值是系統允許同時打開的半連接數,默認情況下windows2000是100,ADVANCED SERVER版本的windows 2000是500,這個值很難確定,取決於服務器TCP負荷的狀況和可能受到的攻擊強度。具體的值需要經過管理員的嘗試測試/預測壹下訪問峰值時期的半連接打開量,以其作為參考設定TcpMaxHalfOpenRetried的值,需要保留壹定的余量,然後再以TcpMaxHalfOpenRetried的1.25倍作為TcpMaxHalfOpen值,這樣可以最大限度地發揮windows 2000自身的SYN攻擊保護機制。

增加壹個TcpMaxHalfOpenRetried的鍵值,類型為REG_DWORD,取值範圍是80-0xFFFF,默認情況下windows2000是80,ADVANCED SERVERwindows2000是400,這個值決定了在什麽情況下系統會打開SYN攻擊保護。

我們來分析壹下windows 2000的SYN攻擊保護機制:正常情況下,windows 2000對TCP連接的三次握手有壹個常規的設置,包括SYN Timeout時間、SYN-ACK的重試次數和SYN報文從路由器到系統再到Winsock的延時等,這個常規設置是針對系統性能進行優化的,所以可以給用戶提供方便快捷的服務;壹旦服務器受到攻擊,SYN半連接的數量超過TcpMaxHalfOpenRetried的設置,系統會認為自己受到了SYN Flood攻擊,此時設置在SynAttackProtect鍵值中的選項開始作用,SYN Timeout時間被減短,SYN-ACK的重試次數減少,系統也會自動對緩沖區中的報文進行延時,避免對TCP/IP堆棧造成過大的沖擊,力圖將攻擊危害減到最低;如果攻擊強度不斷增大,超過了TcpMaxHalfOpen值,此時系統已經不能提供正常的服務了,更重要的是保證系統不會崩潰,所以系統將會丟棄任何超出TcpMaxHalfOpen值範圍的SYN報文(應該是使用隨機丟包策略),保證系統的穩定性。

通過設置註冊表防禦SYN Flood攻擊,采用的是被動的策略,無論系統如何強大,始終不能靠被動的防護支撐下去,下面我們來看看另外壹種比較有效的方法。

我稱這種策略為“犧牲”策略,基於SYN Flood攻擊代碼的壹個缺陷,我們重新來分析壹下SYN Flood攻擊者的流程:SYN Flood程序有兩種攻擊方式,基於IP的和基於域名的,前者是攻擊者自己進行域名解析並將IP地址傳遞給攻擊程序,後者是攻擊程序自動進行域名解析,但是它們有壹點是相同的,就是壹旦攻擊開始,將不會再進行域名解析,我們就是要利用這壹點,假設壹臺服務器在受到SYN Flood攻擊後迅速更換自己的IP地址,那麽攻擊者仍在不斷攻擊的只是壹個空的IP地址,並沒有任何主機,而管理員只需將DNS解析更改到新的IP地址就能在很短的時間內恢復用戶通過域名進行的正常訪問,這種做法取決於DNS的刷新時間。為了迷惑攻擊者,我們甚至可以放置壹臺“犧牲”服務器,對攻擊數據流進行牽引。

同樣的原因,在眾多的負載均衡架構中,基於DNS解析的負載均衡本身就擁有對SYN Flood的免疫力,基於DNS解析的負載均衡能將用戶的請求分配到不同IP的服務器主機上,攻擊者的壹次攻擊永遠只能是其中壹臺服務器,雖然說攻擊者也能不斷去進行DNS請求來持續對用戶的攻擊,但是這樣增加了攻擊者的攻擊強度,同時由於過多的DNS請求,可以幫助管理員查找到攻擊者的地址,這主要是由於DNS請求需要返回數據,而這個數據是很難被偽裝的。

如今DDOS攻擊仍然沒有徹底的解決方案,但各個廠商都在考慮將負載均衡、流量牽引以及帶寬控制等技術綜合利用,配合不斷生機的包分析能力,甚至虛擬技術,力求將SYN Flood攻擊降到最低點。讓用戶和我拭目以待新產品和新技術的誕生。

  • 上一篇:能說說妳的人生經歷嗎?
  • 下一篇:數控等離子切割機編程軟件有哪些
  • copyright 2024編程學習大全網