TCP: SYN ACK FIN RST PSH URG 詳解
三次握手Three-way Handshake
一個虛擬鏈接的創建是經過三次握手來實現的
1. (B) --> [SYN] --> (A)
假如服務器A和客戶機B通信. 當A要和B通訊時,B首先向A發一個SYN (Synchronize) 標記的包,告訴A請求創建鏈接.
注意: 一個 SYN包就是僅SYN標記設爲1的TCP包(參見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 標記設爲1的TCP包. 須要注意的是當三此握手完成、鏈接創建之後,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包是用來初始化鏈接的, 它不可能和 FIN和RST標記一塊兒出現. 這也是一個惡意***.
因爲如今大多數防火牆已知 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端口掃描老是不精確、不可靠的。
ICMP (網間控制消息協議Internet Control Message Protocol)
如同名字同樣, ICMP用來在主機/路由器之間傳遞控制信息的協議。 ICMP包能夠包含診斷信息(ping, traceroute - 注意目前unix系統中的traceroute用UDP包而不是ICMP),錯誤信息(網絡/主機/端口 不可達 network/host/port unreachable), 信息(時間戳timestamp, 地址掩碼address mask request, etc.),或控制信息 (source quench, redirect, etc.) 。
儘管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:A向B發起鏈接請求,以一個隨機數初始化A的seq,這裏假設爲10000,此時ACK=0
2:B收到A的鏈接請求後,也以一個隨機數初始化B的seq,這裏假設爲20000,意思是:你的請求我已收到,我這方的數據流就從這個數開始。B的ACK是A的seq加1,即10000+1=10001
3:A收到B的回覆後,它的seq是它的上個請求的seq加1,即10000+1=10001,意思也是:你的回覆我收到了,我這方的數據流就從這個數開始。A此時的ACK是B的seq加1,即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:因而B向A也發一個數據包,告訴B,你的上個包我收到了。B的seq就以它收到的數據包的ACK填充,ACK是它收到的數據包的SEQ加上數據包的大小(不包括以太網協議頭,IP頭,TCP頭),以證明B發過來的數據全收到了。
25:A在收到B發過來的ack爲41460的數據包時,一看到41460,正好是它的上個數據包的seq加上包的大小,就明白,上次發送的數據包已安全到達。因而它再發一個數據包給B。這個正在發送的數據包的seq也以它收到的數據包的ACK填充,ACK就以它收到的數據包的seq(70000)加上包的size(54)填充,即ack=70000+54-54(全是頭長,沒數據項)。
其實在握手和結束時確認號應該是對方序列號加1,傳輸數據時則是對方序列號加上對方攜帶應用層數據的長度.若是從以太網包返回來計算所加的長度,就嫌走彎路了. 另外,若是對方沒有數據過來,則本身的確認號不變,序列號爲上次的序列號加上本次應用層數據發送長度.