在TCP實(shí)現(xiàn)中,當(dāng)收到客戶端的SYN請(qǐng)求時(shí),服務(wù)器需要回復(fù)SYN+ACK包給客戶端,客戶端也要發(fā)送確認(rèn)包給服務(wù)器。通常,服務(wù)器的初始序列號(hào)由服務(wù)器按照一定的規(guī)律計(jì)算得到或采用隨機(jī)數(shù),但在SYN cookies中,服務(wù)器的初始序列號(hào)是通過對(duì)客戶端IP地址、客戶端端囗、服務(wù)器IP地址和服務(wù)器端囗以及其他一些安全數(shù)值等要素進(jìn)行hash運(yùn)算,加密得到的,稱之為cookie。當(dāng)服務(wù)器遭受SYN攻擊使得backlog隊(duì)列滿時(shí),服務(wù)器并不拒絕新的SYN請(qǐng)求,而是回復(fù)cookie(回復(fù)包的SYN序列號(hào))給客戶端, 如果收到客戶端的ACK包,服務(wù)器將客戶端的ACK序列號(hào)減去1得到cookie比較值,并將上述要素進(jìn)行一次hash運(yùn)算,看看是否等于此cookie。如果相等,直接完成三次握手(注意:此時(shí)并不用查看此連接是否屬于backlog隊(duì)列)。
在RedHat linux中,啟用SYN cookies是通過在啟動(dòng)環(huán)境中設(shè)置以下命令來完成:
# echo 1 > /proc/sys/net/ipv4/tcp_syncookies
■ 增加最大半連接數(shù)
大量的SYN請(qǐng)求導(dǎo)致未連接隊(duì)列被塞滿,使正常的TCP連接無法順利完成三次握手,通過增大未連接隊(duì)列空間可以緩解這種壓力。當(dāng)然backlog隊(duì)列需要占用大量的內(nèi)存資源,不能被無限的擴(kuò)大。
WIN2000:除了上面介紹的TcpMaxHalfOpen, TcpMaxHalfOpenRetried參數(shù)外,WIN2000操作系統(tǒng)可以通過設(shè)置動(dòng)態(tài)backlog(dynamic backlog)來增大系統(tǒng)所能容納的最大半連接數(shù),配置動(dòng)態(tài)backlog由AFD.SYS驅(qū)動(dòng)完成,AFD.SYS是一種內(nèi)核級(jí)的驅(qū)動(dòng),用于支持基于window socket的應(yīng)用程序,比如ftp、telnet等。AFD.SYS在注冊(cè)表的位置:
HKLM\System\CurrentControlSet\Services\AFD\ParametersEnableDynamicBacklog值為1時(shí),表示啟用動(dòng)態(tài)backlog,可以修改最大半連接數(shù)?!?
MinimumDynamicBacklog表示半連接隊(duì)列為單個(gè)TCP端囗分配的最小空閑連接數(shù),當(dāng)該TCP端囗在backlog隊(duì)列的空閑連接小于此臨界值時(shí),系統(tǒng)為此端囗自動(dòng)啟用擴(kuò)展的空閑連接(DynamicBacklogGrowthDelta),Microsoft推薦該值為20。
MaximumDynamicBacklog是當(dāng)前活動(dòng)的半連接和空閑連接的和,當(dāng)此和超過某個(gè)臨界值時(shí),系統(tǒng)拒絕SYN包,Microsoft推薦MaximumDynamicBacklog值不得超過2000。
DynamicBacklogGrowthDelta值是指擴(kuò)展的空閑連接數(shù),此連接數(shù)并不計(jì)算在MaximumDynamicBacklog內(nèi),當(dāng)半連接隊(duì)列為某個(gè)TCP端囗分配的空閑連接小于MinimumDynamicBacklog時(shí),系統(tǒng)自動(dòng)分配DynamicBacklogGrowthDelta所定義的空閑連接空間,以使該TCP端囗能處理更多的半連接。Microsoft推薦該值為10。
LINUX:Linux用變量tcp_max_syn_backlog定義backlog隊(duì)列容納的最大半連接數(shù)。在Redhat 7.3中,該變量的值默認(rèn)為256,這個(gè)值是遠(yuǎn)遠(yuǎn)不夠的,一次強(qiáng)度不大的SYN攻擊就能使半連接隊(duì)列占滿。我們可以通過以下命令修改此變量的值:
# sysctl -w net.ipv4.tcp_max_syn_backlog="2048"
Sun Solaris Sun Solaris用變量tcp_conn_req_max_q0來定義最大半連接數(shù),在Sun Solaris 8中,該值默認(rèn)為1024,可以通過add命令改變這個(gè)值:
# ndd -set /dev/tcp tcp_conn_req_max_q0 2048
HP-UX:HP-UX用變量tcp_syn_rcvd_max來定義最大半連接數(shù),在HP-UX 11.00中,該值默認(rèn)為500,可以通過ndd命令改變默認(rèn)值:
?。dd -set /dev/tcp tcp_syn_rcvd_max 2048
■縮短超時(shí)時(shí)間
上文提到,通過增大backlog隊(duì)列能防范SYN攻擊;另外減少超時(shí)時(shí)間也使系統(tǒng)能處理更多的SYN請(qǐng)求。我們知道,timeout超時(shí)時(shí)間,也即半連接存活時(shí)間,是系統(tǒng)所有重傳次數(shù)等待的超時(shí)時(shí)間總和,這個(gè)值越大,半連接數(shù)占用backlog隊(duì)列的時(shí)間就越長,系統(tǒng)能處理的SYN請(qǐng)求就越少。為縮短超時(shí)時(shí)間,可以通過縮短重傳超時(shí)時(shí)間(一般是第一次重傳超時(shí)時(shí)間)和減少重傳次數(shù)來實(shí)現(xiàn)。
Win2000第一次重傳之前等待時(shí)間默認(rèn)為3秒,為改變此默認(rèn)值,可以通過修改網(wǎng)絡(luò)接囗在注冊(cè)表里的TcpInitialRtt注冊(cè)值來完成。重傳次數(shù)由TcpMaxConnectResponseRetransmissions 來定義,注冊(cè)表的位置是:HKLM\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters registry key。
當(dāng)然我們也可以把重傳次數(shù)設(shè)置為0次,這樣服務(wù)器如果在3秒內(nèi)還未收到ack確認(rèn)包就自動(dòng)從backlog隊(duì)列中刪除該連接條目。
LINUX:Redhat使用變量tcp_synack_retries定義重傳次數(shù),其默認(rèn)值是5次,總超時(shí)時(shí)間需要3分鐘。
Sun Solaris Solaris 默認(rèn)的重傳次數(shù)是3次,總超時(shí)時(shí)間為3分鐘,可以通過ndd命令修改這些默認(rèn)值。