由于WebRTC是基于點對點的次慢,自然而然需要NAT穿越的技術(shù)风秤,否則消息將無法傳遞座菠。在WebRTC使用了ICE協(xié)議框架,里面提到了STUN和TURN兩個協(xié)議沉桌,而NAT穿越實現(xiàn)就是由這兩個協(xié)議共同協(xié)調(diào)完成的谢鹊。
一算吩、首先來簡單講講什么是NAT?
原來這是因為IPV4引起的佃扼,我們上網(wǎng)很可能會處在一個NAT設(shè)備(無線路由器之類)之后偎巢。
NAT設(shè)備會在IP封包通過設(shè)備時修改源/目的IP地址. 對于家用路由器來說, 使用的是網(wǎng)絡(luò)地址端口轉(zhuǎn)換(NAPT), 它不僅改IP, 還修改TCP和UDP協(xié)議的端口號, 這樣就能讓內(nèi)網(wǎng)中的設(shè)備共用同一個外網(wǎng)IP. 舉個例子, NAPT維護一個類似下表的NAT映射表:
NAT設(shè)備會根據(jù)NAT表對出去和進來的數(shù)據(jù)做修改, 比如將192.168.0.3:8888發(fā)出去的封包改成120.132.92.21:9202, 外部就認(rèn)為他們是在和120.132.92.21:9202通信. 同時NAT設(shè)備會將120.132.92.21:9202收到的封包的IP和端口改成192.168.0.3:8888, 再發(fā)給內(nèi)網(wǎng)的主機, 這樣內(nèi)部和外部就能雙向通信了, 但如果其中192.168.0.3:8888==120.132.92.21:9202這一映射因為某些原因被NAT設(shè)備淘汰了, 那么外部設(shè)備就無法直接與192.168.0.3:8888通信了。
我們的設(shè)備經(jīng)常是處在NAT設(shè)備的后面, 比如在大學(xué)里的校園網(wǎng), 查一下自己分配到的IP, 其實是內(nèi)網(wǎng)IP, 表明我們在NAT設(shè)備后面, 如果我們在寢室再接個路由器, 那么我們發(fā)出的數(shù)據(jù)包會多經(jīng)過一次NAT.
二兼耀、NAT的副作用以及解決方案
國內(nèi)移動無線網(wǎng)絡(luò)運營商在鏈路上一段時間內(nèi)沒有數(shù)據(jù)通訊后, 會淘汰NAT表中的對應(yīng)項, 造成鏈路中斷压昼。
這是NAT帶來的第一個副作用:NAT超時:
而國內(nèi)的運營商一般NAT超時的時間為5分鐘,所以通常我們TCP長連接的心跳設(shè)置的時間間隔為3-5分鐘瘤运。
而第二個副作用就是:我們這邊文章要提到的NAT墻窍霞。
NAT會有一個機制,所有外界對內(nèi)網(wǎng)的請求尽超,到達NAT的時候官撼,都會被NAT所丟棄,這樣如果我們處于一個NAT設(shè)備后面似谁,我們將無法得到任何外界的數(shù)據(jù)傲绣。
但是這種機制有一個解決方案:就是如果我們A主動往B發(fā)送一條信息,這樣A就在自己的NAT上打了一個B的洞巩踏。這樣A的這條消息到達B的NAT的時候秃诵,雖然被丟掉了,但是如果B這個時候在給A發(fā)信息塞琼,到達A的NAT的時候菠净,就可以從A之前打的那個洞中,發(fā)送給到A手上了彪杉。
簡單來講毅往,就是如果A和B要進行通信,那么得事先A發(fā)一條信息給B派近,B發(fā)一條信息給A攀唯。這樣提前在各自的NAT上打了對方的洞,這樣下一次A和B之間就可以進行通信了渴丸。
三侯嘀、四種NAT類型:
RFC3489 中將 NAT 的實現(xiàn)分為四大類:
Full Cone NAT (完全錐形 NAT)
Restricted Cone NAT (限制錐形 NAT ,可以理解為 IP 限制谱轨,Port不限制)
Port Restricted Cone NAT (端口限制錐形 NAT戒幔,IP+Port 限制)
Symmetric NAT (對稱 NAT)
其中完全最上層的完全錐形NAT的穿透性最好,而最下層的對稱形NAT的安全性最高土童。
簡單來講講這4種類型的NAT代表什么:
如果一個NAT是Full Cone NAT诗茎,那么無論什么IP地址訪問,都不會被NAT墻掉(這種基本很少)献汗。
Restricted Cone NAT敢订,僅僅是經(jīng)過打洞的IP能穿越NAT栅组,但是不限于Port。
Port Restricted Cone NAT枢析,僅僅是經(jīng)過打洞的IP+端口號能穿越NAT。
Symmetric NAT 這種也是僅僅是經(jīng)過打洞的IP+端口號能穿越NAT刃麸,但是它有一個最大的和Cone類型的NAT的區(qū)別醒叁,它對外的公網(wǎng)Port是不停的變化的:
比如A是一個對稱NAT,那么A給B發(fā)信息泊业,經(jīng)過NAT映射到一個Port:10000把沼,A給C發(fā)信息,經(jīng)過NAT映射到一個Port:10001吁伺,這樣會導(dǎo)致一個問題饮睬,我們服務(wù)器根本無法協(xié)調(diào)進行NAT打洞。
至于為什么無法協(xié)調(diào)打洞篮奄,下面我們會從STUN和TURN的工作原理來講捆愁。
四、STUN和TURN的實現(xiàn):
- STUN Server主要做了兩件事:
接受客戶端的請求窟却,并且把客戶端的公網(wǎng)IP昼丑、Port封裝到ICE Candidate中。 - 通過一個復(fù)雜的機制夸赫,得到客戶端的NAT類型菩帝。
完成了這些STUN Server就會這些基本信息發(fā)送回客戶端,然后根據(jù)NAT類型茬腿,來判斷是否需要TURN服務(wù)器協(xié)調(diào)進行下一步工作呼奢。
我們來講講這兩步具體做了什么吧:
第一件事就不用說了,其實就是得到客戶端的請求切平,把源IP和Port拿到握础,添加到ICE Candidate中。
來講講第二件事揭绑,STUN是如何判斷NAT的類型的:
假設(shè)B是客戶端弓候,C是STUN服務(wù)器,C有兩個IP分別為IP1和IP2(至于為什么要兩個IP他匪,接著往下看):
STEP1. 判斷客戶端是否在NAT后:
B向C的IP1的pot1端口發(fā)送一個UDP 包菇存。C收到這個包后,會把它收到包的源IP和port寫到UDP包中邦蜜,然后把此包通過IP1和port1發(fā)還給B依鸥。這個IP和port也就是NAT的外網(wǎng) IP和port(如果你不理解,那么請你去看我的BLOG里面的NAT的原理和分類)悼沈,也就是說你在STEP1中就得到了NAT的外網(wǎng)IP贱迟。
熟悉NAT工作原理的朋友可以知道姐扮,C返回給B的這個UDP包B一定收到。如果在你的應(yīng)用中衣吠,向一個STUN服務(wù)器發(fā)送數(shù)據(jù)包后茶敏,你沒有收到STUN的任何回應(yīng)包,那只有兩種可能:1缚俏、STUN服務(wù)器不存在惊搏,或者你弄錯了port。2忧换、你的NAT拒絕一切UDP包從外部向內(nèi)部通過恬惯。
當(dāng)B收到此UDP后,把此UDP中的IP和自己的IP做比較亚茬,如果是一樣的酪耳,就說明自己是在公網(wǎng),下步NAT將去探測防火墻類型刹缝,我不想多說碗暗。如果不一樣,說明有NAT的存在梢夯,系統(tǒng)進行STEP2的操作讹堤。
STEP2.判斷是否處于Full Cone Nat下:
B向C的IP1發(fā)送一個UDP包,請求C通過另外一個IP2和PORT(不同與SETP1的IP1)向B返回一個UDP數(shù)據(jù)包(現(xiàn)在知道為什么C要有兩個IP了吧厨疙,雖然還不理解為什么洲守,呵呵)雁歌。
我們來分析一下葬毫,如果B收到了這個數(shù)據(jù)包,那說明什么闯捎?說明NAT來著不拒撒蟀,不對數(shù)據(jù)包進行任何過濾叙谨,這也就是STUN標(biāo)準(zhǔn)中的full cone NAT。遺憾的是保屯,F(xiàn)ull Cone Nat太少了手负,這也意味著你能收到這個數(shù)據(jù)包的可能性不大。如果沒收到姑尺,那么系統(tǒng)進行STEP3的操作竟终。
STEP3.判斷是否處于對稱NAT下:
B向C的IP2的port2發(fā)送一個數(shù)據(jù)包,C收到數(shù)據(jù)包后切蟋,把它收到包的源IP和port寫到UDP包中统捶,然后通過自己的IP2和port2把此包發(fā)還給B。
和step1一樣,B肯定能收到這個回應(yīng)UDP包喘鸟。此包中的port是我們最關(guān)心的數(shù)據(jù)匆绣,下面我們來分析:
如果這個port和step1中的port一樣,那么可以肯定這個NAT是個CONE NAT什黑,否則是對稱NAT崎淳。道理很簡單:根據(jù)對稱NAT的規(guī)則,當(dāng)目的地址的IP和port有任何一個改變愕把,那么NAT都會重新分配一個port使用凯力,而在step3中,和step1對應(yīng)礼华,我們改變了IP和port。因此拗秘,如果是對稱NAT,那這兩個port肯定是不同的圣絮。
如果在你的應(yīng)用中,到此步的時候PORT是不同的雕旨,那么這個它就是處在一個對稱NAT下了扮匠。如果相同,那么只剩下了restrict cone 和port restrict cone凡涩。系統(tǒng)用step4探測是是那一種棒搜。
STEP4.判斷是處于Restrict Cone NAT還是Port Restrict NAT之下:
B向C的IP2的一個端口PD發(fā)送一個數(shù)據(jù)請求包,要求C用IP2和不同于PD的port返回一個數(shù)據(jù)包給B活箕。
我們來分析結(jié)果:如果B收到了力麸,那也就意味著只要IP相同,即使port不同育韩,NAT也允許UDP包通過克蚂。顯然這是Restrict Cone NAT。如果沒收到筋讨,沒別的好說埃叭,Port Restrict NAT.
到這里STUN Server一共通過這4步,判斷出客戶端處于什么類型的NAT下悉罕,然后去做后續(xù)的處理:
這4步都會返回給客戶端它的公網(wǎng)IP赤屋、Port和NAT類型,除此之外:
a) 如果A處于公網(wǎng)或者Full Cone Nat下壁袄,STUN不做其他的了类早,因為其他客戶端可以直接和A進行通信。
image
b) 如果A處于Restrict Cone或者Port Restrict NAT下嗜逻,STUN還會協(xié)調(diào)TURN進行NAT打洞莺奔。
image
c) 如果A處于對稱NAT下,那么點對點連接下,NAT是無法進行打洞的令哟。所以為了通信恼琼,只能采取最后的手段了,就是轉(zhuǎn)成C/S架構(gòu)了屏富,STUN會協(xié)調(diào)TURN進行消息轉(zhuǎn)發(fā)晴竞。
image - TURN Server也主要做了兩件事:
a) 為NAT打洞:
如果A和B要互相通信,那么TURN Server狠半,會命令A(yù)和B互相發(fā)一條信息噩死,這樣各自的NAT就留下了對方的洞,下次他們就可以之間進行通信了神年。
b) 為對稱NAT提供消息轉(zhuǎn)發(fā):
當(dāng)A或者B其中一方是對稱NAT時已维,那么給這一方發(fā)信息,就只能通過TURN Server來轉(zhuǎn)發(fā)了已日。
最后補充一下垛耳,為什么對稱NAT無法打洞:
假如A、B進行通信飘千,而B處于對稱NAT之下堂鲜,那么A與B通信,STUN拿到A护奈,B的公網(wǎng)地址和端口號都為10000缔莲,然后去協(xié)調(diào)TURN打洞,那么TURN去命令A(yù)發(fā)信息給B霉旗,則A就在NAT打了個B的洞痴奏,但是這個B的洞是端口號為10000的洞,但是下次B如果給A發(fā)信息厌秒,因為B是對稱NAT抛虫,它給每個新的IP發(fā)送信息時,都重新對應(yīng)一個公網(wǎng)端口简僧,所以給A發(fā)送請求可能是公網(wǎng)10001端口建椰,但是A只有B的10000端口被打洞過,所以B的請求就被丟棄了岛马。
顯然Server是無法協(xié)調(diào)客戶端打洞的棉姐,因為協(xié)調(diào)客戶端打得洞僅僅是上次對端為Server發(fā)送端口的洞,并不適用于另一個請求啦逆。
最后的最后再補充一點伞矩,就是NAT打的洞也是具有時效性的,如果NAT超時了夏志,那么還是需要重新打洞的乃坤。
作者:涂耀輝
鏈接:http://www.reibang.com/p/84e8c78ca61d
來源:簡書
著作權(quán)歸作者所有。商業(yè)轉(zhuǎn)載請聯(lián)系作者獲得授權(quán),非商業(yè)轉(zhuǎn)載請注明出處湿诊。