SYN cookie 是一種用於阻止 SYN flood 攻擊的技術。這項技術的主要發明人 Daniel J. Bernstein 將 SYN cookies 定義為「TCP 伺服器進行的對開始TCP數據包序列數字的特定選擇」。舉例來說,SYN Cookies 的應用允許伺服器當 SYN 隊列被填滿時避免丟棄連接。相反,伺服器會表現得像 SYN 隊列擴大了一樣。伺服器會返回適當的 SYN+ACK 響應,但會丟棄 SYN 隊列條目。如果伺服器接收到客戶端隨後的ACK響應,伺服器能夠使用編碼在 TCP 序號內的信息重構 SYN 隊列條目。

實現

發起一個 TCP 連接時,客戶端將一個 TCP SYN 包發送給伺服器。作為響應,伺服器將 TCP SYN + ACK 包返回給客戶端。此數據包中有一個序號(sequence number,TCP頭中的第二個32 bit),它被 TCP 用來重新組裝數據流。根據 TCP 規範,由端點發送的第一個序號可以是由該端點決定的任何值。SYN Cookies 是根據以下規則構造的初始序號:

  • t 為一個緩慢遞增的時間戳(通常為 time() >> 6 ,提供 64 秒的解析度);
  • m 為伺服器會在 SYN 隊列條目中存儲的最大分段大小(maximum segment size,簡稱為 MSS);
  • s 為一個加密散列函數對伺服器和客戶端各自的 IP 地址和埠號以及 t 進行運算的結果。返回得到的數值 s 必須是一個24位值。

初始 TCP 序號,也就是所謂的 SYN cookie,按照如下算法得到:

  • 頭五位:t mod 32;
  • 中三位:m 編碼後的數值;
  • 末24位:s 本身;

註:由於 m 必須用 3 位進行編碼,伺服器在啟用了 SYN Cookie 時只能為 m 發送八種不同的數值。

根據 TCP 規範,當客戶端發回 TCP ACK 包給伺服器以響應伺服器的 SYN + ACK 包時,客戶端必須使用由伺服器發送的初始序號加1作為數據包中的確認號。伺服器接著從確認號中減去 1 以便還原向客戶端發送的原始 SYN Cookie。

接下來伺服器進行以下檢查:

  • 根據當前的時間以及 t 來檢查連接是否過期。
  • 重新計算 s 來確認這是不是一個有效的 SYN Cookie。
  • 從 3 位編碼中解碼 m,以便之後用來重建 SYN 隊列條目。在此之後,連接照常進行。

缺陷

SYN Cookies 的使用不與任何協議定義衝突,照理來說它該和所有的 TCP 實現兼容。然而,當 SYN Cookies 使用的時候,會發生兩種值得注意的變化:首先,伺服器只能編碼八種 MSS 數值,因為只有 3 位二進制空間可用。其次,這個伺服器必須拒絕所有的 TCP 選用項,例如大型窗口和時間戳,因為伺服器會在信息被用其他方式存儲時丟棄 SYN 隊列條目。 [1]

儘管這些限制將不可避免地導致一個不如最佳的體驗,它們的效果很少被客戶端注意到——這些改變只在被攻擊時值得注意。在這樣的情況下,犧牲 TCP 選項來保護連接一般被認為是合乎情理的。

Linux內核 從 2.6.26 版本開始為 TCP 選用項加入了有限的支持,通過把它們編碼在時間戳內實現。[2]

較新的 TCP Cookie 傳輸(TCPCT)標準被設計用來克服 SYN Cookies 的這些問題,並且在各種方面改進這套機制。不像 SYN Cookies,TCPCT 是一個 TCP 拓展並且要求兩端點都支持 TCPCT。

安全考量

被設置為允許所有出站連接但對入站連接有限制(例如在 Web 伺服器上只允許 80 埠)的簡單防火牆一般是這樣實現的:只阻斷不必要埠的 SYN 請求。如果 SYN Cookies 被啟動了,應當小心以保證攻擊者不能使用偽造 ACK、嘗試隨機序列號的方式來繞過這樣的防火牆。因此 SYN cookies 應該按照每個埠單獨處理的方式來調節開關,這樣的話一個公共埠上的 SYN Cookies 並不會在一個私有埠上被認可。[3]

歷史

Daniel J. BernsteinEric Schenk 於 1996 年九月創造了這個技術。Jeff Weisberg 在一個月後發布了最早的實現(在 SunOS 上),Eric Schenk 隨後在 1997 年二月發布了他的 Linux 實現(目前的實現使用,例如 net.ipv4.tcp_syncookies頁面存檔備份,存於網際網路檔案館))。

參見

參考資料

  1. ^ [1]頁面存檔備份,存於網際網路檔案館), cr.yp.to September 1996
  2. ^ Patrick McManus, Improving Syncookies頁面存檔備份,存於網際網路檔案館), lwn.net April 2008
  3. ^ 存档副本. [2013-03-17]. (原始內容存檔於2013-04-13).