一、OSI七層模型與TCP/IP協(xié)議簡(jiǎn)介
OSI模型(Open System Interconnection Reference Model,縮寫為OSI),全名“開放式系統(tǒng)互聯(lián)通信參考模型”,是一個(gè)試圖使各種計(jì)算機(jī)在全世界范圍內(nèi)互聯(lián)為網(wǎng)絡(luò)的標(biāo)準(zhǔn)框架疫向。
TCP/IP協(xié)議族(TCP/IP Protocol Suite稠鼻,或TCP/IP Protocols),簡(jiǎn)稱TCP/IP協(xié)議酌媒。有關(guān)TCP/IP協(xié)議的詳細(xì)理論介紹參見《TCP/IP詳解》。
二迄靠、TCP報(bào)文格式說明
TCP協(xié)議屬于OSI模型的傳輸層馍佑,傳輸層的功能是使源端主機(jī)和目標(biāo)端主機(jī)上的對(duì)等實(shí)體可以進(jìn)行會(huì)話。
TCP協(xié)議是一個(gè)面向連接的梨水、可靠的協(xié)議拭荤。它將一臺(tái)主機(jī)發(fā)出的字節(jié)流無差錯(cuò)地發(fā)往互聯(lián)網(wǎng)上的其他主機(jī)。
在發(fā)送端疫诽,它負(fù)責(zé)把上層傳送下來的字節(jié)流分成報(bào)文段并傳遞給下層舅世。
在接收端,它負(fù)責(zé)把收到的報(bào)文進(jìn)行重組后遞交給上層奇徒。
-
TCP協(xié)議還要處理端到端的流量控制雏亚,以避免緩慢接收的接收方?jīng)]有足夠的緩沖區(qū)接收發(fā)送方發(fā)送的大量數(shù)據(jù)。
TCP報(bào)文格式圖圖中重點(diǎn)字段介紹:
(1)序號(hào):Seq序號(hào)摩钙,占32位罢低,用來標(biāo)識(shí)從TCP源端向目的端發(fā)送的字節(jié)流,發(fā)起方發(fā)送數(shù)據(jù)時(shí)對(duì)此進(jìn)行標(biāo)記胖笛。
(2)確認(rèn)序號(hào):Ack序號(hào)网持,占32位,只有ACK標(biāo)志位為1時(shí)长踊,確認(rèn)序號(hào)字段才有效功舀,Ack=Seq+1。
(3)標(biāo)志位:共6個(gè)身弊,即URG辟汰、ACK列敲、PSH、RST帖汞、SYN戴而、FIN等,具體含義如下:
SYN(synchronous)建立聯(lián)機(jī)翩蘸,發(fā)起一個(gè)新連接所意。
ACK(acknowledgement )確認(rèn)序號(hào)有效。
PSH(push)傳送鹿鳖,接收方應(yīng)該盡快將這個(gè)報(bào)文交給應(yīng)用層扁眯。
FIN(finish)結(jié)束壮莹,釋放一個(gè)連接翅帜。
RST(reset)重置連接。
URG(urgent)緊急指針有效命满。
需要注意的是:
(A)不要將確認(rèn)序號(hào)Ack與標(biāo)志位中的ACK搞混了涝滴。
(B)確認(rèn)方Ack=發(fā)起方Req+1,兩端配對(duì)胶台。
三歼疮、TCP完整連接過程與狀態(tài)示意
- LISTEN:偵聽來自客戶端的TCP端口的連接請(qǐng)求
- SYN-SENT:再發(fā)送連接請(qǐng)求后等待匹配的連接請(qǐng)求(如果有大量這樣的狀態(tài)包,檢查是否中招了)
- SYN-RCVD:再收到和發(fā)送一個(gè)連接請(qǐng)求后等待對(duì)方對(duì)連接請(qǐng)求的確認(rèn)(如有大量此狀態(tài)诈唬,估計(jì)被flood攻擊了)
- ESTABLISHED:代表一個(gè)打開的連接
- FIN-WAIT-1:等待遠(yuǎn)程TCP連接中斷請(qǐng)求韩脏,或先前的連接中斷請(qǐng)求的確認(rèn)
- FIN-WAIT-2:從遠(yuǎn)程TCP等待連接中斷請(qǐng)求
- CLOSE-WAIT:等待從本地用戶發(fā)來的連接中斷請(qǐng)求
- LAST-ACK:等待原來的發(fā)向遠(yuǎn)程TCP的連接中斷請(qǐng)求的確認(rèn)(不是什么好東西,此項(xiàng)出現(xiàn)铸磅,檢查是否被攻擊)
- TIME-WAIT:等待足夠的時(shí)間以確保遠(yuǎn)程TCP接收到連接中斷請(qǐng)求的確認(rèn)
- CLOSED:沒有任何連接狀態(tài)赡矢,連接結(jié)束
四、TCP的3次握手過程
所謂三次握手(Three-Way Handshake)即建立TCP連接阅仔,就是指建立一個(gè)TCP連接時(shí)吹散,需要客戶端和服務(wù)端總共發(fā)送3個(gè)包以確認(rèn)連接的建立。在socket編程中八酒,這一過程服務(wù)器accept(被動(dòng)等待)空民,由客戶端執(zhí)行connect來觸發(fā)(主動(dòng)打開)。
為什么需要“三次握手”羞迷?
目的是“為了防止已失效的連接請(qǐng)求報(bào)文段突然又傳送到了服務(wù)端界轩,因而產(chǎn)生錯(cuò)誤”。
例子:client發(fā)出的第一個(gè)連接請(qǐng)求報(bào)文段并沒有丟失衔瓮,而是在某個(gè)網(wǎng)絡(luò)結(jié)點(diǎn)長(zhǎng)時(shí)間的滯留了耸棒,以致延誤到連接釋放以后的某個(gè)時(shí)間才到達(dá)server。本來這是一個(gè)早已失效的報(bào)文段报辱。但server收到此失效的連接請(qǐng)求報(bào)文段后与殃,就誤認(rèn)為是client再次發(fā)出的一個(gè)新的連接請(qǐng)求单山。于是就向client發(fā)出確認(rèn)報(bào)文段,同意建立連接幅疼。假設(shè)不采用“三次握手”米奸,那么只要server發(fā)出確認(rèn),新的連接就建立了爽篷。由于現(xiàn)在client并沒有發(fā)出建立連接的請(qǐng)求悴晰,因此不會(huì)理睬server的確認(rèn),也不會(huì)向server發(fā)送數(shù)據(jù)逐工。但server卻以為新的運(yùn)輸連接已經(jīng)建立铡溪,并一直等待client發(fā)來數(shù)據(jù)。這樣泪喊,server的很多資源就白白浪費(fèi)掉了棕硫。采用“三次握手”的辦法可以防止上述現(xiàn)象發(fā)生。例如剛才那種情況袒啼,client不會(huì)向server的確認(rèn)發(fā)出確認(rèn)哈扮。server由于收不到確認(rèn),就知道client并沒有要求建立連接蚓再』猓”。主要目的防止server端一直等待摘仅,浪費(fèi)資源靶庙。
整個(gè)流程如下圖所示:
seq:(Sequence number順序號(hào)碼) ack:(Acknowledge number確認(rèn)號(hào)碼)
(1)第一次握手:
- 發(fā)送端首先發(fā)送一個(gè)帶SYN標(biāo)志的數(shù)據(jù)包給接收端。
- Client將標(biāo)志位SYN置為1娃属,隨機(jī)產(chǎn)生一個(gè)值seq=J六荒,并將該數(shù)據(jù)包發(fā)送給Server,Client進(jìn)入SYN_SENT狀態(tài)膳犹,等待Server確認(rèn)恬吕。
(2)第二次握手:
- 接收端收到后,回傳一個(gè)帶有SYN/ACK標(biāo)志的數(shù)據(jù)包以示傳達(dá)確認(rèn)信息须床。
- Server收到數(shù)據(jù)包后由標(biāo)志位SYN=1知道Client請(qǐng)求建立連接铐料,Server將標(biāo)志位SYN和ACK都置為1,ack=J+1豺旬,隨機(jī)產(chǎn)生一個(gè)值seq=K钠惩,并將該數(shù)據(jù)包發(fā)送給Client以確認(rèn)連接請(qǐng)求,Server進(jìn)入SYN_RCVD狀態(tài)族阅。
(3)第三次握手:
- 發(fā)送端再回傳一個(gè)帶ACK標(biāo)志的數(shù)據(jù)包
- Client收到確認(rèn)后篓跛,檢查ack是否為J+1,ACK是否為1坦刀,如果正確則將標(biāo)志位ACK置為1愧沟,ack=K+1蔬咬,并將該數(shù)據(jù)包發(fā)送給Server,Server檢查ack是否為K+1沐寺,ACK是否為1林艘,如果正確則連接建立成功,Client和Server進(jìn)入ESTABLISHED狀態(tài)混坞,完成三次握手狐援,隨后Client與Server之間可以開始傳輸數(shù)據(jù)了。
實(shí)例:
IP 192.168.1.116.3337 > 192.168.1.123.7788: S 3626544836:3626544836 IP 192.168.1.123.7788 > 192.168.1.116.3337: S 1739326486:1739326486 ack 3626544837 IP 192.168.1.116.3337 > 192.168.1.123.7788: ack 1739326487,ack 1
第一次握手:192.168.1.116發(fā)送位碼syn=1,隨機(jī)產(chǎn)生seq number=3626544836的數(shù)據(jù)包到192.168.1.123,192.168.1.123由SYN=1知道192.168.1.116要求建立聯(lián)機(jī);
第二次握手:192.168.1.123收到請(qǐng)求后要確認(rèn)聯(lián)機(jī)信息究孕,向192.168.1.116發(fā)送ack number=3626544837,syn=1,ack=1,隨機(jī)產(chǎn)生seq=1739326486的包;
第三次握手:192.168.1.116收到后檢查ack number是否正確啥酱,即第一次發(fā)送的seq number+1,以及位碼ack是否為1,若正確厨诸,192.168.1.116會(huì)再發(fā)送ack number=1739326487,ack=1镶殷,192.168.1.123收到后確認(rèn)seq=seq+1,ack=1則連接建立成功。
SYN攻擊: SYN 攻擊原理以及防范技術(shù)
在三次握手過程中泳猬,Server發(fā)送SYN-ACK之后批钠,收到Client的ACK之前的TCP連接稱為半連接(half-open connect)宇植,此時(shí)Server處于SYN_RCVD狀態(tài)得封,當(dāng)收到ACK后,Server轉(zhuǎn)入ESTABLISHED狀態(tài)指郁。SYN攻擊就是Client在短時(shí)間內(nèi)偽造大量不存在的IP地址忙上,并向Server不斷地發(fā)送SYN包,Server回復(fù)確認(rèn)包闲坎,并等待Client的確認(rèn)疫粥,由于源地址是不存在的,因此腰懂,Server需要不斷重發(fā)直至超時(shí)梗逮,這些偽造的SYN包將長(zhǎng)時(shí)間占用未連接隊(duì)列,導(dǎo)致正常的SYN請(qǐng)求因?yàn)殛?duì)列滿而被丟棄绣溜,從而引起網(wǎng)絡(luò)堵塞甚至系統(tǒng)癱瘓慷彤。SYN攻擊時(shí)一種典型的DDos攻擊( 沒有根治方法, 除非不用TCP/IP鏈接)怖喻,檢測(cè)SYN攻擊的方式非常簡(jiǎn)單底哗,即當(dāng)Server上有大量半連接狀態(tài)且源IP地址是隨機(jī)的,則可以斷定遭到SYN攻擊了锚沸,使用系統(tǒng)自帶的netstat 工具來檢測(cè)SYN攻擊命令可以讓之現(xiàn)行:
#netstat -nap | grep SYN_RECV
五跋选、TCP的4次揮手過程
所謂四次揮手(Four-Way Wavehand)即終止TCP連接,就是指斷開一個(gè)TCP連接時(shí)哗蜈,需要客戶端和服務(wù)端總共發(fā)送4個(gè)包以確認(rèn)連接的斷開前标。在socket編程中坠韩,這一過程由客戶端或服務(wù)端任一方執(zhí)行close來觸發(fā)。
為什么要四次揮手炼列?
由于TCP連接是全雙工(通訊傳輸?shù)囊粋€(gè)術(shù)語:即允許數(shù)據(jù)在兩個(gè)方向上可以同時(shí)(瞬時(shí))進(jìn)行信號(hào)的雙向傳輸同眯,指A→B的同時(shí)B→A。)的唯鸭,因此须蜗,每個(gè)方向都必須要單獨(dú)進(jìn)行關(guān)閉目溉,這一原則是當(dāng)一方完成數(shù)據(jù)發(fā)送任務(wù)后明肮,發(fā)送一個(gè)FIN來終止這一方向的連接,收到一個(gè)FIN只是意味著這一方向上沒有數(shù)據(jù)流動(dòng)了缭付,即不會(huì)再收到數(shù)據(jù)了柿估,但是在這個(gè)TCP連接上仍然能夠發(fā)送數(shù)據(jù),直到這一方向也發(fā)送了FIN陷猫。首先進(jìn)行關(guān)閉的一方將執(zhí)行主動(dòng)關(guān)閉秫舌,而另一方則執(zhí)行被動(dòng)關(guān)閉。
整個(gè)流程如下圖所示:
(1)第一次揮手:Client:我已經(jīng)不會(huì)再給你發(fā)數(shù)據(jù)了绣檬。
- Client(主動(dòng)關(guān)閉方)發(fā)送一個(gè)FIN足陨,用來關(guān)閉Client到Server(被動(dòng)關(guān)閉方)的數(shù)據(jù)傳送,Client進(jìn)入FIN_WAIT_1狀態(tài)娇未。
- (當(dāng)然墨缘,在FIN包之前發(fā)送出去的數(shù)據(jù),如果沒有收到對(duì)應(yīng)的ack確認(rèn)報(bào)文零抬,主動(dòng)關(guān)閉方依然會(huì)重發(fā)這些數(shù)據(jù))镊讼,但是,此時(shí)主動(dòng)關(guān)閉方還可 以接受數(shù)據(jù)平夜。
(2)第二次揮手:Server:好蝶棋,我知道了。
- Server收到FIN后忽妒,發(fā)送一個(gè)ACK給Client玩裙,確認(rèn)序號(hào)為收到序號(hào)+1(與SYN相同,一個(gè)FIN占用一個(gè)序號(hào))锰扶,Server進(jìn)入CLOSE_WAIT狀態(tài)献酗。
(3)第三次揮手:Server:我的數(shù)據(jù)也發(fā)送完了,我也不會(huì)再給你發(fā)數(shù)據(jù)了坷牛。
- Server發(fā)送一個(gè)FIN罕偎,用來關(guān)閉Server到Client的數(shù)據(jù)傳送,Server進(jìn)入LAST_ACK狀態(tài)京闰。
(4)第四次揮手:Client:OK颜及,我也知道了甩苛,再見。
- Client收到FIN后俏站,Client進(jìn)入TIME_WAIT狀態(tài)讯蒲,接著發(fā)送一個(gè)ACK給Server,確認(rèn)序號(hào)為收到序號(hào)+1肄扎,Server進(jìn)入CLOSED狀態(tài)墨林,完成四次揮手。
上面是一方主動(dòng)關(guān)閉犯祠,另一方被動(dòng)關(guān)閉的情況旭等,實(shí)際中還會(huì)出現(xiàn)同時(shí)發(fā)起主動(dòng)關(guān)閉的情況,具體流程如下圖:
流程和狀態(tài)在上圖中已經(jīng)很明了衡载,在此可以參考前面的四次揮手解析步驟搔耕,不再贅述。
六痰娱、常見問題
TCP與UDP的區(qū)別是什么弃榨?
- TCP(Transmission Control Protocol,傳輸控制協(xié)議)是基于連接的協(xié)議梨睁,也就是說鲸睛,在正式收發(fā)數(shù)據(jù)前,必須和對(duì)方建立可靠的連接而姐。一個(gè)TCP連接(一對(duì)一)必須要經(jīng)過三次“對(duì)話”才能建立起來腊凶。保證兩端通信主機(jī)之間的通信可達(dá)划咐;全雙工通信拴念;面向字節(jié)流;首部最低20個(gè)字節(jié)
- UDP(User Data Protocol褐缠,用戶數(shù)據(jù)報(bào)協(xié)議)是與TCP相對(duì)應(yīng)的協(xié)議政鼠。它是面向無連接的傳輸層協(xié)議。它不與對(duì)方建立連接队魏,而是直接就把數(shù)據(jù)包發(fā)送過去公般!支持一對(duì)一、一對(duì)多胡桨、多對(duì)一官帘、多對(duì)多的交互通信。 不保證可靠交付昧谊,也不使用擁塞控制刽虹;面向報(bào)文的,沒有擁塞控制呢诬,適合多媒體通信的要求涌哲;首部開銷小8字節(jié)胖缤。
三次握手有什么缺點(diǎn)?
慢阀圾,效率低哪廓,占用系統(tǒng)資源高赶诊,易被攻擊 TCP在傳遞數(shù)據(jù)之前证逻,要先建連接,這會(huì)消耗時(shí)間君珠,而且在數(shù)據(jù)傳遞時(shí)肾筐,確認(rèn)機(jī)制综膀、重傳機(jī)制、擁塞控制機(jī)制等都會(huì)消耗大量的時(shí)間局齿,而且要在每臺(tái)設(shè)備上維護(hù)所有的傳輸連接剧劝,事實(shí)上,每個(gè)連接都會(huì)占用系統(tǒng)的CPU抓歼、內(nèi)存等硬件資源讥此。 而且,因?yàn)門CP有確認(rèn)機(jī)制谣妻、三次握手機(jī)制萄喳,這些也導(dǎo)致TCP容易被人利用,實(shí)現(xiàn)DOS蹋半、DDOS他巨、CC等攻擊。
為什么建立連接是三次握手减江,而關(guān)閉連接卻是四次揮手呢染突?
這是因?yàn)榉?wù)端在LISTEN狀態(tài)下,收到建立連接請(qǐng)求的SYN報(bào)文后辈灼,把ACK和SYN放在一個(gè)報(bào)文里發(fā)送給客戶端份企。而關(guān)閉連接時(shí),當(dāng)收到對(duì)方的FIN報(bào)文時(shí)巡莹,僅僅表示對(duì)方不再發(fā)送數(shù)據(jù)了但是還能接收數(shù)據(jù)司志,己方也未必全部數(shù)據(jù)都發(fā)送給對(duì)方了,所以己方可以立即close降宅,也可以發(fā)送一些數(shù)據(jù)給對(duì)方后骂远,再發(fā)送FIN報(bào)文給對(duì)方來表示同意現(xiàn)在關(guān)閉連接,因此腰根,己方ACK和FIN一般都會(huì)分開發(fā)送激才。