syn flood (syn洪水) 是種典型的dos (denial of service,拒絕服務) 攻擊。效果就是伺服器tcp連線資源耗盡,停止響應正常的tcp連線請求。
說到原理,還得從tcp如何建立連線(connection)講起。通訊的雙方最少得經過3次成功的資訊交換才能進入連線全開狀態(full-open),行話叫建立tcp連線的3次握手(tcp three-way handshake)。
本文假設連線發起方是a,連線接受方是b,即b在某個埠(port)上監聽a發出的連線請求。如下圖所示,左邊是a,右邊是b。
a首先傳送syn(synchronization)訊息給b,要求b做好接收資料的準備;b收到後反饋syn-ack(synchronization-acknowledgement) 訊息給a,這個訊息的目的有兩個:(1) 向a確認已做好接收資料的準備,(2) 同時要求a也做好接收資料的準備,此時b已向a確認好接收狀態,並等待a的確認,連線處於半開狀態(half-open),顧名思義只開了一半;a收到後再次傳送ack(acknowledgement)訊息給b,向b確認也做好了接收資料的準備,至此三次握手完成,「連線」就建立了,實際上只是雙方都按對方的要求進入了可以接收訊息的狀態。以上彼此要求對方確認的「狀態」主要是雙方將要使用的訊息序號(sequencenum),tcp為保證訊息按傳送順序抵達接收方的上層應用,需要用訊息序號來標記訊息的傳送先後順序的。tcp是「雙工」(duplex)連線,同時支援雙向通訊,也就是雙方同時可向對方傳送訊息,其中syn和syn-ack訊息開啟了a→b的單向通訊通道(b獲知了a的訊息序號);syn-ack和ack訊息開啟了b→a單向通訊通道(a獲知了b的訊息序號)。
以上討論的是在雙方誠實可信,網路正常的理想狀況下建立連線。但實際情況是,網路可能不穩定會丟包,使握手訊息不能抵達對方,也可能是對方故意不按規矩來,故意延遲或不傳送握手確認訊息。假設b通過某tcp埠提供服務,b在收到a的syn訊息時,積極的反饋了syn-ack訊息,使連線進入半開狀態,因為b不確定自己發給a的syn-ack訊息或a反饋的ack訊息是否會丟在半路,所以會給每個待完成的半開連線都設乙個timer,如果超過時間還沒有收到a的ack訊息,則重新傳送一次syn-ack訊息給a,直到重試超過一定次數時才會放棄。
做好人是要付出代價的,b為幫助a能順利連線,需要分配核心資源維護半開連線,那麼當b面臨海量的大忽悠a時[1]
,如上圖所示,syn flood攻擊就形成了。攻擊方a可以控制肉雞向b傳送大量syn訊息但不響應ack訊息,或者乾脆偽造syn訊息中的source ip,使b反饋的syn-ack訊息石沉大海[2]
,導致b被大量注定不能完成的半開連線佔據,直到資源耗盡,停止響應正常的連線請求[3]
。接下來說說應對思路。最簡單粗暴的辦法就是提高tcp埠連線容量的同時減少半開連線的資源占用時間。在linux上可以修改以下配置提高tcp半開連線佇列大小的上限:
/proc/sys/net/ipv4/tcp_max_syn_backlog可以減少半開狀態下等待ack訊息的時間或者重試傳送syn-ack訊息的次數:
/proc/sys/net/ipv4/tcp_synack_retries抑或啟用某種半開連線**機制,使得當半開連線佇列滿了以後做「除舊迎新」操作,當然並不是所有系統都支援這種機制。
以上方法更像是權宜之計,只是緩解了被攻擊時的系統壓力,以及稍稍提高了些防禦門檻,但也同時影響了部分正常的請求的建立,比如減少syn-ack重試次數,同樣也會降低某些網路環境不好的正常使用者的連線成功率;而且攻擊者只要稍稍改變策略就可以提高攻擊效果,比如當使用半開連線**機制時,攻擊者只需提高攻擊頻率就可使大部分正常的等待的半開連線,在ack訊息到來前就被踢出佇列。
另乙個思路是將攻擊扼殺在搖籃,比如部署支援「ip防偽」的路由器,將偽造過ip位址的syn訊息過濾掉,或是提高網民防護意識減小肉雞網路的規模等,但這都太過理想,有些時候攻擊者都有高大上的背景,根本不需要攻擊前先抓肉雞,呵呵,***☺。
以上兩個思路都沒有直擊癥結所在--任何乙個syn訊息無論**是誰,都會消耗b的一些資源儲存半開狀態,並逐漸達到「鳩佔鵲巢」的效果。syn cache和syn cookies就是基於這個觀察提出的兩個方案。
syn cache的出發點主要是針對「鳩佔鵲巢」問題,基本原理如下:構造乙個全域性的hash table,用來快取系統當前所有的半開連線資訊,連線成功則從cache中清除相關資訊;hash table中每個桶(bucket)的容量大小也有限制,當桶「滿」時做除舊迎新操作。當b收到乙個syn訊息後,會將半開連線資訊加入到hash table中,其中key的生成很關鍵,既要用到syn訊息中包含的資訊(如:source ip,port等)又要做到很難被攻擊者猜到,一般會通過乙個秘密的函式生成,這樣所有的半開連線無論好壞,都看似隨機地被平均分配到了不同的「桶」中,使攻擊難度大增,因為為達到dos效果,攻擊者需要使每個桶都達到填滿狀態,並且還要有足夠快的「填桶」速度,使得正常的半開連線在還未完成建立前就被踢出桶,這樣的攻擊行為估計在達到目的前早就暴露了。
syn cookies著眼點主要是設法消除半開連線的資源消耗,原理與http cookies技術類似,b通過特定的演算法把半開連線資訊編碼成「cookie」,用作b給a的訊息編號(sequencenum),隨syn-ack訊息一同返回給連線發起方a,這樣在連線完全建立前b不儲存任何資訊。如果a是正常使用者,則會向b傳送最後一次握手訊息(ack),b收到後驗證「cookie」的內容並建立連線;如果a是攻擊者,則不會向b反饋ack訊息,b也沒任何損失,也就說是單純的syn攻擊不會造成b的連線資源消耗。當然這種方案也有一定缺點,最明顯的就是b不儲存連線的半開狀態,就喪失了重發syn-ack訊息的能力,這一方面會降低正常使用者的連線成功率,另一方面會導致某些情況下正常通訊的雙方會對連線是否成功開啟產生誤解,如a發給b的第三次握手訊息(ack)半路遺失,a認為連線成功了,b認為沒收到ack,連線沒成功,這種情況就需要上層應用採取策略特別處理了。
當然,所有這些方案都不完美各有利弊,最終的策略可能是幾種方案的結合使用,形成防禦體系,將攻擊提前化解在區域性,不至於影響整個系統。
[1] 實際攻擊時攻擊方不太會暴力的傳送大量syn訊息,這樣反倒會提前暴露自己,而是先嗅探出被攻擊物件的tcp配置引數,如半連線狀態過期時間,佇列上限等,掌握好節奏更量體裁衣的傳送攻擊訊息,做到用最經濟最不易被發現的方式鳩佔鵲巢,佔滿半連線佇列。
[2] 偽造source ip(ip spoofing)有一定講究,不能選乙個真實的有tcp連線能力的主機,因為tcp協議要求在收到莫名其妙的syn-ack訊息時,直接返回rst訊息,這反倒提示被攻擊的b可以提前中止假冒的半開連線,將其清理出佇列。
[3] 這裡指特定埠(port)的連線資源被耗盡不能接受新連線請求,埠上已經建立的連線和其他未被攻擊的埠不受影響。
SYN Flood攻擊及防禦方法
一 為什麼syn flood會造成危害 這要從作業系統的tcp ip協議棧的實現說起。當開放了乙個tcp埠後,該埠就處於listening狀態,不停地監視發到該埠的syn報文,一旦接收到client發來的syn報文,就需要為該請求分配乙個tcb transmission control block ...
SYN Flood 攻擊及防禦方法
一 為什麼syn flood會造成危害 這要從作業系統的tcp ip協議棧的實現說起。當開放了乙個tcp埠後,該埠就處於listening狀態,不停地監視發到該埠的syn報文,一旦接收到client發來的syn報文,就需要為該請求分配乙個tcb transmission control block ...
SYN Flood攻擊及防禦方法
syn flood攻擊及防禦方法 一 為什麼syn flood會造成危害 這要從計算機網路的tcp ip協議棧的實現說起。當開放了乙個tcp埠後,該埠就處於listening狀態,不停地監視發到該埠的syn報文,一旦接收到client發來的syn報文,就需要為該請求分配乙個tcb transmiss...