ICE協(xié)議下NAT穿越的實現(xiàn)(STUN&TURN)

由于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映射表:


image

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):
  1. STUN Server主要做了兩件事:
    接受客戶端的請求窟却,并且把客戶端的公網(wǎng)IP昼丑、Port封裝到ICE Candidate中。
  2. 通過一個復(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
  3. 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)載請注明出處湿诊。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末狱杰,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子厅须,更是在濱河造成了極大的恐慌仿畸,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,858評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件朗和,死亡現(xiàn)場離奇詭異错沽,居然都是意外死亡,警方通過查閱死者的電腦和手機眶拉,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,372評論 3 395
  • 文/潘曉璐 我一進店門千埃,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人忆植,你說我怎么就攤上這事放可。” “怎么了唱逢?”我有些...
    開封第一講書人閱讀 165,282評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長屋休。 經(jīng)常有香客問我坞古,道長,這世上最難降的妖魔是什么劫樟? 我笑而不...
    開封第一講書人閱讀 58,842評論 1 295
  • 正文 為了忘掉前任痪枫,我火速辦了婚禮,結(jié)果婚禮上叠艳,老公的妹妹穿的比我還像新娘奶陈。我一直安慰自己,他們只是感情好附较,可當(dāng)我...
    茶點故事閱讀 67,857評論 6 392
  • 文/花漫 我一把揭開白布吃粒。 她就那樣靜靜地躺著,像睡著了一般拒课。 火紅的嫁衣襯著肌膚如雪徐勃。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,679評論 1 305
  • 那天早像,我揣著相機與錄音僻肖,去河邊找鬼。 笑死卢鹦,一個胖子當(dāng)著我的面吹牛臀脏,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 40,406評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼揉稚,長吁一口氣:“原來是場噩夢啊……” “哼秒啦!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起窃植,我...
    開封第一講書人閱讀 39,311評論 0 276
  • 序言:老撾萬榮一對情侶失蹤帝蒿,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后巷怜,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體葛超,經(jīng)...
    沈念sama閱讀 45,767評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年延塑,在試婚紗的時候發(fā)現(xiàn)自己被綠了绣张。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,090評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡关带,死狀恐怖侥涵,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情宋雏,我是刑警寧澤芜飘,帶...
    沈念sama閱讀 35,785評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站磨总,受9級特大地震影響嗦明,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜蚪燕,卻給世界環(huán)境...
    茶點故事閱讀 41,420評論 3 331
  • 文/蒙蒙 一娶牌、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧馆纳,春花似錦诗良、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,988評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至钥弯,卻和暖如春壹罚,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背寿羞。 一陣腳步聲響...
    開封第一講書人閱讀 33,101評論 1 271
  • 我被黑心中介騙來泰國打工猖凛, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人绪穆。 一個月前我還...
    沈念sama閱讀 48,298評論 3 372
  • 正文 我出身青樓辨泳,卻偏偏與公主長得像虱岂,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子菠红,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,033評論 2 355