NAT
punchthrough success rates is based on what kind of algorithm the
NAT uses.
Full cone NAT: Accepts any datagrams to a port
that has been previously used. Will accept the first datagram from the
remote peer.
Address-Restricted cone NAT: Accepts datagrams
to a port as long as the datagram source IP address is a system we have
already sent to. Will accept the first datagram if both systems send
simultaneously. Otherwise, will accept the first datagram after we have
sent one datagram.
Port-Restricted cone NAT: Same as
address-restricted cone NAT, but we had to send to both the correct
remote IP address and correct remote port. The same source address and
port to a different destination uses the same mapping.
Symmetric NAT: A different port is chosen for
every remote destination. The same source address and port to a
different destination uses a different mapping. Since the port will be
different, the first external punchthrough attempt will fail. For this
to work it requires port-prediction (MAX_PREDICTIVE_PORT_RANGE>1)
and that the router chooses ports sequentially.
Success Graph
Router Type |
Full cone NAT |
Address-Restricted cone NAT |
Port-Restricted cone NAT |
Symmetric NAT |
Full cone NAT |
YES |
YES |
YES |
YES |
Address-Restricted cone NAT |
YES |
YES |
YES |
YES |
Port-Restricted cone NAT |
YES |
YES |
YES |
NO |
Symmetric NAT |
YES |
YES |
NO |
NO |
The NatTypeDetection plugins allow you to determine which type of NAT
you have, and therefore if NAT punchthrough is likely to complete or
not. This can be determined in advance of joining a game.
- Client opens two ports on the same IP address
- Server opens two ports on one IP address, and one port on four
additional IP addresses
- Client connects to the server on the first IP address normally
- Client requests NAT type detection begins
- Server attempts to send to client's second port. If received, then
the client is not behind a NAT.
- Server sends from a different IP address to client's first port.
If received, then the client is using full-cone NAT.
- Server sends from the second port on the already-connected IP
address. If received, then the client is using address-restricted cone
NAT.
- Client sends to another IP address on the server, from its first
(already connected) port. If the IP address and port is the same, then
the client uses the same external IP address and port to all connections
from the same source address. This is port-restricted NAT.
- Else symmetric NAT.
- Create an instance of the plugin: NatTypeDetectionServer
nayTypeDetectionClient;
- Attach the plugin to an instance of RakPeerInterface: rakPeer->AttachPlugin(&nayTypeDetectionClient);
- Connect to the server, and wait for
ID_CONNECTION_REQUEST_ACCEPTED. Use the following line to use the free
server provided by RakNet: rakPeer->Connect("8.17.250.34",
60481, 0, 0);
- Call DetectNATType with the SystemAddress of the server.
- Wait for ID_NAT_TYPE_DETECTION_RESULT
- Byte 1 contains the type of NAT that you have. See the
enumeration NATTypeDetectionResult in NATTypeDetectionCommon.h
- Various utility functions are provided for this enumeration: CanConnect(), NATTypeDetectionResultToString(),
NATTypeDetectionResultToStringFriendly()
- Host a server somewhere, not using NAT / e.g. behind a
firewall. (RakNet provides a free one at 8.17.250.34:60481, however you
may wish to host your own for consistent uptime). The server must have
enough external IP addresses, as described in NAT Type Detection
Algorithm.
- Create an instance of the plugin: NatTypeDetectionServernatTypeDetectionServer;
- Attach the plugin: rakPeer->AttachPlugin(&natTypeDetectionServer);
- Get a list of IP addresses on your system
char ipList[
MAXIMUM_NUMBER_OF_INTERNAL_IDS ][ 16 ];
unsigned int binaryAddresses[MAXIMUM_NUMBER_OF_INTERNAL_IDS];
SocketLayer::Instance()->GetMyIP( ipList, binaryAddresses );
- Call natTypeDetectionServer.Startup(ip2,ip3,ip4);
// ip2,ip3,ip4 must be ip addresses not already in use. If you bound
RakNet to ip1 in the call to RakPeer::Startup(), then use the 2nd to 4th
indices in ipList.
See the sample \Samples\NATCompleteClient
This is also implemented for the server in \Samples\NATCompleteServer
|