NAT是在傳輸層及以上做的,傳輸層最主要的2個協議是TCP和UDP。對于TCP和UDP而言,每個包都有很基本的4個要素:src ip、src port、dst ip、dst port。
根據在做NAT的時候是否保留src ip和src port,可以把NAT分為這么三種:
Cone: 將src ip映射到一個固定的IP,并且將src port映射到一個固定的Port,無論dst ip和dst port是什么。
Single IP address, symmetric:將src ip映射到一個固定的IP,將src port映射到一個隨機的port,但是保證對于相同的(dst ip,dst port), src port始終相同。(否則雙方沒法通話啊,回來的包回給哪個端口呢?)
Multiple IP address, symmetric:與上面類似,但是src ip可能會有多個。
這三種之中,最簡單的就是Cone。根據對incoming packet的過濾限制,可能把Cone分為3種:
Full Cone: A full cone NAT is one where all requests from the same internal IP address and port are mapped to the same external IP address and port. Furthermore, any external host can send a packet to the internal host, by sending a packet to the mapped external address. 這種NAT通常被稱為static NAT,比如拿iptables redirect作端口轉發。
Restricted Cone: A restricted cone NAT is one where all requests from the same internal IP address and port are mapped to the same external IP address and port. Unlike a full cone NAT, an external host (with IP address X) can send a packet to the internal host only if the internal host had previously sent a packet to IP address X.這種就是當有連接的時候,洞才打開。只限制IP,通訊的另一方,可以用任意端口。
Port Restricted Cone: A port restricted cone NAT is like a restricted cone NAT, but the restriction includes port numbers. Specifically, an external host can send a packet, with source IP address X and source port P, to the internal host only if the internal host had previously sent a packet to IP address X and port P. 既限制IP又限制端口。
對于Cone,可采用很簡單的NAT穿透的方式建立P2P直連。
RTMFP中的P2P打洞過程:
假設一共三個角色:Server、Initiator(Peer1)、Target(Peer2)。Peer2已經與Server建立RTMFP連接,現在Peer1要連接Peer2。
Peer1首先向Server發InitiatorHello請求,其中帶上Peer2的peerID。Peer1此時并不知道Peer2的地址,它只知道PeerID。
Server向Peer1回復一個Redirect消息,里面包含Peer2的公網IP端口(通過UDP包頭可以得到)、以及Peer2的所有內網IP端口(Peer2自己可以得知,它在建立完和Server的連接后會通過SetPeerInfo匯報給Server)。
稍等一小會兒(1秒左右),Server給Peer2回復一個Forward Message,里面包含Peer1的公網IP端口。
RTMFP Redirect消息就像HTTP的302一樣,收到者(Peer1)需要向新地址重新建立連接,即發送InitiatorHello包。RTMFP Redirect消息中是一個IP端口的列表,每個IP端口都要去嘗試。
Forward Message就像servlet里面的forward一樣,收到者(Peer2)需要直接給原始的請求者回包(回Response Hello)。
對Peer1來說,哪個地址先回給它第一個Response Hello包,它就跟哪個地址繼續握手。
假設Peer1和Peer2處于同一個NAT中,那么會盡量通過redirect消息進行直連,以后的交互就跟NAT沒有關系。
假設Peer1和Peer2處于不同的NAT之中,兩個NAT類型都是Port Restricted Cone,那么Peer1收到Redirect消息的時候,然后向Peer2發送InitiatorHello的時候,就在Peer1的NAT上打了一個洞。雖然這個InitiatorHello也許會被Peer2的防火墻攔掉,但是沒有關系,正因為有了這個洞,Peer2的ResponseHello才能進來。
假設Peer1是處于symmetric single IP NAT之后,那么Server給Peer2的地址其實是一個錯誤的地址(端口號不對),所以Peer2收到Forward消息后所作的那個ResponseHello包,Peer1根本就收不到。但是假如Peer2是Restricted Cone,發完這個ResponseHello之后它就能接收來自Peer1的任何端口包。所以它們能接著Redirect消息之后的流程繼續走下去。
如果很不幸,Peer2也是處于symmetric single IP NAT之后,那么Peer2在回復Forward消息的時候就要采用猜端口的方式,給Peer1多發幾個ResponseHello包,如果有幸猜中了Peer1答復Redirect消息時所采用的端口,那么兩者就可以連接起來了。不過Flash好像沒有這么做。
NAT檢查工具:http://cc.rtmfp.net/
Public UDP port number same as local UDP port number:這個是指NAT是否將src port做了轉換。
Can receive from same IP address, same UDP port number:這個值應當永遠是Yes。因為如果連這個檢查都通不過,連接根本就建立不起來。
Can receive from same IP address, different UDP port number:如果這個值是true,說明是Port Restricted Cone,它會把出去的包的dst port記錄下來,然后收到包時檢查port number。
Can receive from different IP address, different UDP port number:如果這個值是true,說明是Restricted Cone,即它不對端口號做檢查。
Can send to different IP address after server introduction:這個值應當永遠是Yes。
Source IP address is preserved from original connection:這個是看server收到的包是否都來自于同一個IP。這個有一定的假陽性在里面,只要有一次為false,就說明用的是Multiple IP address symmetric NAT。
Source UDP port number is preserved from original connection:true說明是cone NAT,false說明是symmetric NAT。
我自制了一張連通性圖:
Restricted Cone | Port Restricted Cone | symmetric single IP | symmetric multiple IP | |
Restricted Cone | Yes | Yes | Yes | No |
Port Restricted Cone | Yes | Yes | No | No |
symmetric single IP | Yes | No | No | No |
symmetric multiple IP | No | No | No | No |
原文轉自:http://www.anti-gravitydesign.com