1. 程式人生 > >你到底遭受了多大的SYN Flood攻擊?

你到底遭受了多大的SYN Flood攻擊?

這是一篇好玩的文章,它並不是講SYN Flood的攻擊原理的,也不描述防禦攻擊的解決方案。在這裡,我會隨便說說幾個通常被裝置廠商或無意,或有意隱藏的幾個細節。如果你在考慮買防禦攻擊的裝置,希望這個文章能夠給你一些幫助——至少在和廠商談判的時候,知道問哪些問題,不會輕易被人忽悠了。

一. 乙太網填充

目前的SYN Flood程式,為了提高發送效率,填充包頭的時候,沒有填充可選的欄位,因此IP頭長度恰好是20位元組(Byte),圖示如下:
typedef struct ip_hdr
{
    unsigned char       h_verlen;
    unsigned char       tos;
    unsigned short      total_len;
    unsigned short      ident;
    unsigned short      frag_and_flags;
    unsigned char       ttl;
    unsigned char       proto;
    unsigned short      checksum;
    unsigned int        sourceIP;
    unsigned int        destIP;
}IP_HEADER;

同樣的,對於TCP頭部,長度也是20位元組,圖示如下:
typedef struct tcp_hdr
{
    unsigned short      th_sport;
    unsigned short      th_dport;
    unsigned int          th_seq;
    unsigned int          th_ack;
    unsigned char       th_lenres;
    unsigned char       th_flag;
    unsigned short      th_win;
    unsigned short      th_sum;
    unsigned short      th_urp;
}TCP_HEADER;

也就是說,攻擊程式填充了一個40位元組的資料包,開始傳送。但是對於乙太網來說,最小的包長度資料段必須達到46位元組,而我們的包只有40位元組,因此,網絡卡在傳送的時候,會作一些處理。我們40位元組的IP頭加TCP頭包的末尾,會被網絡卡填充6個0來滿足最小包的長度要求。這個時候,整個資料包的長度為14位元組的乙太網頭,20位元組的IP頭,20位元組的TCP頭,再加上因為最小包長度要求而填充的6個位元組的0,一共是60位元組。但是這並還沒有完,因為乙太網在傳輸的時候,還有CRC檢驗的要求,傳送資料之前,網絡卡會對資料包進行CRC檢驗,將4位元組的CRC值附加到包頭的最後面。這個時候,我們的資料包長度已經不再是40位元組,而是變成了64位元組了。這時資料包的結構如下:
|              14位元組乙太網頭                           | 20位元組IP頭 |  20位元組TCP頭 |    6位元組填充      |   4位元組檢驗  |  
| 目的MAC地址 | 源MAC地址 | 上層協議型別 |       IP頭     |         TCP頭    |     乙太網填充   |    CRC檢驗   |

這些工作都做完了,網絡卡就開始傳送資料包了。但是遺憾的是,你在攻擊發起端使用一般的抓包工具,比如TcpDump,WireShark這些,是沒法看到這個過程的,這個過程只能由受攻擊的主機上抓包進行一些簡單的驗證。但是在被攻擊端使用類工具進行抓包,則可以明顯的看到,傳送的只有IP頭和TCP頭的SYN資料包,到達被攻擊的機器的時候,後面會多了6個位元組的0填充,這就是剛才所說的乙太網最小包長度填充了。比較遺憾的是,4位元組的CRC檢驗在網絡卡接受到資料包完成檢驗之後,就丟掉了,在被攻擊端也沒法使用常見的工具捕獲到。

也就是說,你填充的40位元組的報文在到達被攻擊機器網絡卡的時候,已經不是40位元組,而是64位元組了。

二. 乙太網傳輸

剛才我們說了在傳送時候網絡卡對資料包的填充等操作,但是還沒完,我們來看看攻擊資料包在網路上的傳輸過程。因為攻擊資料包很小,遠遠不夠最大傳輸單元(MTU)的1500位元組,因此不會被分片。難道這些資料包就像生產流水線上的罐頭一樣,一個包連著一個包緊密的擠在一起傳輸的嗎?事實上不是這樣的。

乙太網在傳輸的時候,還有前導碼(preamble)和幀間距(inter-frame gap)。其中前導碼佔8位元組(byte),64位元位。前導碼前面的7位元組都是10101010,1和0間隔而成。但是第八個位元組就變成了10101011,當主機監測到連續的兩個1的時候,就知道後面開始是資料了,首先是目的MAC地址等等,依次解析。也就是說,前導碼是告訴主機做好接收資料準備的。幀間距是乙太網資料包之間的間隙,幀間距的大小是12位元組(byte),96位元位。因此,在網路傳輸的時候,資料的結構如下:

| 8位元組前導碼 | 6位元組目的MAC地址 | 6位元組源MAC地址 | 2位元組上層協議型別 | 20位元組IP頭  | 20位元組TCP頭 | 6位元組乙太網填充 | 4位元組CRC檢驗 | 12位元組幀間距 |

也就是說,一個SYN包,在網路上傳輸的時候佔得頻寬,其實是84位元組。

三. 百兆線速或者千兆線速

有了上面的基礎,現在可以開始討論網路安全裝置的線速問題了,這裡的安全裝置可以是Anti-DDOS裝置,也可以是IDS,或者IPS等裝置。當只填充IP頭和TCP頭的最小SYN包跑在乙太網絡上的時候,100Mbit的網路,能支援的最大PPS是100*10^6 / (8 * (64 + 8 + 12)) = 148809 pps,1000Mbit的網路,能支援的最大PPS是1488090 pps。

當廠商來宣傳他們的安全裝置的時候,他們的資料是否和這些符合呢?他們的IDS支援的最大流量是怎麼計算的?包含了哪些內容?他們的Anti-DDOS裝置宣傳的線速是符合實際情況的嗎?是否真的能夠防禦相應的PPS的攻擊?當你和別人講,你們的IDS顯示你們遭受了N Gbit SYN Flood攻擊,PPS達到N百萬的時候,你真的遭受了大的攻擊嗎?

四. 總結以及參考

這是去年作DDOS防禦方面的專案時的一些心得筆記,今天週五沒太多事情,就整理一下發出來,或許對一些朋友有幫助。