Microsoft DirectX 8.1 (C++)

Network Address Translation, Firewalls, and Proxies

Network Address Translators (NATs), firewalls, and proxies pose similar challenges when designing a game that allows players on different computers to connect to each other. NATs are used to share a single Internet Protocol (IP) address between multiple machines. This means that a machine's internal IP address will be different from its external IP address, and can result in complications when using Microsoft® DirectPlay®. Firewalls and proxies are used to prevent unauthorized access to a network or machine and are usually designed to be transparent. This section describes how to properly configure your game to work with NATs, firewalls, and proxies.

Using NATs

NATs work best with applications where the server is not behind a NAT and the clients do not communicate directly with each other. If you want your application to run through any hardware or software NAT, you should follow these guidelines:

You can create an application that does not follow these guidelines, but it is not recommended.

In order for clients to enumerate the game's port directly, the client needs to know the host server's port. The client can get this knowledge through a third party, such as a matchmaking system, or the game can be programmed to use a particular port. Of the two options, using the third party is more flexible and is the better solution. If the server is not using a particular port, it should call the GetLocalHostAddresses method to determine on what port it is hosting and communicate that information to the third-party matchmaking service.

A client enumerates the game's port directly by explicitly specifying the port number in the IDirectPlay8Address object passed as the pdpaddrHost parameter in the IDirectPlay8Client::EnumHosts call as shown in the following example.

// Add host port to the address.
hr = g_pHostAddress->AddComponent( DPNA_KEY_PORT,             // pwszName
                                   &dwPort, sizeof(dwPort),   // lpvData, dwDataSize
                                   DPNA_DATATYPE_DWORD );     // dwDataType
.
.
.

// Enumerate host.
hr = g_pDPClient->EnumHosts(&dpAppDesc,                       // pApplicationDesc
                            g_pHostAddress,                   // pdpaddrHost
                            g_pDeviceAddress,                 // pdpaddrDeviceInfo
                            NULL, 0,                          // pvUserEnumData, size
                            4,                                // dwEnumCount
                            0,                                // dwRetryInterval
                            0,                                // dwTimeOut
                            NULL,                             // pvUserContext
                            NULL,                             // pAsyncHandle
                            DPNENUMHOSTS_SYNC );              // dwFlags

If you do use enumeration instead of connecting directly, you should keep the enumeration active and pass the host and device addresses indicated in the DPN_MSGID_ENUM_HOSTS_RESPONSE message without modification to the call to Connect. To do this, complete the following tasks.

  1. Specify INFINITE for the dwEnumCount parameter in the call to the IDirectPlay8Client::EnumHosts method.
  2. Use IDirectPlay8Address::Duplicate and IDirectPlay8Address::AddRef when handling the DPN_MSGID_ENUM_HOSTS_RESPONSE message to get private references to the address objects.
  3. Store the address object pointers in a global location using threadsafe code.
  4. Retrieve the address object pointers using threadsafe code when the user selects the session to join.
  5. Pass the address object pointers into the call to Connect.
  6. Release the references to the address objects when you are done.

DirectPlay will cancel the enumeration when the Connect method completes successfully. Do not call CancelAsyncOperation to end the enumeration unless the Connect method completes with a failure. For an example of how to store, retrieve, and release addresses using threadsafe code, see the code for the DirectPlay Samples.

If you want to allow end users to run their own servers, advise them not to put their game servers behind a NAT, or to explicitly configure their NAT to forward the game host's specific ports to the host machine. End users can also use Microsoft® Windows® Millennium Edition (Windows Me) or Microsoft® Windows XP Internet Connection Sharing (ICS) as their NAT to achieve this same result.

If your game is not able to follow these rules, for example if it is a peer-to-peer game, that game will have problems with most NATs. There is no way to implement a true peer-to-peer networking session where arbitrary users are behind arbitrary NATs. The behavior in this case is much improved when the end users are using Windows Me or Windows XP ICS as their NAT.

Some NATs perform special processing for particular applications or protocols. Windows ICS performs some special processing for DirectPlay. Different versions of Windows ICS perform different processing, depending on what version of DirectPlay was current at the time the Windows ICS was released.

Compatibility for Client/Server Games with NATs

The following sections discuss compatibility issues for client/server games depending on the NAT being used.

Windows 98 Second Edition ICS, Windows 2000 ICS, and third-party non-Universal Plug and Play NATs

Multiple clients behind Windows 98 Second Edition ICS, Windows 2000 ICS, or third-party NATs that are not Universal Plug and Play (UPnP)-compliant can join a client/server game hosted by a server that is not behind a NAT, as long as the clients behind the NAT use direct host enumeration as described earlier. Clients behind non-UPnP NATs are more likely to be able to join a DirectPlay client/server game if the server is not behind a NAT and the clients use direct host enumeration.

DirectPlay might be able to support a server behind these NATs in some cases. However, the application will not work automatically. The end users will need to enable port forwarding. If you selected a port on which to host, they must manually configure their NAT to redirect traffic received externally to the internal host on that port. Be aware that you cannot have more than one server behind the NAT. If you do not select a port, they can attempt to enable port forwarding for the DPNSVR port 6073 and the game port. DirectPlay will usually select port 2302 for the game port, but if there are other DirectPlay applications running, it will select the next sequential port number available (for example, 2303). The user should consult the documentation for the NAT that they are using for information on setting up port forwarding.

Note  Most NATs do not support enumeration through the DPNSVR port for client applications. This is because the client sends initial outbound traffic to the DPNSVR port, but the reply comes from the game port. Clients can attempt to enable port forwarding for the game port, but like servers, this design limits the user to only one client behind the NAT.

Windows Me ICS, Windows XP ICS, and UPnP-compliant NATs

Multiple clients behind a Windows Me ICS machine can join a client/server game hosted by a server not behind a NAT, even if the clients do not use direct host enumeration. However, the Windows Me ICS machine sometimes has problems joining games. The Windows Me ICS machine can usually join the game if it joins the session before any of the clients behind the ICS machine join the game. If the ICS machine does not join first, clients behind the ICS machine will be able to join but the client on the ICS machine might not be able to join.

Servers can be located inside the Windows Me ICS machine and still be seen from outside the NAT. No extra configuration is required in ICS or in the application.

Windows XP ICS and other UPnP-compliant NATs can also cooperate with DirectPlay and should not require extra configuration to support clients or servers behind the NAT. If you are having trouble hosting on a Windows XP ICS machine, be sure that the "Allow other network users to control or disable the shared Internet connection" box is checked.

No NAT can have multiple hosts using the same fixed port simultaneously. If you are using Windows Me ICS, Windows XP ICS, or UPnP-compliant third-party NATs and you specify a port already in use, you will receive the DPNERR_INVALIDDEVICEADDRESS return code when the Host method is called. You can allow DirectPlay to select a port and use DPNSVR enumeration or call the GetLocalHostAddresses method to reach the session. Alternatively, you can allow your users to manually override the fixed port.

Note   When hosting behind these NATs, the GetLocalHostAddresses method returns the public address (the external interface on the NAT machine). Machines outside or inside the NAT can use this address to join the session. It does not return the address of the local network interface card (NIC).

Compatibility for Peer-to-Peer Games with NATs

The following sections discuss compatibility issues for peer-to-peer games depending on the NAT being used.

Windows 98 Second Edition ICS, Windows 2000 ICS, and third-party non-UPnP NATs

IDirectPlay8Peer will not function properly through Windows 98 Second Edition ICS, Windows 2000 ICS, and third-party NATs that are not UPnP-compliant. However, you might be able to get some scenarios working, with the following considerations:

Note  Most NATs do not support enumeration through the DPNSVR port for peer applications. This is because the peer sends initial outbound traffic to the DPNSVR port, but the reply comes from the game port. Peers can attempt to enable port forwarding for the game port, but like hosts, this design limits the user to only one peer behind the NAT.

Windows Me ICS, Windows XP ICS, and UPnP-compliant NATs

Windows Me ICS, Windows XP ICS, and UPnP-compliant NATs cooperate with DirectPlay to make it possible to run full-featured, peer-to-peer DirectPlay sessions through the NAT. Users can host or join DirectPlay sessions that are hosted inside or outside the NAT. No special configuration is required. Even host migration is fully functional.

However, the restriction for Windows Me ICS mentioned previously in the client/server case holds true—the client on the Windows Me ICS machine must join the session before any client behind the NAT joins the session or else the ICS machine will not be able to join.

As with client/server sessions, no NAT can have multiple hosts using the same fixed port simultaneously. The call to IDirectPlay8Peer::Host will fail if the port is already in use on Windows Me ICS, Windows XP ICS, or UPnP-compliant NATs. For more information, see the client/server section.

Note  When hosting behind Windows Me ICS, Windows XP ICS, or UPnP-compliant NATs, the GetLocalHostAddresses method returns the public address (the external interface on the NAT machine). Machines outside or inside the NAT can use this address to join the session. It does not return the address of the local NIC.

Using Firewalls and Proxies

Applications work best when the server is not behind a firewall or proxy and the clients do not communicate directly with each other. If you want your application to run through any hardware or software firewall, you should follow these guidelines.

You can create an application that does not follow these guidelines but it is not recommended.

Compatibility for Client/Server Games Using Firewalls and Proxies

The following sections discuss compatibility issues for client/server games, depending on the firewalls and proxies being used.

Windows XP Internet Connection Firewall

DirectPlay works with the Internet Connection Firewall (ICF) capabilities of Windows XP. When your application begins hosting, enumerating, or connecting, the appropriate ports will automatically open and when your application shuts down, these ports will automatically close. However, the user launching the application must be a member of the administrator group for the computer so that DirectPlay has the security permissions to open the ports.

Third-Party Firewalls

DirectPlay is unable to configure third-party firewalls automatically. Clients behind a third-party firewall should work if the firewall allows outbound UDP traffic.

To support servers behind a third-party firewall, end users will have to manually configure their firewall. If you select a port for the local device address, end users must configure their firewall to open that port. If you do not select a local port, end users need to attempt to open the DPNSVR port 6073 and the game port. DirectPlay usually selects port 2302 for the game port but, if there are other DirectPlay applications running, it will select the next sequential port number available (for example, 2303). Users should consult their firewall's documentation for information on opening ports.

Microsoft Internet Security and Acceleration Server and Third Party Proxies

DirectPlay works with the Microsoft Internet Security and Acceleration (ISA) Server and other proxies when running client applications. Clients that have the ISA Firewall Client software installed should not cancel the enumeration before connecting and should pass the address objects from the DPN_MSGID_ENUM_RESPONSE as described in the Using NATs section. If the enumeration is cancelled, the ISA Server can close the virtual connection established by the enumeration and the call to Connect will fail.

If you want to support a server application behind an ISA Server proxy, the end user must configure the ISA Server. If you have selected a port for the local device address, end users must configure the ISA Server to redirect traffic received externally to the internal host on that port. If you do not select a local port, end users can attempt to configure the ISA Server for the DPNSVR port 6073 as well as the game port. DirectPlay will usually select port 2302 for the game port, but if there are other DirectPlay applications running, it will select the next sequential port number available (for example, 2303). The user should consult the product documentation for how to configure their proxy.

Note  Most proxies do not support enumeration through the DPNSVR port for client applications. This is because the client sends initial outbound traffic to the DPNSVR port, but the reply comes from the game port. Clients can attempt to enable port forwarding for the game port, but like servers, this design limits the user to only one client behind the proxy.

Compatibility for Peer-to-Peer Games Using Firewalls and Proxies

The following sections discuss compatibility issues for peer-to-peer games depending on the firewalls and proxies being used.

Windows XP Internet Connection Firewall

DirectPlay works with the Internet Connection Firewall (ICF) capabilities of Windows XP. When your application begins hosting, enumerating, or connecting, the appropriate ports will automatically open and when your application shuts down, these ports will automatically close. However, the user launching the application must be a member of the administrator group for their computer, so that DirectPlay has the security permissions to open the ports.

Third-Party Firewalls

DirectPlay is unable to configure third-party firewalls automatically.

To support a host behind a third-party firewall, the end user will have to manually configure their firewall. If you select a port for the local device address, end users must configure their firewall to open that port. If you do not select a local port, end users can attempt to open the DPNSVR port 6073 and the game port. DirectPlay usually selects port 2302 for the game port, but if there are other DirectPlay applications running, it will select the next sequential port number available (for example, 2303). The user should consult their firewall's documentation for information on opening ports.

Microsoft Internet Security and Acceleration Server and Third Party Proxies

DirectPlay works with the Microsoft Internet Security and Acceleration (ISA) Server and other proxies when running peer applications. Peers that have the ISA Firewall Client software installed should not cancel the enumeration before connecting and should pass the address objects from the DPN_MSGID_ENUM_RESPONSE as described in the Using NATs section. If the enumeration is cancelled, the ISA Server can close the virtual connection established by the enumeration and the call to Connect will fail.

If you want to support a server application behind an ISA Server proxy, the end user must configure the ISA Server. If you have selected a port for the local device address, end users must configure the ISA Server to redirect traffic received externally to the internal host on that port. If you do not select a local port, end users can attempt to configure the ISA Server for the DPNSVR port 6073 as well as the game port. DirectPlay will usually select port 2302 for the game port, but if there are other DirectPlay applications running, it will select the next sequential port number available (for example, 2303). The user should consult the product documentation for how to configure their proxy.

Note  Most proxies do not support enumeration through the DPNSVR port for client applications. This is because the client sends initial outbound traffic to the DPNSVR port, but the reply comes from the game port. Clients can attempt to enable port forwarding for the game port, but like servers, this design limits the user to only one client behind the proxy.