天天看點

關于網站的SYN_RECV攻擊的防範措施

偶管的blog伺服器syn攻擊了。

SYN攻擊是最常見又最容易被利用的一種攻擊手法。相信很多人還記得2000年YAHOO網站遭受的攻擊事例,當時黑客利用的就是簡單而有效的SYN攻擊,有些網絡蠕蟲病毒配合SYN攻擊造成更大的破壞。本文介紹SYN攻擊的基本原理、工具及檢測方法,并全面探讨SYN攻擊防範技術。

一、TCP握手協定

在TCP/IP協定中,TCP協定提供可靠的連接配接服務,采用三次握手建立一個連接配接。

第一次握手:建立連接配接時,用戶端發送syn包(syn=j)到伺服器,并進入SYN_SEND狀态,等待伺服器确認;

第二次握手:伺服器收到syn包,必須确認客戶的SYN(ack=j+1),同時自己也發送一個SYN包(syn=k),即SYN+ACK包,此時伺服器進入SYN_RECV狀态;

第三次握手:用戶端收到伺服器的SYN+ACK包,向伺服器發送确認包ACK(ack=k+1),此包發送完畢,用戶端和伺服器進入ESTABLISHED狀态,完成三次握手。

(TCP 連接配接示意圖)

(TCP 關閉示意圖)

完成三次握手,用戶端與伺服器開始傳送資料,在上述過程中,還有一些重要的概念:

未連接配接隊列:在三次握手協定中,伺服器維護一個未連接配接隊列,該隊列為每個用戶端的SYN包(syn=j)開設一個條目,該條目表明伺服器已收到SYN包,并向客戶發出确認,正在等待客戶的确認包。這些條目所辨別的連接配接在伺服器處于Syn_RECV狀态,當伺服器收到客戶的确認包時,删除該條目,伺服器進入 ESTABLISHED狀态。

Backlog參數:表示未連接配接隊列的最大容納數目。

SYN-ACK 重傳次數 伺服器發送完SYN-ACK包,如果未收到客戶确認包,伺服器進行首次重傳,等待一段時間仍未收到客戶确認包,進行第二次重傳,如果重傳次數超過系統規定的最大重傳次數,系統将該連接配接資訊從半連接配接隊列中删除。注意,每次重傳等待的時間不一定相同。

半連接配接存活時間:是指半連接配接隊列的條目存活的最長時間,也即服務從收到SYN包到确認這個封包無效的最長時間,該時間值是所有重傳請求包的最長等待時間總和。有時我們也稱半連接配接存活時間為Timeout時間、SYN_RECV存活時間。

二、SYN攻擊的基本原理

SYN攻擊屬于DOS攻擊的一種,它利用TCP協定缺陷,通過發送大量的半連接配接請求,耗費CPU和記憶體資源。SYN攻擊除了能影響主機外,還可以危害路由器、防火牆等網絡系統,事實上SYN攻擊并不管目标是什麼系統,隻要這些系統打開TCP服務就可以實施。從上圖可看到,伺服器接收到連接配接請求(syn= j),将此資訊加入未連接配接隊列,并發送請求包給客戶(syn=k,ack=j+1),此時進入SYN_RECV狀态。當伺服器未收到用戶端的确認包時,重發請求包,一直到逾時,才将此條目從未連接配接隊列删除。配合IP欺騙,SYN攻擊能達到很好的效果,通常,用戶端在短時間内僞造大量不存在的IP位址,向伺服器不斷地發送syn包,伺服器回複确認包,并等待客戶的确認,由于源位址是不存在的,伺服器需要不斷的重發直至逾時,這些僞造的SYN包将長時間占用未連接配接隊列,正常的SYN請求被丢棄,目标系統運作緩慢,嚴重者引起網絡堵塞甚至系統癱瘓。

三、SYN攻擊工具

SYN攻擊實作起來非常的簡單,網際網路上有大量現成的SYN攻擊工具。

windows系統下的SYN工具

以synkill.exe為例,運作工具,選擇随機的源位址和源端囗,并填寫目标機器位址和TCP端囗,激活運作,很快就會發現目标系統運作緩慢。如果攻擊效果不明顯,可能是目标機器并未開啟所填寫的TCP端囗或者防火牆拒絕通路該端囗,此時可選擇允許通路的TCP端囗,通常,windows系統開放 tcp139端囗,UNIX系統開放tcp7、21、23等端囗。

四、檢測SYN攻擊

檢測SYN攻擊非常的友善,當你在伺服器上看到大量的半連接配接狀态時,特别是源IP位址是随機的,基本上可以斷定這是一次SYN攻擊。我們使用系統自帶的netstat 工具來檢測SYN攻擊:

  # netstat -n -p TCP

  tcp 0  0 10.11.11.11:23  124.173.152.8:25882  SYN_RECV -

  tcp 0  0 10.11.11.11:23  236.15.133.204:2577  SYN_RECV -

  tcp 0  0 10.11.11.11:23  127.160.6.129:51748  SYN_RECV -

  tcp 0  0 10.11.11.11:23  222.220.13.25:47393  SYN_RECV -

  tcp 0  0 10.11.11.11:23  212.200.204.182:60427 SYN_RECV -

  tcp 0  0 10.11.11.11:23  232.115.18.38:278   SYN_RECV -

  tcp 0  0 10.11.11.11:23  239.116.95.96:5122  SYN_RECV -

  tcp 0  0 10.11.11.11:23  236.219.139.207:49162 SYN_RECV -

上面是在LINUX系統中看到的,很多連接配接處于SYN_RECV狀态(在WINDOWS系統中是SYN_RECEIVED狀态),源IP位址都是随機的(也可能是同一個IP的很多SYN_RECV連接配接狀态),表明這是一種帶有IP欺騙的SYN攻擊。

我們也可以通過下面的指令直接檢視在LINUX環境下某個端囗的未連接配接隊列的條目數:

  #netstat –atun | grep SYN_RECV | grep :80 | wc -l

顯示TCP端囗80的未連接配接數請求及個數,雖然還遠達不到系統極限,但應該引起管理者的注意。

五、SYN攻擊防範技術

關于SYN攻擊防範技術,人們研究得比較早。歸納起來,主要有兩大類,一類是通過防火牆、路由器等過濾網關防護,另一類是通過加強TCP/IP協定棧防範.但必須清楚的是,SYN攻擊不能完全被阻止,我們所做的是盡可能的減輕SYN攻擊的危害,除非将TCP協定重新設計。

1、過濾網關防護

這裡,過濾網關主要指明防火牆,當然路由器也能成為過濾網關。防火牆部署在不同網絡之間,防範外來非法攻擊和防止保密資訊外洩,它處于用戶端和伺服器之間,利用它來防護SYN攻擊能起到很好的效果。過濾網關防護主要包括逾時設定,SYN網關和SYN代理三種。

■網關逾時設定:防火牆設定SYN轉發逾時參數(狀态檢測的防火牆可在狀态表裡面設定),該參數遠小于伺服器的timeout時間。當用戶端發送完SYN 包,服務端發送确認包後(SYN+ACK),防火牆如果在計數器到期時還未收到用戶端的确認包(ACK),則往伺服器發送RST包,以使伺服器從隊列中删去該半連接配接。值得注意的是,網關逾時參數設定不宜過小也不宜過大,逾時參數設定過小會影響正常的通訊,設定太大,又會影響防範SYN攻擊的效果,必須根據所處的網絡應用環境來設定此參數。

■SYN網關:SYN網關收到用戶端的SYN包時,直接轉發給伺服器;SYN網關收到伺服器的SYN/ACK包後,将該包轉發給用戶端,同時以用戶端的名義給伺服器發ACK确認包。此時伺服器由半連接配接狀态進入連接配接狀态。當用戶端确認包到達時,如果有資料則轉發,否則丢棄。事實上,伺服器除了維持半連接配接隊列外,還要有一個連接配接隊列,如果發生SYN攻擊時,将使連接配接隊列數目增加,但一般伺服器所能承受的連接配接數量比半連接配接數量大得多,是以這種方法能有效地減輕對伺服器的攻擊。

■SYN代理:當用戶端SYN包到達過濾網關時,SYN代理并不轉發SYN包,而是以伺服器的名義主動回複SYN/ACK包給客戶,如果收到客戶的ACK 包,表明這是正常的通路,此時防火牆向伺服器發送ACK包并完成三次握手。SYN代理事實上代替了伺服器去處理SYN攻擊,此時要求過濾網關自身具有很強的防範SYN攻擊能力。

2、加強tcp/ip協定棧

防範SYN攻擊的另一項主要技術是調整tcp/ip協定棧,修改tcp協定實作。主要方法有SynAttackProtect保護機制、SYN cookies技術、增加最大半連接配接和縮短逾時時間等。tcp/ip協定棧的調整可能會引起某些功能的受限,管理者應該在進行充分了解和測試的前提下進行此項工作。

■ SynAttackProtect機制 (針對windows作業系統)

為防範SYN攻擊,win2000系統的tcp/ip協定棧内嵌了SynAttackProtect機制,Win2003系統也采用此機制。 SynAttackProtect機制是通過關閉某些socket選項,增加額外的連接配接訓示和減少逾時時間,使系統能處理更多的SYN連接配接,以達到防範 SYN攻擊的目的。預設情況下,Win2000作業系統并不支援SynAttackProtect保護機制,需要在系統資料庫以下位置增加 SynAttackProtect鍵值:

  HKLM/SYSTEM/CurrentControlSet/Services/Tcpip/Parameters

當SynAttackProtect值(如無特别說明,本文提到的系統資料庫鍵值都為十六進制)為0或不設定時,系統不受SynAttackProtect保護。

當SynAttackProtect值為1時,系統通過減少重傳次數和延遲未連接配接時路由緩沖項(route cache entry)防範SYN攻擊。

當SynAttackProtect值為2時(Microsoft推薦使用此值),系統不僅使用backlog隊列,還使用附加的半連接配接訓示,以此來處理更多的SYN連接配接,使用此鍵值時,tcp/ip的TCPInitialRTT、window size和可滑動窗囗将被禁止。

我們應該知道,平時,系統是不啟用SynAttackProtect機制的,僅在檢測到SYN攻擊時,才啟用,并調整tcp/ip協定棧。那麼系統是如何檢測SYN攻擊發生的呢?事實上,系統根據TcpMaxHalfOpen,TcpMaxHalfOpenRetried 和TcpMaxPortsExhausted三個參數判斷是否遭受SYN攻擊。

TcpMaxHalfOpen 表示能同時處理的最大半連接配接數,如果超過此值,系統認為正處于SYN攻擊中。Win2000 server預設值為100,Win2000 Advanced server為500。

TcpMaxHalfOpenRetried定義了儲存在backlog隊列且重傳過的半連接配接數,如果超過此值,系統自動啟動 SynAttackProtect機制。Win2000 server預設值為80,Win2000 Advanced server為400。

TcpMaxPortsExhausted 是指系統拒絕的SYN請求包的數量,預設是5。

如果想調整以上參數的預設值,可以在系統資料庫裡修改(位置與SynAttackProtect相同)

■ SYN cookies技術

我們知道,TCP協定開辟了一個比較大的記憶體空間backlog隊列來存儲半連接配接條目,當SYN請求不斷增加,并這個空間,緻使系統丢棄SYN連接配接。為使半連接配接隊列被塞滿的情況下,伺服器仍能處理新到的SYN請求,SYN cookies技術被設計出來。

SYN cookies應用于linux、FreeBSD等作業系統,當半連接配接隊列滿時,SYN cookies并不丢棄SYN請求,而是通過加密技術來辨別半連接配接狀态。

在TCP實作中,當收到用戶端的SYN請求時,伺服器需要回複SYN+ACK包給用戶端,用戶端也要發送确認包給伺服器。通常,伺服器的初始序列号由伺服器按照一定的規律計算得到或采用随機數,但在SYN cookies中,伺服器的初始序列号是通過對用戶端IP位址、用戶端端囗、伺服器IP位址和伺服器端囗以及其他一些安全數值等要素進行hash運算,加密得到的,稱之為cookie。當伺服器遭受SYN攻擊使得backlog隊列滿時,伺服器并不拒絕新的SYN請求,而是回複cookie(回複包的 SYN序列号)給用戶端,如果收到用戶端的ACK包,伺服器将用戶端的ACK序列号減去1得到cookie比較值,并将上述要素進行一次hash運算,看看是否等于此 cookie。如果相等,直接完成三次握手(注意:此時并不用檢視此連接配接是否屬于backlog隊列)。

在RedHat linux中,啟用SYN cookies是通過在啟動環境中設定以下指令來完成:

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

注:也可以通過修改其它參數,或者使用/proc/sys/net/ipv4/netfilter/ip_contrack_*

■ 增加最大半連接配接數(加大未連接配接隊列空間)

大量的SYN請求導緻未連接配接隊列被塞滿,使正常的TCP連接配接無法順利完成三次握手,通過增大未連接配接隊列空間可以緩解這種壓力。當然backlog隊列需要占用大量的記憶體資源,不能被無限的擴大。

WIN2000:除了上面介紹的TcpMaxHalfOpen, TcpMaxHalfOpenRetried參數外,WIN2000作業系統可以通過設定動态backlog(dynamic backlog)來增大系統所能容納的最大半連接配接數,配置動态backlog由AFD.SYS驅動完成,AFD.SYS是一種核心級的驅動,用于支援基于 window socket的應用程式,比如ftp、telnet等。AFD.SYS在系統資料庫的位置:

HKLM/System/CurrentControlSet/Services/AFD/ParametersEnableDynamicBacklog

值為1時,表示啟用動态backlog,可以修改最大半連接配接數。 

MinimumDynamicBacklog表示半連接配接隊列為單個TCP端囗配置設定的最小空閑連接配接數,當該TCP端囗在backlog隊列的空閑連接配接小于此臨界值時,系統為此端囗自動啟用擴充的空閑連接配接(DynamicBacklogGrowthDelta),Microsoft推薦該值為20。

MaximumDynamicBacklog是目前活動的半連接配接和空閑連接配接的和,當此和超過某個臨界值時,系統拒絕SYN包,Microsoft推薦MaximumDynamicBacklog值不得超過2000。

DynamicBacklogGrowthDelta值是指擴充的空閑連接配接數,此連接配接數并不計算在MaximumDynamicBacklog内,當半連接配接隊列為某個TCP端囗配置設定的空閑連接配接小于MinimumDynamicBacklog時,系統自動配置設定 DynamicBacklogGrowthDelta所定義的空閑連接配接空間,以使該TCP端囗能處理更多的半連接配接。Microsoft推薦該值為10。

LINUX:Linux用變量tcp_max_syn_backlog定義backlog隊列容納的最大半連接配接數。在Redhat 7.3中,該變量的值預設為256,在AS中,是1024。這個值是遠遠不夠的,一次強度不大的SYN攻擊就能使半連接配接隊列占滿。我們可以通過以下指令修改此變量的值:

  # sysctl -w net.ipv4.tcp_max_syn_backlog="2048"

Sun Solaris Sun Solaris用變量tcp_conn_req_max_q0來定義最大半連接配接數,在Sun Solaris 8中,該值預設為1024,可以通過add指令改變這個值:

  # ndd -set /dev/tcp tcp_conn_req_max_q0 2048

HP-UX:HP-UX用變量tcp_syn_rcvd_max來定義最大半連接配接數,在HP-UX 11.00中,該值預設為500,可以通過ndd指令改變預設值:

  #ndd -set /dev/tcp tcp_syn_rcvd_max 2048

■ 縮短逾時時間

上文提到,通過增大backlog隊列能防範SYN攻擊;另外減少逾時時間也使系統能處理更多的SYN請求。我們知道,timeout逾時時間,也即半連接配接存活時間,是系統所有重傳次數等待的逾時時間總和,這個值越大,半連接配接數占用backlog隊列的時間就越長,系統能處理的SYN請求就越少。為縮短逾時時間,可以通過縮短重傳逾時時間(一般是第一次重傳逾時時間)和減少重傳次數來實作。

Win2000第一次重傳之前等待時間預設為3秒,為改變此預設值,可以通過修改網絡接口在系統資料庫裡的TcpInitialRtt注冊值來完成。重傳次數由TcpMaxConnectResponseRetransmissions 來定義,系統資料庫的位置是:HKLM/SYSTEM/CurrentControlSet/Services/Tcpip/Parameters registry key。

當然我們也可以把重傳次數設定為0次,這樣伺服器如果在3秒内還未收到ack确認包就自動從backlog隊列中删除該連接配接條目。

LINUX:Redhat使用變量tcp_synack_retries定義重傳次數,其預設值是5次,總逾時時間需要3分鐘。

# sysctl -w net.ipv4.tcp_synack_retries="0"

Sun Solaris Solaris 預設的重傳次數是3次,總逾時時間為3分鐘,可以通過ndd指令修改這些預設值。

綜合上述的方法:在linux下可以通過修改/etc/ sysctl.conf,添加下列選項達到效果。

## add by geminis for syn crack

net.ipv4.tcp_syncookies = 1

net.ipv4.tcp_max_syn_backlog="2048"

net.ipv4.tcp_synack_retries="1"

六.編寫bash腳本進行防範(我的方法是統計同一個IP的狀态包并處理)

#!/bin/sh

## 定義變量

MAX_TOTAL_SYN_RECV="1000"

MAX_PER_IP_SYN_RECV="20"

MARK="SYN_RECV"

PORT="80"

LOGFILE="/var/log/netstat_$MARK-$PORT"

LOGFILE_IP="/var/log/netstat_connect_ip.log"

DROP_IP_LOG="/var/log/netstat_syn_drop_ip.log"

## iptables初始化,拒絕非法包和不明狀态的包,允許請求包和已經連接配接的包進入

iptables -F -t filter

iptables -A INPUT -p TCP ! --syn -m state --state NEW -j DROP

iptables -A INPUT -p ALL -m state --state INVALID -j DROP

iptables -A INPUT -p ALL -m state --state ESTABLISHED,RELATED -j ACCEPT

## 初始化變量

if [ -z $MARK ];then

MARK="LISTEN"

fi

if [ -z $PORT ];then

SPORT="tcp"

else

SPORT=":$PORT"

######################## end

## 儲存netstat結果到指定記錄檔案中便于分析

netstat -atun|grep $MARK|grep $SPORT 2>/dev/null >$LOGFILE

REPEAT_CONNECT_IP=`less $LOGFILE|awk '{print $5}'|cut -f1 -d ':'|sort|uniq -d |tee > $LOGFILE_IP`

## 如果IP記錄檔案不為空,則從原來的記錄檔案中讀取記錄并添加規則

if [ -s $DROP_IP_LOG ];then

for i in `less $DROP_IP_LOG|awk '{print $1}'`;do

/sbin/iptables -A INPUT -p ALL -s $i -j DROP

done

for i in `less $LOGFILE_IP`;do

## 統計同一個IP在在的SYN_RECV狀态

REPEAT_CONNECT_NUM=`grep $i $LOGFILE|wc -l`

## 如果超過了預設的同一個IP的連接配接數,就拒絕此IP的連接配接包進入

if [ $REPEAT_CONNECT_NUM -gt $MAX_PER_IP_SYN_RECV ];then

echo "$i $REPEAT_CONNECT_NUM" >> $DROP_IP_LOG

iptables -A INPUT -p ALL -s $i -j DROP

## 統計所有狀态為SYN_RECV狀态的資料包,如果數量超過預設,就重置狀态。

ALL_CONNECT=`uniq -u $LOGFILE|wc -l`

echo $ALL_CONNECT

## count repeat connections ,if the accout is large than default number,then drop packages

if [ $ALL_CONNECT -gt $MAX_TOTAL_SYN_RECV ];then

exit

課外知識:

這些記錄會使得一些 log 統計分析軟體在統計的時候出現錯誤警告,同時我們也不希望經常被這些掃描者所騷擾,于是就試着寫了一個腳本,把 apache 的 log 中的這些 IP 位址讀取出來,以便以後在做 Iptables 的時候可以使用。腳本代碼:

######## Ver 0.2

# ==== NULL.ida掃描者IP排序腳本

### null.ida_stat.sh, Ver. 0.2 2004/05/18 13:41:32 Kreny

LOG_FILE1='/usr/local/apache2/logs/www.domain1.com-access_log'

LOG_FILE2='/usr/local/apache2/logs/www.domain2.com-access_log'

# You can add more log files here.

#LOG_FILE3='/usr/local/apache2/logs/www.domain3.com-access_log'

#LOG_FILE4='/usr/local/apache2/logs/www.domain4.com-access_log'

#LOG_FILE5='/usr/local/apache2/logs/www.domain5.com-access_log'

FINAL_FILE='/home/user/public_html/log/ida.txt'

DATE=`date`

# Rank the IP addresses of NULL.IDA scanner

## Add your LOG_FILEs after the $LOG_FILE2

less $LOG_FILE1 $LOG_FILE2 | grep NULL.IDA | awk '{print $1}'| sort | uniq -c | sort -rn > $FINAL_FILE

echo "" >> $FINAL_FILE

echo "Last update:".$DATE >> $FINAL_FILE

# ========= 僅列出IP位址 (感謝 随風漂 指導)=====

####### null.ida_stat.sh, Ver. 0.2 2004/05/18 13:41:32 Kreny #######

####### Only List the Scanner's IPs #######

FINAL_FILE='/home/user/public_html/log/ida_ip.txt'

awk '/NULL.IDA/{print $1}' $LOG_FILE1 $LOG_FILE2 | sort -u > $FINAL_FILE

### Ver 0.1 #########################

### null.ida_stat.sh, Ver. 0.1 2004/05/15 14:33:28 Kreny

### You can add more log files here.

TMP_FILE='/home/user/public_html/log/ida.tmp'

### Get the IP addresses of NULL.IDA scanner

less $LOG_FILE1 | grep NULL.IDA | awk '{print $1}' > $TMP_FILE

less $LOG_FILE2 | grep NULL.IDA | awk '{print $1}' >> $TMP_FILE

#less $LOG_FILE3 | grep NULL.IDA | awk '{print $1}' >> $TMP_FILE

#less $LOG_FILE4 | grep NULL.IDA | awk '{print $1}' >> $TMP_FILE

#less $LOG_FILE5 | grep NULL.IDA | awk '{print $1}' >> $TMP_FILE

sort $TMP_FILE | uniq -c | sort -rn > $FINAL_FILE

應用在其他方面

awk 的強大功能可以運用在更多的地方,例如通過檢查在qmailscaner的病毒隔離目錄中的郵件,得出發郵件主機的IP位址,以便在Iptables 中進行一些設定。檢視我的統計記錄

代碼:

less /var/spool/qmailscan/quarantine/new/*| grep 'HELO' | awk '{print $6}' | cut -d /( -f2 | cut -d /) -f1 | sort | uniq -c | sort -rn > /home/kreny/public_html/viruse_smtp.txt

echo 'Last Update:' >> /home/kreny/public_html/viruse_smtp.txt

date >> /home/kreny/public_html/viruse_smtp.txt

還有很多問題沒有解決,比如說提出了病毒郵件的ip address以後,怎麼樣自動加到iptables裡面去,是否可以用shell指令解決,之類等等。

繼續閱讀