NAT 及 NAT 打洞技术
生活随笔
收集整理的這篇文章主要介紹了
NAT 及 NAT 打洞技术
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
1 / 6
NAT 及 NAT 打洞技術
一、什么是 NAT?為什么要使用 NAT?
NAT 是將私有地址轉換為合法 IP 地址的技術,通俗的講就是將內網與內網通信時怎么將內網私有 IP 地址
轉換為可在網絡中傳播的合法 IP 地址。 NAT 的出現完美地解決了 lP 地址不足的問題,而且還能夠有效地
避免來自網絡外部的攻擊,隱藏并保護網絡內部的計算機。
二、NAT 的分類
STUN 標準中,根據內部終端的地址(LocalIP:LocalPort)到 NAT 出口的公網地址(PublicIP:PublicPort)的影
射方式,把 NAT 分為四種類型:
1、Full Cone NAT:? 內網主機建立一個 socket(LocalIP:LocalPort)? 第一次使用這個 socket 給外部主機發送數
據時 NAT 會給其分配一個公網(PublicIP:PublicPort),以后用這個 socket 向外面任何主機發送數據都將使用
這對(PublicIP:PublicPort) 。此外,任何外部主機只要知道這個(PublicIP:PublicPort) 就可以發送數據給
(PublicIP:PublicPort),內網的主機就能收到這個數據包。
2、 Restricted Cone NAT:? 內網主機建立一個 socket(LocalIP:LocalPort)? 第一次使用這個 socket 給外部主機發
送數據時 NAT 會給其分配一個公網(PublicIP:PublicPort),以后用這個 socket 向外面任何主機發送數據都將
使用這對(PublicIP:PublicPort)。此外,如果任何外部主機想要發送數據給這個內網主機,只要知道這個
(PublicIP:PublicPort)并且內網主機之前用這個 socket 曾向這個外部主機 IP 發送過數據。只要滿足這兩個
條件,這個外部主機就可以用自己的(IP,任何端口)發送數據給(PublicIP:PublicPort),內網的主機就能收到
這個數據包。
3、 Port Restricted Cone NAT:? 內網主機建立一個 socket(LocalIP:LocalPort)? 第一次使用這個 socket 給外部主
機發送數據時 NAT 會給其分配一個公網(PublicIP:PublicPort),以后用這個 socket 向外面任何主機發送數據
都將使用這對(PublicIP:PublicPort)。此外,如果任何外部主機想要發送數據給這個內網主機,只要知道這
個(PublicIP:PublicPort)并且內網主機之前用這個 socket 曾向這個外部主機(IP,Port)發送過數據。只要滿足
這兩個條件,這個外部主機就可以用自己的(IP,Port)發送數據給(PublicIP:PublicPort),內網的主機就能收到
這個數據包。
4、Symmetric NAT:? 內網主機建立一個 socket(LocalIP,LocalPort),當用這個 socket 第一次發數據給外部主機
1 時,NAT 為其映射一個(PublicIP -1,Port-1), 以后內網主機發送給外部主機 1 的所有數據都是用這個
(PublicIP -1,Port-1),如果內網主機同時用這個 socket 給外部主機 2 發送數據,NAT 會為其分配一個
(PublicIP -2,Port-2),? 以后內網主機發送給外部主機 2 的所有數據都是用這個(PublicIP -2,Port-2).如果 NAT 有
多于一個公網 IP,則 PublicIP-1 和 PublicIP-2 可能不同,如果 NAT 只有一個公網 IP,則 Port-1 和 Port-2 肯定
2 / 6
不同,也就是說一定不能是 PublicIP-1 等于? PublicIP-2 且 Port-1 等于 Port-2。此外,如果任何外部主機想
要發送數據給這個內網主機,那么它首先應該收到內網主機發給他的數據,然后才能往回發送,否則即
使他知道內網主機的一個(PublicIP,Port)也不能發送數據給內網主機,這種 NAT 無法實現 P2P 通信,但是
如果另一方是 Full Cone NAT,還是可以實現穿透的,下面我會詳細分析各種類型 NAT 穿透的情況。
NAT? 功能通常被集成到路由器、防火墻、ISDN 路由器或者單獨的 NAT 設備中。所以我們大家很少會知
道 NAT,上面 NAT 類型的概念描述是比較通俗的,但為了更便于理解,我再舉例闡述一下 NAT 的原理。
現有通信的雙方 A 和 B,當 A 和 B 都是在公網的時候,通信是不用 NAT 的。假設 A 在內網,內網 IP
是 192.168.1.3,端口號是 5000,A 經過 NAT 后的 IP 是 221.221.221.100,端口號是 8000,B 的 IP 是
202.105.124.100,端口是 8500。如果 B 要去主動連接 A,即使 B 知道 A 經過 NAT 后的 IP 和端口也是無
法連接成功的,因為 A 沒有向 B(202.105.124.100:8500)發送過數據,所以 B 的數據包會被 A 的 NAT 丟棄,
于是連接失敗。但是 A 如果去主動連接 B,由于 B 是在公網,所以會連接成功,通信也就會建立。這也
就是反彈連接木馬“反彈”二字的精髓。
當客戶端 A 和 B 都是處在內網的時候,雙方由于都不知道對方的公網 IP 和端口,就會無從下手,所以要
在客戶端 A 和 B 之間架設一臺服務器 S 來為它們牽線,而且 S 是處在公網,以保證 A 和 B 都能連接到 S。
客戶端 A 和 B 登錄時都首先連接 S,S 就會知道 A 和 B 經過 NAT 后的 IP 和端口,當 A 想要連接 B 時,就
像 S 發出請求, S 會把 B 經過 NAT 后的 IP 和端口告訴 A,同時 S 向 B 發送 A 經過 NAT 后的 IP 和端口,并
要求 B 發送數據給 A, B 發送數據到達 A 時會被 A 的 NAT 拋棄,但是 B 的 NAT 會有 B 發送數據到 A 的記
錄,這是 A 再向 B 發送數據時就會被 B 的 NAT 放行,因為 B 曾經向 A 的外網 IP 和端口發送過數據。可
能有點亂,下面以故事的形式敘述一下這個情景。
人物:A(男)? NAT_A(A 家接線員)??? B(女)? NAT_B?? (B 家接線員)? S
場景介紹:A 想認識 B,但是不知道 B 的電話,S 跟 A、B 都是朋友,并且知道 A 和 B 的電話。接線員的
職責:對往外轉接的電話不做詢問,對往內轉接的電話則要過濾以免有騷擾電話。過濾規則:在一定時
間內沒有撥打過的號碼就過濾。
首先 A 給 S 打電話:
A 說:我想認識你朋友 B,你把她電話給我唄。
S 說:行,她的電話是 PublicIP_B,我讓她先給你打個電話,要不她家接線員不幫你轉接。
A 說:好。
S 跟 B 打電話:
S 說:我有一個朋友 A,人挺好的,他想認識你,你給他打個電話,他的電話號碼是 PublicIP_A。
B 說:行,打完告訴你。
3 / 6
S 說:好的。
B 打電話到 A 家,B 家接線員 NET_B 看到女主人想往 PublicIP_A 打電話就轉接到 A 家了,同時把號碼
PublicIP_A 記錄下來,A 家接線員 NAT_A 一看號碼是個近期沒打過的號,就給掛斷了。
B 給 S 打電話:
B 說:我打完電話了
S 說:好,等著吧,一會他就給你打進來了。
S 給 A 打電話:
S 說:他給你打完電話了,你快點給她打。
A 打電話到 B 家,?? A 家接線員 NET_A 看到男主人想往 PublicIP_B 打電話就轉接到 B 家了, B 家接線員 NET_B
看到是剛剛撥過的 PublicIP_A 號碼打過來的,就轉接給 B 了,A 和 B 的電話也就打通了。
A 和 B 通話:
A 說:電話終于打通了,想認識你挺困難的。
B 說:是啊。
以上雖然和實際不太一樣,但穿透的整體過程基本就是這樣。 A 往 B 發送數據的唯一阻礙就
是 NET_B,所以想要成功發送數據,必須把 NET_B 穿一個洞,A 是無法完成這項工作的,所以就得讓 B
完成這個打洞操作,也就是讓 B 往 A 發送數據,這樣 NET_B 就會誤以為 A 發送的數據是上次會話的一部
分從而不予阻攔。
但是,由于 NAT 的類型沒有一個統一的標準,所以 NAT 穿透使用的技術有很多種,穿透的成功率也不一
樣。還有些 NAT 類型的內網之間幾乎無法穿透。下面我們用實例詳細分析一下各種 NAT 類型穿透的可行
性。
A 機器在私網(192.168.0.3)
A 側 NAT 服務器(221.221.221.100)
B 機器在另一個私網(192.168.0.5)
B 側 NAT 服務器(210.30.224.70)
C 機器在公網(210.202.14.36)作為 A 和 B 之間的中介
A 機器連接 C 機器,假使是 A(192.168.0.3:5000)->? A 側 NAT(轉換后 221.221.221.100:8000)->? C
(210.202.14.36:2000)
B 機器也連接 C 機器,假使是 B(192.168.0.5:5000)->? B 側 NAT(轉換后 210.30.224.70:8000)->? C
(210.202.14.36:2000)???? ?
4 / 6
A 機器連接過 C 機器后,A 向 C 報告了自己的內部地址(192.168.0.3:5000),此時 C 不僅知道了 A
的外部地址(C 通過自己看到的 221.221.221.100:8000)也知道了 A 的內部地址。同理 C 也知道了 B 的外
部地址(210.30.224.70:8000)和?? 內部地址(192.168.0.5:5000)。之后,C 作為中介,把 A 的兩個地址
告訴了 B,同時也把 B 的兩個地址告訴了 A。
假設 A 先知道了 B 的兩個地址,則 A 從 192.168.0.3:5000 處同時向 B 的兩個地址 192.168.0.5:5000
和 210.30.224.70:8000 發包,由于 A 和 B 在兩個不同的 NAT 后面,故從 A(192.168.0.3:5000)到 B
(192.168.0.5:5000)的包肯定不通,現在看 A(192.168.0.3:5000)到 B(210.30.224.70:8000)的包,分
如下兩種情況:?? ?
1、B 側 NAT 屬于 Full?? Cone?? NAT??? ?
則無論 A 側 NAT 屬于 Cone?? NAT 還是 Symmetric?? NAT,包都能順利到達 B。如果程序設計得好,使
得 B 主動到 A 的包也能借用 A 主動發起建立的通道的話,則即使 A 側 NAT 屬于 Symmetric?? NAT, B 發出
的包也能順利到達 A。
結論 1:只要單側 NAT 屬于 Full?? Cone?? NAT,即可實現雙向通信。
2、B 側 NAT 屬于 Restricted?? Cone 或 Port?? Restricted?? Cone??? ?
則包不能到達 B。再細分兩種情況
(1)、A 側 NAT 屬于 Restricted?? Cone 或 Port?? Restricted?? Cone
雖然先前那個初始包不曾到達 B ,但該發包過程已經在 A 側 NAT 上留下了足夠的記錄:A
(192.168.0.3:5000)->(221.221.221.100:8000)->B(210.30.224.70:8000)。如果在這個記錄沒有超時之
前, B 也重復和 A 一樣的動作,即向 A (221.221.221.100:8000)發包,雖然 A 側 NAT 屬于 Restricted??? Cone
或 Port? Restricted? Cone,但先前 A 側 NAT 已經認為 A 已經向 B(210.30.224.70:8000)發過包,故 B 向 A
(221.221.221.100:8000)發包能夠順利到達 A。同理,此后 A 到 B 的包,也能順利到達。
結論 2:只要兩側 NAT 都不屬于 Symmetric?? NAT,也可雙向通信。換種說法,只要兩側 NAT 都屬于
Cone?? NAT,即可雙向通信。
(2)、A 側 NAT 屬于 Symmetric?? NAT??? ?
因為 A 側 NAT 屬于 Symmetric?? NAT,且最初 A 到 C 發包的過程在 A 側 NAT 留下了如下記錄:A
(192.168.0.3:5000)->(221.221.221.100:8000)->? C(210.202.14.36:2000),故 A 到 B 發包過程在 A 側
NAT 上留下的記錄為:
A(192.168.0.3:5000)->(221.221.221.100:8001)->B(210.30.224.70:8000)(注意,轉換后端口產生
了變化)。而 B 向 A 的發包,只能根據 C 給他的關于 A 的信息,發往 A(221.221.221.100:8000),因為 A
端口受限,故此路不通。再來看 B 側 NAT,由于 B 也向 A 發過了包,且 B 側 NAT 屬于 Restricted??? Cone
5 / 6
或 Port??? Restricted?? Cone,故在 B 側 NAT 上留下的記錄為: B (192.168.0.5:5000) -> (210.30.224.70:8000)
->A(221.221.221.100:8000),此后,如果 A 還繼續向 B 發包的話(因為同一目標,故仍然使用前面的映
射),如果 B 側 NAT 屬于 Restricted??? Cone,則從 A (221.221.221.100:8001)來的包能夠順利到達 B;如
果 B 側 NAT 屬于 Port?? Restricted?? Cone,則包永遠無法到達 B。
結論 3:一側 NAT 屬于 Symmetric?? NAT,另一側 NAT 屬于 Restricted??? Cone,也可雙向通信。
反過來想,則可以得出另一個結論:兩個都是 Symmetric NAT 或者一個是 Symmetric?? NAT、另一個是
Port Restricted Cone,則不能雙向通信,因為 NAT 無法穿透。
上面的例子雖然只是分析了最初發包是從 A 到 B 的情況,但是,由于兩者的對稱性,前面得出的幾
條結論沒有方向性,雙向都適用。
我們上面得出了四條結論,natcheck 網站則把他歸結為一條:只要兩側 NAT 都屬于 Cone?? NAT(含
Full?? Cone、Restricted?? Cone 和 Port?? Restricted?? Cone 三者),即可雙向通信。沒有把我們的結論 3 包
括進去。
一般情況下,只有比較注重安全的大公司會使用 Symmetric NAT,禁止使用 P2P 類型的通信,很多地方使
用的都是 Cone?? NAT,因此穿透技術還是有發展前景的。
三、使用 UDP、TCP 穿透 NAT
上面講的情況可以直接應用于 UDP 穿透技術中,使用 TCP? 協議穿透 NAT? 的方式和使用 UDP? 協
議穿透 NAT? 的方式幾乎一樣,沒有什么本質上的區別,只是將無連接的 UDP? 變成了面向連接的 TCP? 。
值得注意是:
1、? B 在向 A 打洞時,發送的 SYN? 數據包,而且同樣會被 NAT_A? 丟棄。同時,B 需要在原來的
socket? 上監聽,由于重用 socket? ,所以需要將 socket? 屬性設置為 SO_REUSEADDR? 。
A 向 B 發送連接請求。同樣,由于 B 到 A 方向的孔已經打好,所以連接會成功,經過 3? 次握手
后,A 到 B 之間的連接就建立起來了。具體過程如下:
1、? S 啟動兩個網絡偵聽,一個叫【主連接】偵聽,一個叫【協助打洞】的偵聽。
2、? A 和 B 分別與 S 的【主連接】保持聯系。
3、? 當 A 需要和 B 建立直接的 TCP 連接時,首先連接 S 的【協助打洞】端口,并發送協助連接申請。同
時在該端口號上啟動偵聽。注意由于要在相同的網絡終端上綁定到不同的套接字上,所以必須為這些套
接字設置? SO_REUSEADDR? 屬性(即允許重用),否則偵聽會失敗。
4、? S 的【協助打洞】連接收到 A 的申請后通過【主連接】通知 B,并將 A 經過 NAT -A 轉換后的公網 IP
地址和端口等信息告訴 B。
5、? B 收到 S 的連接通知后首先與 S 的【協助打洞】端口連接,隨便發送一些數據后立即斷開,這樣做
6 / 6
的目的是讓 S 能知道 B 經過 NAT -B 轉換后的公網 IP 和端口號。
6、? B 嘗試與 A 的經過 NAT -A 轉換后的公網 IP 地址和端口進行 connect,大多數路由器對于不請自到的
SYN 請求包直接丟棄而導致 connect 失敗,但 NAT -B 會紀錄此次連接的源地址和端口號,為接下來真正
的連? 接做好了準備,這就是所謂的打洞,即 B 向 A 打了一個洞,下次 A 就能直接連接到 B 剛才使用的
端口號了。
7、? 客戶端 B 打洞的同時在相同的端口上啟動偵聽。B 在一切準備就緒以后通過與 S 的【主連接】回復
消息“我已經準備好”,S 在收到以后將 B 經過 NAT -B 轉換后的公網 IP 和端口號告訴給 A。
8、? A 收到 S 回復的 B 的公網 IP 和端口號等信息以后,開始連接到 B 公網 IP 和端口號,由于在步驟 6
中 B 曾經嘗試連接過 A 的公網 IP 地址和端口,NAT -B 紀錄了此次連接的信息,所以當 A 主動連接 B 時,
NAT -B 會認為是合法的 SYN 數據,并允許通過,從而直接的 TCP 連接建立起來了。
NAT 及 NAT 打洞技術
一、什么是 NAT?為什么要使用 NAT?
NAT 是將私有地址轉換為合法 IP 地址的技術,通俗的講就是將內網與內網通信時怎么將內網私有 IP 地址
轉換為可在網絡中傳播的合法 IP 地址。 NAT 的出現完美地解決了 lP 地址不足的問題,而且還能夠有效地
避免來自網絡外部的攻擊,隱藏并保護網絡內部的計算機。
二、NAT 的分類
STUN 標準中,根據內部終端的地址(LocalIP:LocalPort)到 NAT 出口的公網地址(PublicIP:PublicPort)的影
射方式,把 NAT 分為四種類型:
1、Full Cone NAT:? 內網主機建立一個 socket(LocalIP:LocalPort)? 第一次使用這個 socket 給外部主機發送數
據時 NAT 會給其分配一個公網(PublicIP:PublicPort),以后用這個 socket 向外面任何主機發送數據都將使用
這對(PublicIP:PublicPort) 。此外,任何外部主機只要知道這個(PublicIP:PublicPort) 就可以發送數據給
(PublicIP:PublicPort),內網的主機就能收到這個數據包。
2、 Restricted Cone NAT:? 內網主機建立一個 socket(LocalIP:LocalPort)? 第一次使用這個 socket 給外部主機發
送數據時 NAT 會給其分配一個公網(PublicIP:PublicPort),以后用這個 socket 向外面任何主機發送數據都將
使用這對(PublicIP:PublicPort)。此外,如果任何外部主機想要發送數據給這個內網主機,只要知道這個
(PublicIP:PublicPort)并且內網主機之前用這個 socket 曾向這個外部主機 IP 發送過數據。只要滿足這兩個
條件,這個外部主機就可以用自己的(IP,任何端口)發送數據給(PublicIP:PublicPort),內網的主機就能收到
這個數據包。
3、 Port Restricted Cone NAT:? 內網主機建立一個 socket(LocalIP:LocalPort)? 第一次使用這個 socket 給外部主
機發送數據時 NAT 會給其分配一個公網(PublicIP:PublicPort),以后用這個 socket 向外面任何主機發送數據
都將使用這對(PublicIP:PublicPort)。此外,如果任何外部主機想要發送數據給這個內網主機,只要知道這
個(PublicIP:PublicPort)并且內網主機之前用這個 socket 曾向這個外部主機(IP,Port)發送過數據。只要滿足
這兩個條件,這個外部主機就可以用自己的(IP,Port)發送數據給(PublicIP:PublicPort),內網的主機就能收到
這個數據包。
4、Symmetric NAT:? 內網主機建立一個 socket(LocalIP,LocalPort),當用這個 socket 第一次發數據給外部主機
1 時,NAT 為其映射一個(PublicIP -1,Port-1), 以后內網主機發送給外部主機 1 的所有數據都是用這個
(PublicIP -1,Port-1),如果內網主機同時用這個 socket 給外部主機 2 發送數據,NAT 會為其分配一個
(PublicIP -2,Port-2),? 以后內網主機發送給外部主機 2 的所有數據都是用這個(PublicIP -2,Port-2).如果 NAT 有
多于一個公網 IP,則 PublicIP-1 和 PublicIP-2 可能不同,如果 NAT 只有一個公網 IP,則 Port-1 和 Port-2 肯定
2 / 6
不同,也就是說一定不能是 PublicIP-1 等于? PublicIP-2 且 Port-1 等于 Port-2。此外,如果任何外部主機想
要發送數據給這個內網主機,那么它首先應該收到內網主機發給他的數據,然后才能往回發送,否則即
使他知道內網主機的一個(PublicIP,Port)也不能發送數據給內網主機,這種 NAT 無法實現 P2P 通信,但是
如果另一方是 Full Cone NAT,還是可以實現穿透的,下面我會詳細分析各種類型 NAT 穿透的情況。
NAT? 功能通常被集成到路由器、防火墻、ISDN 路由器或者單獨的 NAT 設備中。所以我們大家很少會知
道 NAT,上面 NAT 類型的概念描述是比較通俗的,但為了更便于理解,我再舉例闡述一下 NAT 的原理。
現有通信的雙方 A 和 B,當 A 和 B 都是在公網的時候,通信是不用 NAT 的。假設 A 在內網,內網 IP
是 192.168.1.3,端口號是 5000,A 經過 NAT 后的 IP 是 221.221.221.100,端口號是 8000,B 的 IP 是
202.105.124.100,端口是 8500。如果 B 要去主動連接 A,即使 B 知道 A 經過 NAT 后的 IP 和端口也是無
法連接成功的,因為 A 沒有向 B(202.105.124.100:8500)發送過數據,所以 B 的數據包會被 A 的 NAT 丟棄,
于是連接失敗。但是 A 如果去主動連接 B,由于 B 是在公網,所以會連接成功,通信也就會建立。這也
就是反彈連接木馬“反彈”二字的精髓。
當客戶端 A 和 B 都是處在內網的時候,雙方由于都不知道對方的公網 IP 和端口,就會無從下手,所以要
在客戶端 A 和 B 之間架設一臺服務器 S 來為它們牽線,而且 S 是處在公網,以保證 A 和 B 都能連接到 S。
客戶端 A 和 B 登錄時都首先連接 S,S 就會知道 A 和 B 經過 NAT 后的 IP 和端口,當 A 想要連接 B 時,就
像 S 發出請求, S 會把 B 經過 NAT 后的 IP 和端口告訴 A,同時 S 向 B 發送 A 經過 NAT 后的 IP 和端口,并
要求 B 發送數據給 A, B 發送數據到達 A 時會被 A 的 NAT 拋棄,但是 B 的 NAT 會有 B 發送數據到 A 的記
錄,這是 A 再向 B 發送數據時就會被 B 的 NAT 放行,因為 B 曾經向 A 的外網 IP 和端口發送過數據。可
能有點亂,下面以故事的形式敘述一下這個情景。
人物:A(男)? NAT_A(A 家接線員)??? B(女)? NAT_B?? (B 家接線員)? S
場景介紹:A 想認識 B,但是不知道 B 的電話,S 跟 A、B 都是朋友,并且知道 A 和 B 的電話。接線員的
職責:對往外轉接的電話不做詢問,對往內轉接的電話則要過濾以免有騷擾電話。過濾規則:在一定時
間內沒有撥打過的號碼就過濾。
首先 A 給 S 打電話:
A 說:我想認識你朋友 B,你把她電話給我唄。
S 說:行,她的電話是 PublicIP_B,我讓她先給你打個電話,要不她家接線員不幫你轉接。
A 說:好。
S 跟 B 打電話:
S 說:我有一個朋友 A,人挺好的,他想認識你,你給他打個電話,他的電話號碼是 PublicIP_A。
B 說:行,打完告訴你。
3 / 6
S 說:好的。
B 打電話到 A 家,B 家接線員 NET_B 看到女主人想往 PublicIP_A 打電話就轉接到 A 家了,同時把號碼
PublicIP_A 記錄下來,A 家接線員 NAT_A 一看號碼是個近期沒打過的號,就給掛斷了。
B 給 S 打電話:
B 說:我打完電話了
S 說:好,等著吧,一會他就給你打進來了。
S 給 A 打電話:
S 說:他給你打完電話了,你快點給她打。
A 打電話到 B 家,?? A 家接線員 NET_A 看到男主人想往 PublicIP_B 打電話就轉接到 B 家了, B 家接線員 NET_B
看到是剛剛撥過的 PublicIP_A 號碼打過來的,就轉接給 B 了,A 和 B 的電話也就打通了。
A 和 B 通話:
A 說:電話終于打通了,想認識你挺困難的。
B 說:是啊。
以上雖然和實際不太一樣,但穿透的整體過程基本就是這樣。 A 往 B 發送數據的唯一阻礙就
是 NET_B,所以想要成功發送數據,必須把 NET_B 穿一個洞,A 是無法完成這項工作的,所以就得讓 B
完成這個打洞操作,也就是讓 B 往 A 發送數據,這樣 NET_B 就會誤以為 A 發送的數據是上次會話的一部
分從而不予阻攔。
但是,由于 NAT 的類型沒有一個統一的標準,所以 NAT 穿透使用的技術有很多種,穿透的成功率也不一
樣。還有些 NAT 類型的內網之間幾乎無法穿透。下面我們用實例詳細分析一下各種 NAT 類型穿透的可行
性。
A 機器在私網(192.168.0.3)
A 側 NAT 服務器(221.221.221.100)
B 機器在另一個私網(192.168.0.5)
B 側 NAT 服務器(210.30.224.70)
C 機器在公網(210.202.14.36)作為 A 和 B 之間的中介
A 機器連接 C 機器,假使是 A(192.168.0.3:5000)->? A 側 NAT(轉換后 221.221.221.100:8000)->? C
(210.202.14.36:2000)
B 機器也連接 C 機器,假使是 B(192.168.0.5:5000)->? B 側 NAT(轉換后 210.30.224.70:8000)->? C
(210.202.14.36:2000)???? ?
4 / 6
A 機器連接過 C 機器后,A 向 C 報告了自己的內部地址(192.168.0.3:5000),此時 C 不僅知道了 A
的外部地址(C 通過自己看到的 221.221.221.100:8000)也知道了 A 的內部地址。同理 C 也知道了 B 的外
部地址(210.30.224.70:8000)和?? 內部地址(192.168.0.5:5000)。之后,C 作為中介,把 A 的兩個地址
告訴了 B,同時也把 B 的兩個地址告訴了 A。
假設 A 先知道了 B 的兩個地址,則 A 從 192.168.0.3:5000 處同時向 B 的兩個地址 192.168.0.5:5000
和 210.30.224.70:8000 發包,由于 A 和 B 在兩個不同的 NAT 后面,故從 A(192.168.0.3:5000)到 B
(192.168.0.5:5000)的包肯定不通,現在看 A(192.168.0.3:5000)到 B(210.30.224.70:8000)的包,分
如下兩種情況:?? ?
1、B 側 NAT 屬于 Full?? Cone?? NAT??? ?
則無論 A 側 NAT 屬于 Cone?? NAT 還是 Symmetric?? NAT,包都能順利到達 B。如果程序設計得好,使
得 B 主動到 A 的包也能借用 A 主動發起建立的通道的話,則即使 A 側 NAT 屬于 Symmetric?? NAT, B 發出
的包也能順利到達 A。
結論 1:只要單側 NAT 屬于 Full?? Cone?? NAT,即可實現雙向通信。
2、B 側 NAT 屬于 Restricted?? Cone 或 Port?? Restricted?? Cone??? ?
則包不能到達 B。再細分兩種情況
(1)、A 側 NAT 屬于 Restricted?? Cone 或 Port?? Restricted?? Cone
雖然先前那個初始包不曾到達 B ,但該發包過程已經在 A 側 NAT 上留下了足夠的記錄:A
(192.168.0.3:5000)->(221.221.221.100:8000)->B(210.30.224.70:8000)。如果在這個記錄沒有超時之
前, B 也重復和 A 一樣的動作,即向 A (221.221.221.100:8000)發包,雖然 A 側 NAT 屬于 Restricted??? Cone
或 Port? Restricted? Cone,但先前 A 側 NAT 已經認為 A 已經向 B(210.30.224.70:8000)發過包,故 B 向 A
(221.221.221.100:8000)發包能夠順利到達 A。同理,此后 A 到 B 的包,也能順利到達。
結論 2:只要兩側 NAT 都不屬于 Symmetric?? NAT,也可雙向通信。換種說法,只要兩側 NAT 都屬于
Cone?? NAT,即可雙向通信。
(2)、A 側 NAT 屬于 Symmetric?? NAT??? ?
因為 A 側 NAT 屬于 Symmetric?? NAT,且最初 A 到 C 發包的過程在 A 側 NAT 留下了如下記錄:A
(192.168.0.3:5000)->(221.221.221.100:8000)->? C(210.202.14.36:2000),故 A 到 B 發包過程在 A 側
NAT 上留下的記錄為:
A(192.168.0.3:5000)->(221.221.221.100:8001)->B(210.30.224.70:8000)(注意,轉換后端口產生
了變化)。而 B 向 A 的發包,只能根據 C 給他的關于 A 的信息,發往 A(221.221.221.100:8000),因為 A
端口受限,故此路不通。再來看 B 側 NAT,由于 B 也向 A 發過了包,且 B 側 NAT 屬于 Restricted??? Cone
5 / 6
或 Port??? Restricted?? Cone,故在 B 側 NAT 上留下的記錄為: B (192.168.0.5:5000) -> (210.30.224.70:8000)
->A(221.221.221.100:8000),此后,如果 A 還繼續向 B 發包的話(因為同一目標,故仍然使用前面的映
射),如果 B 側 NAT 屬于 Restricted??? Cone,則從 A (221.221.221.100:8001)來的包能夠順利到達 B;如
果 B 側 NAT 屬于 Port?? Restricted?? Cone,則包永遠無法到達 B。
結論 3:一側 NAT 屬于 Symmetric?? NAT,另一側 NAT 屬于 Restricted??? Cone,也可雙向通信。
反過來想,則可以得出另一個結論:兩個都是 Symmetric NAT 或者一個是 Symmetric?? NAT、另一個是
Port Restricted Cone,則不能雙向通信,因為 NAT 無法穿透。
上面的例子雖然只是分析了最初發包是從 A 到 B 的情況,但是,由于兩者的對稱性,前面得出的幾
條結論沒有方向性,雙向都適用。
我們上面得出了四條結論,natcheck 網站則把他歸結為一條:只要兩側 NAT 都屬于 Cone?? NAT(含
Full?? Cone、Restricted?? Cone 和 Port?? Restricted?? Cone 三者),即可雙向通信。沒有把我們的結論 3 包
括進去。
一般情況下,只有比較注重安全的大公司會使用 Symmetric NAT,禁止使用 P2P 類型的通信,很多地方使
用的都是 Cone?? NAT,因此穿透技術還是有發展前景的。
三、使用 UDP、TCP 穿透 NAT
上面講的情況可以直接應用于 UDP 穿透技術中,使用 TCP? 協議穿透 NAT? 的方式和使用 UDP? 協
議穿透 NAT? 的方式幾乎一樣,沒有什么本質上的區別,只是將無連接的 UDP? 變成了面向連接的 TCP? 。
值得注意是:
1、? B 在向 A 打洞時,發送的 SYN? 數據包,而且同樣會被 NAT_A? 丟棄。同時,B 需要在原來的
socket? 上監聽,由于重用 socket? ,所以需要將 socket? 屬性設置為 SO_REUSEADDR? 。
A 向 B 發送連接請求。同樣,由于 B 到 A 方向的孔已經打好,所以連接會成功,經過 3? 次握手
后,A 到 B 之間的連接就建立起來了。具體過程如下:
1、? S 啟動兩個網絡偵聽,一個叫【主連接】偵聽,一個叫【協助打洞】的偵聽。
2、? A 和 B 分別與 S 的【主連接】保持聯系。
3、? 當 A 需要和 B 建立直接的 TCP 連接時,首先連接 S 的【協助打洞】端口,并發送協助連接申請。同
時在該端口號上啟動偵聽。注意由于要在相同的網絡終端上綁定到不同的套接字上,所以必須為這些套
接字設置? SO_REUSEADDR? 屬性(即允許重用),否則偵聽會失敗。
4、? S 的【協助打洞】連接收到 A 的申請后通過【主連接】通知 B,并將 A 經過 NAT -A 轉換后的公網 IP
地址和端口等信息告訴 B。
5、? B 收到 S 的連接通知后首先與 S 的【協助打洞】端口連接,隨便發送一些數據后立即斷開,這樣做
6 / 6
的目的是讓 S 能知道 B 經過 NAT -B 轉換后的公網 IP 和端口號。
6、? B 嘗試與 A 的經過 NAT -A 轉換后的公網 IP 地址和端口進行 connect,大多數路由器對于不請自到的
SYN 請求包直接丟棄而導致 connect 失敗,但 NAT -B 會紀錄此次連接的源地址和端口號,為接下來真正
的連? 接做好了準備,這就是所謂的打洞,即 B 向 A 打了一個洞,下次 A 就能直接連接到 B 剛才使用的
端口號了。
7、? 客戶端 B 打洞的同時在相同的端口上啟動偵聽。B 在一切準備就緒以后通過與 S 的【主連接】回復
消息“我已經準備好”,S 在收到以后將 B 經過 NAT -B 轉換后的公網 IP 和端口號告訴給 A。
8、? A 收到 S 回復的 B 的公網 IP 和端口號等信息以后,開始連接到 B 公網 IP 和端口號,由于在步驟 6
中 B 曾經嘗試連接過 A 的公網 IP 地址和端口,NAT -B 紀錄了此次連接的信息,所以當 A 主動連接 B 時,
NAT -B 會認為是合法的 SYN 數據,并允許通過,從而直接的 TCP 連接建立起來了。
總結
以上是生活随笔為你收集整理的NAT 及 NAT 打洞技术的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 退出MFC应用程序的方法集
- 下一篇: TCP长连接,短连接