TCP的連接和終止
TCP是一個面向連接的協議。在傳輸數據前必須要建立連接,在停止傳輸數據后要終止連接釋放資源。
一.TCP連接建立
TCP連接是在IP網絡中兩個進程間(應用層協議)的雙向、全雙工的邏輯回路。由節點的IP地址和端口將連接雙方對應起來。
1.TCP連接特點:
- 通過一個握手進程建立起來;
- 通過一個周期性保持進程來保持,保證兩個TCP節點間處于激活狀態;
- 通過一個握手進程來終止,釋放資源。
- TCP連接也被連接中的任意一端重置。
1.TCP連接的建立
為了建立連接TCP連接雙方必須從對方了解下面的信息:
- 1.對方數據發送的開始序列號;
- 2.對方在出站管道上發送數據的緩沖區大小;
- 3.能被接收的最大段MSS;
- 4.被支持的TCP選項;
通
過3個TCP段的交換來了解這些信息,就是常說的TCP
握手的3個包。一般在客戶端訪問TCP服務器的時候,在客戶端初始化一個TCP連接,服務器端打開一個特殊端口等待傳入的請求。客戶端主動發起第一個
SYN置位的包開始協商TCP連接。服務器接收后向客戶端回ACK,最后客戶端在向服務器回復ACK后連接建立。
下面我們用TCP連接的兩個對等端A和B來詳細介紹握手過程,其中發起方是A。
- 段一:同步(SYN)段
TCP連接的發起方A向B發送第一個TCP同步段(SYN).在TCP頭部的選項中會包含一些選項與對端協商。
TCP 頭部包含如下字段:
目的端口 TCP連接對端B被動打開的TCP端口數
源端口 TCP連接發起方A主動打開的端口,大多數是一個隨機一個端口。
序列號 SYN的序列號ISN1可以看作是一個32位的計數器,由發起方A產生,具有一定的隨機性。Windows 2003和XP根據派生啟動(startup-derived)、2048位的隨機密鑰和一個基于RC4的隨機數來計算ISN,從而減少下一TCP連接的 ISN被預測的可能性。
確認號 設置為0.SYN握手第一個包的ACK字段不重要,此時剛發起連接沒有數據報需要確認。但后續的ACK是重要的。
SYN標志 置1.
窗口 設置為默認值,指示本地TCP接收緩沖區大小的初始值。
MSS TCP選項中的MSS 指示發起方A接收的最大的TCP段。
選擇性確認(SACK) –TCP選項 如果包含這個字段,可以指示發起方A 的TCP能接收和解釋此選項。
窗口縮放選項 如果包含,指示出發起方A的TCP能接收和支持此選項。協商好窗口因子后此連接就固定使用直到斷開連接
一個FTP會話的SYN段 - 段二:SYN-ACK段
在B收到SYN包后,B將發SYN-ACK,TCP選項僅包含發起方A發送的SYN包中的的選項。
目的端口 設置為A的源端口
源端口 設置為B端口
序列號 B產生自己的序列號ISN2。和A發送的SYN中的ISN沒有關系,僅產生的方法一樣。
確認號 期望收到的對端的下一個字節ISN1+1.
SYN標志 置1.
ACK標志 置1,必須有此標志,除了SYN中置0外,SYN之后的所有報文(包括SYN-ACK和實際數據包都會帶ACK的標志)。
窗口 設置B可以接收的最大窗口值,一般根據應用程序或者操作系統默認指定。
MSS TCP選項 設為B能接收的最大長度的TCP段;
SACK-許可 如果A發送的SYN包含此選項時才使用此選項,表示B的TCP能接收和解釋SACK選項。
窗口縮放選項 如果SYN包含,此時才會包含。
一個FTP會話的SYN-ACK段 - 段3:ACK段
在TCP連接的發起方A收到SYN-ACK后,A再向B發送ACK。ACK中確認被發起方A使用的最終TCP參數,同時向B確認它該使用同樣的參數。自此TCP連接建立完成。
一個FTP會話的SYN-ACK段
2.同時打開
兩個應用程序同時執行主動建立TCP的連接的可能性是存在的,此時發送到SYN建立需要交換4個包,如圖所示:
需要注意的是,即使同時打開仍然只建立一條連接。(但其他的協議不一定)
3.TCP 連接的結果
- 1.每一個TCP對等端知道連接上對方將被發送的第一個字節的序列號(發給對方的確認號,A發給B的確認號就是B將發送的序列號,同樣B也是。)
- 2.每一個TCP對等端知道連接上能發送的MSS。選取握手階段SYN和SYN+ACK包中MSS選項中較小的值。以此值開始進行PMTU的發現機制。
- 3.知道連接對端接收緩沖區大小,即窗口大小。
- 4.每個對等端知道對方能否使用SACK,窗口縮放等選項。
4.Windows控制TCP建立連接進程的注冊表:
TcpMaxConnectRetransmissions
Location:HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters
Data Type:REG_DWORD
Valid range:0~255
Default value:2
Present by default:No
設定當試圖建立一個TCP連接時,會重傳多少次SYN。每次間隔時間加倍。初始的RTO為3秒,并且默認值為2,這樣第一次SYN等待3秒后重傳第一次,在等待6秒后重傳第二次,在等待12秒沒有SYN+ACK就超時了。
TcpNumConnections
Location:HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters
Data Type:REG_DWORD
Valid range:0~0xFFFFFF
Default value:0xFFFFFF
Present by default:No
設定能打開的TCP最大數。默認能打開16777214(0xFFFFFF)個連接。
5.TCP半開連接
TCP
半開連接是未完成的連接建立的進程的一個TCP連接,收到一個SYN包,并且一個SYN-ACK已經發送,但是最后的ACK沒有收到。前面知道XP默認設
置情況下在發送2個重傳SYN-ACK后等待12秒后放棄連接,并釋放內存和連接的內部表項,從收到SYN到釋放總共會花費21秒。
SYN-ACK重傳輸的一個半開連接
- SYN攻擊
SYN攻擊就是利用這種方法,使用偽裝的IP地址和TCP端口,在短時間內制造大量的半開連接來耗盡資源,造成拒絕服務攻擊。大量的半開連接能做如下事情:
1.使用所有可用的內存,
2.使用在TCP傳輸控制模塊(TCB)中所有可能的項,這是一個用來跟蹤TCP連接的內部表,一旦半開連接使用完所有的項,就用一個TCP連接復位來響應下一個連接企圖。
3.使用所有可能的半開連接,此后用一個TCP連接復位響應下一個連接企圖。
可以使用netstat -n -p tcp 查看TCP連接狀態,包括半開連接。如果state出現大量的SYN-RECEIVED就該受到SYN攻擊了。
Windows xp和2003 在檢測和防護SYN攻擊方面的注冊表:
TcpMaxConnectResponseRetransmissions
Location:HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters
Data Type:REG_DWORD
Valid range:0~255
Default value:2
Present by default:No
設定針對半開連接的一個AYN-ACK的重傳數目,對于大于1的值使用SYN攻擊防護機制。
SynAttackProtect
Location:HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters
Data Type:REG_DWORD
Valid range:0~1
Default value:0
Present by default:No
設置為0禁用SYN攻擊防護,1啟用SYN攻擊防護。被啟用時,檢測到SYN攻擊,則半開連接的超時會更快些。
TcpMaxHalfOpen
Location:HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters
Data Type:REG_DWORD
Valid range:100~65535
Default value:100 for windows xp 和Windows 2003 web版及標準版,500 for Windows 2003 企業版和數據中心版
Present by default:No
在SYN攻擊防護起作用前,此鍵值設定了在SYN-RECEIVED狀態中的TCP鏈接最大數。
TcpMaxHalfOpenRetried
Location:HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters
Data Type:REG_DWORD
Valid range:80~65535
Default value:80 for windows xp 和Windows 2003 web版及標準版,400 for Windows 2003 企業版和數據中心版
Present by default:No
在SYN-RECEIVED狀態中設定TCP連接的最大數并且在SYN攻擊防護起作用前至少發送過一個重傳。
6.TCP連接的維持
在 建立TCP連接后,必須有一些機制維持TCP連接。如果TCP建立連接后不傳輸任何數據也沒有應用級別的保活機制時,那么TCP連接一直存在,數天,數月 會一直存在。中間的路由器可能重啟,崩潰,TCP連接的雙方無從知道,許多時候一個服務器希望知道客戶主機是否崩潰并關機或者崩潰又重新啟動。許多實現提 供的保活定時器可以提供這種能力。但這個規范并不推薦,理由如下:
- 在出現短暫差錯的情況下,這可能會使一個非常好的連接釋放掉;
- 它們耗費不必要的帶寬;
- 在按分組計費的情況下會在互聯網上花掉更多的錢。
TCP保活定時器(keepalive)
Windows 中TCP通過一個TCP keepalive的周期性交換,能維持一個TCP連接。在keepalive的TCP頭部序列號字段被設為比當前出站數據流的序列號小1的值。如果一個 TCP對等端的下一個數據的字節序列號是N,那么keepalive的序列號是N-1.
在接收到keepalive包后,對等端回送一個ACK字段,并將確認號置為下一個期望收到的字節N,這個交換證實了兩個對等端仍然處于TCP連接狀態中。
Windows 2003 和 XP的TCP/IP在默認情況下禁用TCP的keepalive.啟用情況下每2個小時發送一次keepalive。如果其他上層協議的保活機制時間小于keepalive,tcp的keepalive將不會發送。
相關注冊表
KeepAliveTime
Location:HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters
Data Type:REG_DWORD
Valid range:0~0xFFFFFFFF
Default value:0x6DDD00 (2小時)
Present by default:No
如果連接上沒有沒有數據,并且啟用keepalive,此鍵值在每一個TCP保持活躍包之間設置了毫秒數,默認是2小時。
KeepAliveInterval
Location:HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters
Data Type:REG_DWORD
Valid range:0~0xFFFFFFFF
Default value:0x3E8 (1000毫秒)
Present by default:No
在沒有接收到對初始的保持活躍的響應時,此鍵值設置了重傳時間默認是1秒。重傳數目受TcpMaxDataRetransmission鍵值控制,默認是5.此時的重傳不會有指數級的回退行為。
如果都啟用且是默認,無數據傳輸的TCP連接在keepalive包發出后2小時6秒收不到ACK就放棄連接。
舉例:
另一端崩潰
keepalive機制在重復發送探測包到一定次數后報錯,由TCP轉換為“連接超時”
另一端崩潰而重啟
客戶端telnet到服務器后,我們拔掉服務器網線重啟服務器,服務器重啟好后我們在telnet客戶端上輸入命令。服務器重啟后丟失了以前連接的所有信息,此時服務器收到來著telnet客戶端的命令,不知道此連接的信息,于是TCP就以復位作為應答來結束TCP連接。
另外一端不可達
拔掉網線,模擬中間路由器崩潰,keepalive探測的時候會引起ICMP差錯“不可達--沒有到達主機的路由”反饋給主機。
二.TCP連接的終止
TCP的連接終止需要4個包交換來完成。在兩個邏輯管道上每個邏輯管道上發送方發送FIN置位的終止包,然后收到ACK后關閉該邏輯管道的連接。
TCP連接終止的4個TCP段交換過程
段1:來自TCP對等端A的FIN-ACK
一個期望終止出站數據流的TCP對等端(A)發送一個不包含任何數據的TCP段,他具有如下特點:
- 序列號,和發送帶數據TCP段一樣設置為出站數據的當前序列號,且當前序列號是最終序列號FSN1,因為馬上要關閉了。
- 確認序列號 被設為TCP對等端A期望對方發送的下一個字節。對應TCP對等端B當前序列號CSN2。
- 設置ACK標志
- 設置FIN標志,指示此邏輯管道上沒有其他數據需要發送。
段2:來自TCP對等端B的ACK
與SYN類似,FIN包也會占用一個字節的序列空間,并且必須把它當作是一個字節數據來確認。所以B接收到FIN-ACK后必須發送一個ACK,具有如下特點:
- 序列號 設為出站數據的當前序列號CSN2
- 確認號字段被設為比對端A發送的最終序列號多1的值FSN1+1.
- 設置ACK標志。
一旦FIN-ACK被確認,發送初始FIN-ACK端A就不能再發送數據了,這僅終止了一個邏輯管道的連接,TCP對等端B發送數據到A的邏輯管道仍然開放,B仍然可以發數據給A。
段三:來自TCP對等端B的FIN-ACK
前面對等端A向B發送數據的邏輯管道被關閉后,如果B向A發送數據的邏輯管道仍然有數據發送,且被對等端A確認,這就是TCP半關閉。TCP對等端B向A發送數據的邏輯管道沒有數據發送后,也要B向A發送FIN-ACK來關閉。
特點:
- 序列號,和發送帶數據TCP段一樣設置為出站數據的當前序列號,且當前序列號最終序列號FSN2,因為馬上要關閉了。
- 確認序列號 被設為TCP對等端A期望對方發送的下一個字節。對應TCP對等端A當前序列號FSN1+1。
- 設置ACK標志
- 設置FIN標志,指示此邏輯管道上沒有其他數據需要發送

ftp客戶端關閉FTP會話的Fin-ack段
段四:來自TCP對等端A的ACK
同樣段三的FIN-ACK包也按占用了一個字節算,并且必須作為一個字節的數據被確認。因此收到FIN-ACK的A必須發送一個ACK。
具有如下特點:
- 序列號 設為出站數據的當前序列號FSN1+1
- 確認號字段被設為比對端B發送的最終序列號多1的值FSN2+1
- 設置ACK標志。
當來自A的ACK被B接收后,TCP連接上的B向A發送數據的邏輯管道就會被關閉,此時經過四次握手后,整個TCP連接才會被完整關閉。
但在有些實現中段二和段段三被合并。其過程就是FIN-ACK/FIN-ACK/ACK,此時中間的FIN-ACK中的ACK是對第一個FIN-ACK的確認。
同時關閉
雙方都執行主動關閉也是可能的,TCP協議也允許這樣的同時關閉(simultaneous close)。雙方各發送一個FIN,兩個FIN經過網絡傳送后分別到達另一端。收到FIN后,兩端發送最后的ACK。當收到最后的A C K時,關閉TCP連接.
同時關閉的報文段交換
TCP連接的復位(Reset)
TCP連接終止進程適用于一個TCP連接的兩個管道在互相同意的情況下正常關閉。另外一種終止TCP連接的方式是通過TCP連接復位—一個具有RST(Reset)標志的TCP段來完成。
當一個不可調和的入站TCP段的TCP頭中存在參數問題時,一個TCP連接復位就會被發送。例如,不恰當的源IP地址、目的IP地址或者TCP端口號都能中斷一個建立了的連接。中斷的TCP連接將丟失所有的TCP數據,包括正在傳送中或者在等待被發送的緩沖區中。
TCP也用來拒絕一個TCP連接企圖,以響應對SYN段的接收。最常見的是,SYN段中目的端口與運行在SYN段接收者上的應用層進程相對應。當達到被允許的最大值時,連接企圖就會被拒絕。下圖顯示了TCP連接復位
一個顯示SYN和RST段的TCP連接的復位
注意:當UDP到達一個與應用層進程不對應的目的端口時,會產生一個ICMP,目的不可達-端口不可達的報錯發送給UDP數據發送方。
抓包截圖顯示了在一臺運行FTP客戶端和一臺非FTP服務器主機之間的包交換。幀一是一個到FTP控制端口的SYN段,幀二是連接復位。
在連接復位段中:
1.設置了RST和ACK標志
2.序列號為0
3.確認號比SYN段的序列號多1
4.窗口大小是0.
三 TCP連接狀態
TCP連接狀態和說明:
狀態 | 說明 |
CLOSED | 不存在TCP連接 |
LISTEN | 一個應用層協議已經發布了一個被動打開,并且有意接收TCP連接企圖 |
SYN SENT | 一個應用層協議已經發布一個主動打開,并且發送一個SYN段 |
SYN RCVD | 一個SYN段被接收,并且一個SYN-ACK被發送 |
ESTABLISHED | 建立TCP連接的3此握手完成。現在數據能雙向傳輸 |
FIN WAIT-1 | 初始的關閉連接段的FIN-ACK被發送 |
FIN WAIT-2 | 響應初始的FIN-ACK的ACK被接收 |
CLOSING | 一個FIN-ACK被接收但ACK不是針對已發送的FIN-ACK的。收到的FIN-ACK中的是針對已發送的FINA-ACK被稱為同時關閉,這時兩個TCP對等端在相同時刻發送FIN-ACK。 |
TIME WAIT | FIN- ACK已被發送并得到兩個對等端的確認,并且TCP連接終止進程完成。一旦到達TIME WAIT狀態,在連接的TCP端口能被重新使用前,TCP必須等待的時間是最大生存時間(MSL)的兩倍。MSL是在互聯網中一個TCP段能存在時間的最 大值,推薦是240秒。這個延遲防止一個使用相同端口的連接的TCP段與舊連接的TCP段的副本相混淆 |
CLOSE WAIT | 一個FIN-ACK被接收,并且一個FIN-ACK被發送 |
LAST ACK | 響應FIN-ACK的ACK已被接收 |
TCP狀態變遷圖
一個TCP對等端經過的連接狀態依賴于TCP對等端是TCP連接建立的初始化方還是TCP連接終止的初始化方。
TCP連接圖和終止圖
原文: http://ustb-618.spaces.live.com/default.aspx