SOCKET 實現NAT 穿越

    在當前IPv4NAT盛行的網絡環境下,兩個用戶要直接進行P2P連接是非常困難的。較好的解決辦法是藉助含公網的用戶或是服務器中介實現P2P連接。

    NAT:Network Address Translation,網絡地址轉換。由於IPv4地址數量十分有限,不可能每一臺網絡設備都能擁有一個IP。於是NAT技術很好地解決了這個問題。路由設備被ISP分給一個公網地址,路由設備自己生成另外的局域網地址,局域網內部的信息通過路由器的網絡地址轉換,實現內部網絡與外部網絡的通信。

    對於通常的NAT,當一個內部地址向外部某個網絡發送信息:當信息到達NAT設備,NAT設備會首先查詢自己的地址轉換表。看是否有該內部地址-端口的地址轉換表,如果沒有,路由器會分配給該地址-端口一個可用的外網端口,並記錄在地址轉換表中。發送的數據包的源地址會修改爲NAT設備的公網地址,端口會變爲分配的端口(注意,是直接把IP頭部的內容修改了,外部網絡是沒辦法從協議頭中知道NAT內部主機的地址的), 然後發送至指定的外部地址。

    外部的數據發往內部的某個地址:剛纔提到了,外部網絡幾乎是不知道目的內網的地址的。他只知道該公網路由器的IP和端口(這種情況都是因爲內部實現聯絡了外網纔有外部向該內網通信)。外網只關心之前路由器發給他的數據是哪個地址哪個端口。發送信息就朝着這個地址和端口發送。因爲NAT設備上有相應的地址轉換表。發往改端口的數據會映射到內網的對應地址和端口。

    

    當內網的設備向外網發送數據,NAT設備會使用公網IP以及自己分配的端口爲內網設備轉發以及接收數據。生成的轉換表有會有一定的時限。大多數路由器接收數據要按照內部的地址信任表來,即:內網設備A通過NAT設備S發送至外網設備B,B可以根據S發送過來的端口發給S然後轉到A。但是網絡中另一個知道A在NAT上的地址與端口的設備C缺不能通過該端口通過S發送到A。因爲A沒有給C發送數據,路由器S並不信任C只信任B。但如果此時A再向C發送數據,此時就能使得S添加對C的信任,使得C能夠通過S發送數據到A。

    通過上面的這種理論,我們就能實現不同NAT間的網絡穿越。我們需要利用一箇中介服務器來傳遞需要連接的設備在NAT設備上的IP與端口信息。


    UDP實現NAT穿越(UDP打洞):

    服務器用來接收需要進行NAT穿越的設備在NAT設備上的IP和端口,假如有兩個設備A和B要建立連接,他們先要分別向服務器發送一個UDP數據包。服務器可以通過數據包得到A與B在NAT路由器上轉換後的IP和端口。此時A向服務器發送一個向B連接的請求,服務器便把B的地址-端口信息發送給A,通知A向B發送連接,並把A的信息發送個給B並通知他連接A。此時A和B都知道對方的IP與端口信息。各自先向對方地址發送一個UDP數據包。這是會有幾種情況:

        1、A和B都收到了對方發送的數據。(這種情況可能是至少有一個路由器已經信任對方的地址或是路由器不進行地址信任。也可能是網絡傳輸速度慢。兩個路由器都發送出數據後,數據纔到達兩個設備,此時兩個設備早已相互信任)

        2、A或B只有一個收到了對方發送的數據。(這是最常見的情況,因爲兩個數據包到達有先後,先發送數據的路由器已經對發送的地址產生了信任,而另一個路由器由於還沒有發送數據包就收到了數據,此時它是不信任該地址發過來的數據包的)

        3、都沒有收到數據包(

            a、A或B在NAT設備上的端口發生改變 

            b、A與B屬於同一NAT下,NAT設備不支持迴環轉換或做了連接限制

            c、NAT一個端口只信任一個外部地址

        )

如果是第三種情況,可能A與B就不能通過這種環境實現UDP的穿越。對於第二種情況,A與B需要在幾秒後再發送幾次數據包。如果還是一方全部都收不到。可能收不到這方的NAT設備上的端口發生改變或是NAT一個端口只信任一個外部地址,無法連接。但是通常都能成功的。

    說一下移動通信商網絡的NAT。中國聯通的NAT是這樣的:我使用聯通設備向服務器發送UDP數據包,服務器獲得的端口號是xxx,而我卻不能與另一設備實現NAT穿越。最後經我調試發現,我向另一設備發送數據NAT轉換後的端口又是另一個端口。我再向服務器發數據,卻是原來的xxx端口。查閱資料發現,聯通使用的是NAT3,對於不同的地址,NAT轉換爲不同的端口進行通信。因此不能普通地通過從服務器收到的端口進行連接。



程序實現:

首先兩個需要打洞的設備連接上位於公網118.112.50.95 的服務器(受條件限制,其中有一個設備也處於118.112.50.95的公網NAT下)。並獲得對方的IP和端口


wKioL1S3dpzgo4xXAAD0y40h-oY115.jpg

因爲此設備也位於服務器所在的公網下,但是是在NAT後的,他自己的公網ip也是118.112.50.95

對方設備的ip是118.113.89.4



wKiom1S3ddCzk4xKAAEDtdCRTq8703.jpg

此設備的ip:118.113.89.4,對方的ip爲118.112.50.95




然後我們用第一個設備(118.112.50.95)向服務器發起UDP連接(118.113.89.4)的請求,讓服務器告知(118.113.89.4)的設備連接自己。之後雙方會每隔幾秒向對方送一個hellow數據。共發送五次

wKioL1S3dpyTaDWGAAE7dnrneds936.jpg

該設備收到5次hellow


wKiom1S3ddCx4JM9AAFCqEQGCdY703.jpg

該設備只收到了4次hellow。因爲這個設備是被髮起連接的設備,所以發送數據包要晚一些。118.112.50.95先發過來的數據包的地址由於不被信任而被丟棄了。當自己向118.112.50.95發出數據包後。服務器開始信任118.112.50.95,於是就收到了118.112.50.95發送過來的剩下的條數據包。


附件所附帶的程序是中介服務器與客戶端混合在一起的(左邊下角,右下角客戶端)。左邊在公網設置監聽端口後就可以用另外的程序連接了。客戶端在左上角列表選中要連接的目的地址即通知服務器發起連接。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章