深刻淺出TCP中的SYN-Cookies

圖片描述

本文漸進地介紹 TCP中的 syn-cookie技術,包括其由來、原理、實例測試。

SYN Flood 攻擊

TCP鏈接創建時,客戶端經過發送SYN報文發起向處於監聽狀態的服務器發起鏈接,服務器爲該鏈接分配必定的資源,併發送SYN+ACK報文。對服務器來講,此時該鏈接的狀態稱爲半鏈接(Half-Open),而當其以後收到客戶端回覆的ACK報文後,鏈接纔算創建完成。在這個過程當中,若是服務器一直沒有收到ACK報文(好比在鏈路中丟失了),服務器會在超時後重傳SYN+ACK
圖片描述
若是通過屢次超時重傳後,尚未收到, 那麼服務器會回收資源並關閉半鏈接,彷彿以前最初的SYN報文歷來沒到過同樣!算法

圖片描述

這看上一切正常,可是若是有壞人故意大量不斷髮送僞造的SYN報文,那麼服務器就會分配大量註定無用的資源,而且從backlog的意義 中可知,服務器能保存的半鏈接的數量是有限的!因此當服務器受到大量攻擊報文時,它就不能再接收正常的鏈接了。換句話說,它的服務再也不可用了!這就是SYN Flood攻擊的原理,它是一種典型的DDoS攻擊。segmentfault

鏈接請求的關鍵信息

Syn-Flood攻擊成立的關鍵在於服務器資源是有限的,而服務器收到請求會分配資源。一般來講,服務器用這些資源保存這次請求的關鍵信息,包括請求的來源和目(五元組),以及TCP選項,如最大報文段長度MSS、時間戳timestamp、選擇應答使能Sack、窗口縮放因子Wscale等等。當後續的ACK報文到達,三次握手完成,新的鏈接建立,這些信息能夠會被複制到鏈接結構中,用來指導後續的報文收發。bash

那麼如今的問題就是服務器如何在不分配資源的狀況下服務器

  1. 驗證以後可能到達的ACK的有效性,保證這是一次完整的握手
  2. 得到SYN報文中攜帶的TCP選項信息

SYN cookies 算法

SYN Cookies算法wiki能夠解決上面的第1個問題以及第2個問題的一部分cookie

咱們知道,TCP鏈接創建時,雙方的起始報文序號是能夠任意的。SYN cookies利用這一點,按照如下規則構造初始序列號:併發

  • t爲一個緩慢增加的時間戳(典型實現是每64s遞增一次)
  • m爲客戶端發送的SYN報文中的MSS選項值
  • s是鏈接的元組信息(源IP,目的IP,源端口,目的端口)和t通過密碼學運算後的Hash值,即s = hash(sip,dip,sport,dport,t)s的結果取低 24

則初始序列號n爲:tcp

  • 5 位爲t mod 32
  • 接下來3位爲m的編碼值
  • 24 位爲s

當客戶端收到此SYN+ACK報文後,根據TCP標準,它會回覆ACK報文,且報文中ack = n + 1,那麼在服務器收到它時,將ack - 1就能夠拿回當初發送的SYN+ACK報文中的序號了!服務器巧妙地經過這種方式間接保存了一部分SYN報文的信息。測試

接下來,服務器須要對ack - 1這個序號進行檢查:編碼

  • 將高 5 位表示的t與當前之間比較,看其到達地時間是否能接受。
  • 根據t和鏈接元組從新計算s,看是否和低 24 一致,若不一致,說明這個報文是被僞造的。
  • 解碼序號中隱藏的mss信息

到此,鏈接就能夠順利創建了。spa

SYN Cookies 缺點

既然SYN Cookies能夠減少資源分配環節,那爲何沒有被歸入TCP標準呢?緣由是SYN Cookies也是有代價的:

  1. MSS的編碼只有3位,所以最多隻能使用 8MSS
  2. 服務器必須拒絕客戶端SYN報文中的其餘只在SYNSYN+ACK中協商的選項,緣由是服務器沒有地方能夠保存這些選項,好比WscaleSACK
  3. 增長了密碼學運算

Linux 中的 SYN Cookies

Linux上的SYN Cookies實現與wiki中描述的算法在序號生成上有一些區別,其SYN+ACK的序號經過下面的公式進行計算:

內核編譯須要打開 CONFIG_SYN_COOKIES
seq = hash(saddr, daddr, sport, dport, 0, 0) + req.th.seq + t << 24 + (hash(saddr, daddr, sport, dport, t, 1) + mss_ind) & 0x00FFFFFF

其中,req.th.seq表示客戶端的SYN報文中的序號,mss_ind是客戶端通告的MSS值得編碼,它的取值在比較新的內核中有 4 種(老的內核有 8 種), 分別對應如下 4 種值

static __u16 const msstab[] = {
    536,
    1300,
    1440,    /* 1440, 1452: PPPoE */
    1460,
};

感興趣的能夠順着如下軌跡瀏覽調用順序

tcp_conn_request
  |-- cookie_init_sequence
     |-- cookie_v4_init_sequence
        |-- __cookie_v4_init_sequence
           |-- secure_tcp_syn_cookie

SYN Cookies 與時間戳

若是服務器和客戶端打開了時間戳選項,那麼服務器能夠將客戶端在SYN報文中攜帶了TCP選項的使能狀況暫時保存在時間戳中。當前使用了低 6 位,分別保存WscaleSACKECN

圖片描述

客戶端會在ACKTSecr字段,把這些值帶回來。

實驗

Linux中的 /proc/sys/net/ipv4/tcp_syncookies是內核中的 SYN Cookies開關, 0表示關閉 SYN Cookies1表示在新鏈接壓力比較大時啓用 SYN Cookies, 2表示始終使用 SYN Cookies

本實驗是在4.4.0內核運行的,服務端監聽50001端口,backlog參數爲3(該參數意義)。同時,模擬不一樣的客戶端注入SYN報文。

測試代碼

不開啓 SYN Cookies

echo 0 > /proc/sys/net/ipv4/tcp_syncookies

能夠看到,在收到3SYN報文後,服務器再也不響應新的鏈接請求了,這也就是SYN-Flood的攻擊方式。
圖片描述

有條件使用 SYN Cookies

echo 1 > /proc/sys/net/ipv4/tcp_syncookies

圖片描述

因爲服務器的backlog參數爲3,所以圖中的從第4SYN+ACK(#8報文)開始使用SYN Cookies

從時間戳能夠看出,#8報文(44167748)比 #6號報文(44167796)還要小。

44167748 = 0x2A1F244 ,最後低6位是 0b000100 ,與SYN報文中 wscale = 4 是相符的

小結

SYN Cookie技術可讓服務器在收到客戶端的SYN報文時,不分配資源保存客戶端信息,而是將這些信息保存在SYN+ACK的初始序號和時間戳中。對正常的鏈接,這些信息會隨着ACK報文被帶回來。

REF

SYN Flood Attack
Improving syncookies

相關文章
相關標籤/搜索