TCP協議中報文詳解

TCP協議中報文SYN、ACK、FIN、RST、PSH、URG詳解
1、 SYN:同步連接序號,TCP SYN報文就是把這個標誌設置爲1,來請求建立連接;
2、 ACK:請求/應答狀態。0爲請求,1爲應答;
3、 FIN:結束連線。如果FIN爲0是結束連線請求,FIN爲1表示結束連線;
4、 RST:連線復位,首先斷開連接,然後重建;
5、 PSH:通知協議棧儘快把TCP數據提交給上層程序處理。
6、 URG : 緊急標誌置位。

三次握手Three-way Handshake

一個虛擬連接的建立是通過三次握手來實現的

1. (B) --> [SYN] --> (A)

假如服務器A和客戶機B通訊. A要和B通信時,B首先向A發一個SYN (Synchronize) 標記的包,告訴A請求建立連接.

注意: 一個 SYN包就是僅SYN標記設爲1TCP(參見TCP包頭Resources). 認識到這點很重要,只有當A受到B發來的SYN包,纔可建立連接,除此之外別無他法。因此,如果你的防火牆丟棄所有的發往外網接口的SYN包,那麼你將不能讓外部任何主機主動建立連接。

2. (B) <-- [SYN/ACK] <--(A)

接着,A收到後會發一個對SYN包的確認包(SYN/ACK)回去,表示對第一個SYN包的確認,並繼續握手操作.

注意: SYN/ACK包是僅SYN ACK 標記爲1的包.

3. (B) --> [ACK] --> (A)

B
收到SYN/ACK ,B發一個確認包(ACK),通知A連接已建立。至此,三次握手完成,一個TCP連接完成

Note: ACK
包就是僅ACK 標記設爲1TCP. 需要注意的是當三此握手完成、連接建立以後,TCP連接的每個包都會設置ACK

這就是爲何連接跟蹤很重要的原因了. 沒有連接跟蹤,防火牆將無法判斷收到的ACK包是否屬於一個已經建立的連接.一般的包過濾(Ipchains)收到ACK包時,會讓它通過(這絕對不是個好主意). 而當狀態型防火牆收到此種包時,它會先在連接表中查找是否屬於哪個已建連接,否則丟棄該包

四次握手Four-way Handshake

四次握手用來關閉已建立的TCP連接

1. (B) --> ACK/FIN --> (A)

2. (B) <-- ACK <-- (A)

3. (B) <-- ACK/FIN <-- (A)

4. (B) --> ACK --> (A)

注意: 由於TCP連接是雙向連接, 因此關閉連接需要在兩個方向上做。ACK/FIN (ACK FIN 標記設爲1)通常被認爲是FIN(終結).然而, 由於連接還沒有關閉, FIN包總是打上ACK標記. 沒有ACK標記而僅有FIN標記的包不是合法的包,並且通常被認爲是惡意的

連接復位Resetting a connection

四次握手不是關閉TCP連接的唯一方法. 有時,如果主機需要儘快關閉連接(或連接超時,端口或主機不可達),RST (Reset)包將被髮送. 注意在,由於RST包不是TCP連接中的必須部分, 可以只發送RST(即不帶ACK標記). 但在正常的TCP連接中RST包可以帶ACK確認標記

請注意RST包是可以不要收到方確認的?

無效的TCP標記Invalid TCP Flags

到目前爲止,你已經看到了 SYN, ACK, FIN, RST 標記. 另外,還有PSH (Push) URG (Urgent)標記.

最常見的非法組合是SYN/FIN . 注意:由於 SYN包是用來初始化連接的, 它不可能和 FINRST標記一起出現. 這也是一個惡意攻擊.

由於現在大多數防火牆已知 SYN/FIN , 別的一些組合,例如SYN/FIN/PSH, SYN/FIN/RST, SYN/FIN/RST/PSH。很明顯,當網絡中出現這種包時,很你的網絡肯定受到攻擊了。

別的已知的非法包有FIN (ACK標記)"NULL"包。如同早先討論的,由於ACK/FIN包的出現是爲了關閉一個TCP連接,那麼正常的FIN包總是帶有 ACK 標記。"NULL"包就是沒有任何TCP標記的包(URG,ACK,PSH,RST,SYN,FIN都爲0)

到目前爲止,正常的網絡活動下,TCP協議棧不可能產生帶有上面提到的任何一種標記組合的TCP包。當你發現這些不正常的包時,肯定有人對你的網絡不懷好意。

UDP (
用戶數據包協議User Datagram Protocol)
TCP
是面向連接的,而UDP是非連接的協議。UDP沒有對接受進行確認的標記和確認機制。對丟包的處理是在應用層來完成的。(or accidental arrival).

此處需要重點注意的事情是:在正常情況下,當UDP包到達一個關閉的端口時,會返回一個UDP復位包。由於UDP是非面向連接的, 因此沒有任何確認信息來確認包是否正確到達目的地。因此如果你的防火牆丟棄UDP包,它會開放所有的UDP端口(?)

由於Internet上正常情況下一些包將被丟棄,甚至某些發往已關閉端口(非防火牆的)UDP包將不會到達目的,它們將返回一個復位UDP包。

因爲這個原因,UDP端口掃描總是不精確、不可靠的。

看起來大UDP包的碎片是常見的DOS (Denial of Service)攻擊的常見形式 (這裏有個DOS攻擊的例子,http://grc.com/dos/grcdos.htm ).

ICMP (
網間控制消息協議Internet Control Message Protocol)
如同名字一樣, ICMP用來在主機/路由器之間傳遞控制信息的協議。 ICMP包可以包含診斷信息(ping, traceroute - 注意目前unix系統中的tracerouteUDP包而不是ICMP),錯誤信息(網絡/主機/端口不可達 network/host/port unreachable), 信息(時間戳timestamp, 地址掩碼address mask request, etc.),或控制信息 (source quench, redirect, etc.)

你可以在http://www.iana.org/assignments/icmp-parameters中找到ICMP包的類型。

儘管ICMP通常是無害的,還是有些類型的ICMP信息需要丟棄。

Redirect (5), Alternate Host Address (6), Router Advertisement (9)
能用來轉發通訊。

Echo (8), Timestamp (13) and Address Mask Request (17)
能用來分別判斷主機是否起來,本地時間和地址掩碼。注意它們是和返回的信息類別有關的。它們自己本身是不能被利用的,但它們泄露出的信息對攻擊者是有用的。

ICMP
消息有時也被用來作爲DOS攻擊的一部分(例如:洪水ping flood ping, ping ?呵呵,有趣 ping of death)?/p>

包碎片注意A Note About Packet Fragmentation

如果一個包的大小超過了TCP的最大段長度MSS (Maximum Segment Size) MTU (Maximum Transmission Unit),能夠把此包發往目的的唯一方法是把此包分片。由於包分片是正常的,它可以被利用來做惡意的攻擊。

因爲分片的包的第一個分片包含一個包頭,若沒有包分片的重組功能,包過濾器不可能檢測附加的包分片。典型的攻擊Typical attacks involve in overlapping the packet data in which packet header is 典型的攻擊Typical attacks involve in overlapping the packet data in which packet header isnormal until is it overwritten with different destination IP (or port) thereby bypassing firewall rules。包分片能作爲 DOS 攻擊的一部分,它可以crash older IP stacks 或漲死CPU連接能力。

Netfilter/Iptables
中的連接跟蹤代碼能自動做分片重組。它仍有弱點,可能受到飽和連接攻擊,可以把CPU資源耗光。

握手階段:
序號方向 seq ack
1
  A->B 10000 0
2 B->A 20000 10000+1=10001
3 A->B 10001 20000+1=20001
解釋:
1
AB發起連接請求,以一個隨機數初始化Aseq,這裏假設爲10000,此時ACK0

2
B收到A的連接請求後,也以一個隨機數初始化Bseq,這裏假設爲20000,意思是:你的請求我已收到,我這方的數據流就從這個數開始。BACKAseq1,即10000110001

3
A收到B的回覆後,它的seq是它的上個請求的seq1,即10000110001,意思也是:你的回覆我收到了,我這方的數據流就從這個數開始。A此時的ACKBseq1,即20000+1=20001


數據傳輸階段:
序號  方向      seq ack size
23 A->B 40000 70000 1514
24 B->A 70000 40000+1514-54=41460 54
25 A->B 41460 70000+54-54=70000 1514
26 B->A 70000 41460+1514-54=42920 54
解釋:
23:B
接收到A發來的seq=40000,ack=70000,size=1514的數據包
24:
於是BA也發一個數據包,告訴B,你的上個包我收到了。Bseq就以它收到的數據包的ACK填充,ACK是它收到的數據包的SEQ加上數據包的大小(不包括以太網協議頭,IP頭,TCP),以證實B發過來的數據全收到了。
25:A
在收到B發過來的ack41460的數據包時,一看到41460,正好是它的上個數據包的seq加上包的大小,就明白,上次發送的數據包已安全到達。於是它再發一個數據包給B。這個正在發送的數據包的seq也以它收到的數據包的ACK填充,ACK就以它收到的數據包的seq(70000)加上包的size(54)填充,ack=70000+54-54(全是頭長,沒數據項)

其實在握手和結束時確認號應該是對方序列號加1,傳輸數據時則是對方序列號加上對方攜帶應用層數據的長度.如果從以太網包返回來計算所加的長度,就嫌走彎路了.
另外,如果對方沒有數據過來,則自己的確認號不變,序列號爲上次的序列號加上本次應用層數據發送長度.

在TCP/IP協議中,TCP協議提供可靠的連接服務,採用三次握手建立一個連接,如圖1所示。

(1)第一次握手:建立連接時,客戶端A發送SYN包(SYN=j)到服務器B,並進入SYN_SEND狀態,等待服務器B確認。

(2)第二次握手:服務器B收到SYN包,必須確認客戶A的SYN(ACK=j+1),同時自己也發送一個SYN包(SYN=k),即SYN+ACK包,此時服務器B進入SYN_RECV狀態。

(3)第三次握手:客戶端A收到服務器B的SYN+ACK包,向服務器B發送確認包ACK(ACK=k+1),此包發送完畢,客戶端A和服務器B進入ESTABLISHED狀態,完成三次握手。

完成三次握手,客戶端與服務器開始傳送數據。

圖1 TCP三次握手建立連接

由於TCP連接是全雙工的,因此每個方向都必須單獨進行關閉。這個原則是當一方完成它的數據發送任務後就能發送一個FIN來終止這個方向的連接。收到一個 FIN只意味着這一方向上沒有數據流動,一個TCP連接在收到一個FIN後仍能發送數據。首先進行關閉的一方將執行主動關閉,而另一方執行被動關閉。

(1)客戶端A發送一個FIN,用來關閉客戶A到服務器B的數據傳送(報文段4)。

(2)服務器B收到這個FIN,它發回一個ACK,確認序號爲收到的序號加1(報文段5)。和SYN一樣,一個FIN將佔用一個序號。

(3)服務器B關閉與客戶端A的連接,發送一個FIN給客戶端A(報文段6)。

(4)客戶端A發回ACK報文確認,並將確認序號設置爲收到序號加1(報文段7)。

TCP採用四次揮手關閉連接如圖2所示。

圖2 TCP四次揮手關閉連接

1.爲什麼建立連接協議是三次握手,而關閉連接卻是四次握手呢?

這是因爲服務端的LISTEN狀態下的SOCKET當收到SYN報文的建連請求後,它可以把ACK和SYN(ACK起應答作用,而SYN起同步作用)放在一個報文裏來發送。但關閉連接時,當收到對方的FIN報文通知時,它僅僅表示對方沒有數據發送給你了;但未必你所有的數據都全部發送給對方了,所以你可以未必會馬上會關閉SOCKET,也即你可能還需要發送一些數據給對方之後,再發送FIN報文給對方來表示你同意現在可以關閉連接了,所以它這裏的ACK報文和FIN報文多數情況下都是分開發送的。

2.爲什麼TIME_WAIT狀態還需要等2MSL後才能返回到CLOSED狀態?

這是因爲雖然雙方都同意關閉連接了,而且握手的4個報文也都協調和發送完畢,按理可以直接回到CLOSED狀態(就好比從SYN_SEND狀態到ESTABLISH狀態那樣);但是因爲我們必須要假想網絡是不可靠的,你無法保證你最後發送的ACK報文會一定被對方收到,因此對方處於LAST_ACK狀態下的SOCKET可能會因爲超時未收到ACK報文,而重發FIN報文,所以這個TIME_WAIT狀態的作用就是用來重發可能丟失的ACK報文。

TCP 狀態機

TCP 協議的操作可以使用一個具有 11 種狀態的有限狀態機( Finite State Machine )來表示,圖 3-12 描述了 TCP 的有限狀態機,圖中的圓角矩形表示狀態,箭頭表示狀態之間的轉換,各狀態的描述如表 3-2 所示。圖中用粗線表示客戶端主動和被動的服務器端建立連接的正常過程:客戶端的狀態變遷用粗實線,服務器端的狀態變遷用粗虛線。細線用於不常見的序列,如復位、同時打開、同時關閉等。圖中的每條狀態變換線上均標有“事件/動作”:事件是指用戶執行了系統調用( CONNECT 、 LISTEN 、 SEND 或 CLOSE )、收到一個報文段( SYN 、 FIN 、 ACK 或 RST )、或者是出現了超過兩倍最大的分組生命期的情況;動作是指發送一個報文段( SYN 、 FIN 或 ACK )或什麼也沒有(用“-”表示)。

每個連接均開始於 CLOSED 狀態。當一方執行了被動的連接原語( LISTEN )或主動的連接原語( CONNECT )時,它便會脫離 CLOSED 狀態。如果此時另一方執行了相對應的連接原語,連接便建立了,並且狀態變爲 ESTABLISHED 。任何一方均可以首先請求釋放連接,當連接被釋放後,狀態又回到了 CLOSED 。

表 3-2 TCP 狀態表

狀 態

描 述

CLOSED

關閉狀態,沒有連接活動或正在進行

LISTEN

監聽狀態,服務器正在等待連接進入

SYN RCVD

收到一個連接請求,尚未確認

SYN SENT

已經發出連接請求,等待確認

ESTABLISHED

連接建立,正常數據傳輸狀態

FIN WAIT 1

(主動關閉)已經發送關閉請求,等待確認

FIN WAIT 2

(主動關閉)收到對方關閉確認,等待對方關閉請求

TIMED WAIT

完成雙向關閉,等待所有分組死掉

CLOSING

雙方同時嘗試關閉,等待對方確認

CLOSE WAIT

(被動關閉)收到對方關閉請求,已經確認

LAST ACK

(被動關閉)等待最後一個關閉確認,並等待所有分組死掉

1. 正常狀態轉換

我們用圖 3-13 來顯示在正常的 TCP 連接的建立與終止過程中,客戶與服務器所經歷的不同狀態。讀者可以對照圖 3-12 來閱讀,使用圖 3-12 的狀態圖來跟蹤圖 3-13 的狀態變化過程,以便明白每個狀態的變化:

· 服務器端首先執行 LISTEN 原語進入被動打開狀態( LISTEN ),等待客戶端連接;

· 當客戶端的一個應用程序發出 CONNECT 命令後,本地的 TCP 實體爲其創建一個連接記錄並標記爲 SYN SENT 狀態,然後給服務器發送一個 SYN 報文段;

· 服務器收到一個 SYN 報文段,其 TCP 實體給客戶端發送確認 ACK 報文段同時發送一個 SYN 信號,進入 SYN RCVD 狀態;

· 客戶端收到 SYN + ACK 報文段,其 TCP 實體給服務器端發送出三次握手的最後一個 ACK 報文段,並轉換爲 ESTABLISHED 狀態;

· 服務器端收到確認的 ACK 報文段,完成了三次握手,於是也進入 ESTABLISHED 狀態。

在此狀態下,雙方可以自由傳輸數據。當一個應用程序完成數據傳輸任務後,它需要關閉 TCP 連接。假設仍由客戶端發起主動關閉連接。

· 客戶端執行 CLOSE 原語,本地的 TCP 實體發送一個 FIN 報文段並等待響應的確認(進入狀態 FIN WAIT 1 );

· 服務器收到一個 FIN 報文段,它確認客戶端的請求發回一個 ACK 報文段,進入 CLOSE WAIT 狀態;

· 客戶端收到確認 ACK 報文段,就轉移到 FIN WAIT 2 狀態,此時連接在一個方向上就斷開了;

· 服務器端應用得到通告後,也執行 CLOSE 原語關閉另一個方向的連接,其本地 TCP 實體向客戶端發送一個 FIN 報文段,並進入 LAST ACK 狀態,等待最後一個 ACK 確認報文段;

· 客戶端收到 FIN 報文段並確認,進入 TIMED WAIT 狀態,此時雙方連接均已經斷開,但 TCP 要等待一個 2 倍報文段最大生存時間 MSL ( Maximum Segment Lifetime ),確保該連接的所有分組全部消失,以防止出現確認丟失的情況。當定時器超時後, TCP 刪除該連接記錄,返回到初始狀態( CLOSED )。

· 服務器收到最後一個確認 ACK 報文段,其 TCP 實體便釋放該連接,並刪除連接記錄,返回到初始狀態( CLOSED )。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章