4. NAT Traversal

4.1. Introduction

RTI Cloud Discovery Service incorporates functionality that allows Connext DDS applications situated behind Network Address Translators (NATs) to discover and communicate with each other using UDP. This is possible when Cloud Discovery Service is configured to use RTI® RTI Real-Time WAN Transport 1. For further details, see the Real-Time WAN Transport in the Core Libraries User’s Manual.

Note

For a better understanding of this section, we recommend that you become familiar with the basic concepts explained in The Basics. We also assume that you are familiar with NAT traversal concepts and challenges. You can refer to Key Terms for a list of definitions and conventions used in this section.

Cloud Discovery Service can assist in the discovery and NAT traversal in the scenario depicted in Figure 4.1. Communication between two remote DomainParticipants that sit behind NATs cannot occur by any means, because they are unable to know how to reach each other.

_images/CdsNatUseCase.png

Figure 4.1 Communication challenge between applications behind NATs

DomainParticipants sitting behind a NAT are only aware of their own private IP transport addresses (iAddr:iPort). These are the only addresses they can exchange as part of the locators list they announce in their DomainParticipant announcements. In addition, their actual public IP transport addresses depend on the NAT forwarding rules, which are for the most part dynamic and impossible to know beforehand – unless a static configuration is set in the NAT-enabled routers.

In this situation, the only alternative is to consider a third player that can inform the remote DomainParticipants how they can reach each other through their public addresses. This third player is Cloud Discovery Service, in combination with the RTI Real-Time WAN Transport (RWT), which is used in the DomainParticipants.

_images/CdsNatTraversalConceptBasic.png

Figure 4.2 Public address resolution through Cloud Discovery Service

Figure 4.2 shows how Cloud Discovery Service acts as the entity that provides the resolution of public IP transport addresses. Cloud Discovery Service acts as an externally reachable service that obtains the public IP transport addresses from a DomainParticipant and provides them to the other DomainParticipants using RTPS locators. A resolved public IP transport address is called a service reflexive address (SRA).

Let’s examine Figure 4.2 in more detail to understand how Cloud Discovery Service assists with the NAT traversal. The scenario depicts two DomainParticipants behind NATs. Each DomainParticipant sends a participant announcement (or PA) to Cloud Discovery Service containing WAN locators. These locators can be UUID locators or UUID+PUBLIC locators depending on the configuration of RTI Real-Time WAN Transport. Cloud Discovery Service cannot forward the original PAs to peer DomainParticipants if they contain UUID locators, which are unreachable. Instead, Cloud Discovery Service will obtain the service reflexive address eA:eP, where eA is the public IPv4 address and eP is the public UDP port, and use it to replace the original UUID locator in the PA with a UUID+PUBLIC locator. DomainParticipants receive the forwarded and modified PAs from Cloud Discovery Service. These contain the public service reflexive addresses that are potentially reachable, thus making peer-to-peer communication possible.

Note that we say the SRAs are potentially reachable. The point is that these addresses will be reachable depending on the type of NAT that the DomainParticipant sits behind. We will see in further sections that only Cone NATs allow this communication, whereas Symmetric NATs don’t.

To help you understand this behavior, see Example: Using RTI Real-Time WAN Transport, where you will emulate the scenario described above in Figure 4.2. In that example, we will analyze step-by-step what you need to configure in Cloud Discovery Service and the application DomainParticipants. You can run the example first if you want to see it in action.

Footnotes

1

RTI Real-Time WAN Transport may require an additional license. Contact support@rti.com or your sales representative at RTI for further information.

4.2. Running Cloud Discovery Service with RTI Real-Time WAN Transport

To perform the public address resolution needed to assist in the discovery and communication of remote DomainParticipants behind NATs, you will need to run a Cloud Discovery Service instance on a publicly reachable host and enable RTI Real-Time WAN Transport (RWT). For that, you will need to configure the following Cloud Discovery Service parameters:

  • Service or host port host_port: This is the UDP port number where the Cloud Discovery Service instance will listen for PAs. This number shall be within the valid range for UDP ports and not taken by any other application running on the host.

  • Public IPv4 address public_addr: This is the publicly reachable address that external DomainParticipants can use to access the service host.

  • Public port public_port: This is the UDP port number that external remote DomainParticipants use to communicate with the service running on host_port.

If the service host is directly accessible to the WAN with no firewalls/NAT, the host_port is the same as the public_port, and public_addr also matches the local host address. If the service host is behind a NAT, then public_port represents the forwarded port statically configured in the NAT device, and can be a different number than host_port; also the public_addr will be different than the local host address.

4.2.1. Cloud Discovery Service configuration

To run Cloud Discovery Service using RWT, we will need to specify the host_port and public_addr. For example, in the following configuration:

<cloud_discovery_service name="CdsWanUdp">
    <transport>
        <element>
            <alias>builtin.udpv4_wan</alias>
            <receive_port>7400</receive_port>
            <property>
                <element>
                    <name>dds.transport.UDPv4_WAN.builtin.public_address</name>
                    <value>216.58.194.174</value>
                </element>
            </property>
        </element>
    </transport>
</cloud_discovery_service>
  • <receive_port> is set to the host_port.

  • The RWT property public_address is set to the public_addr.

In our example, we use one of the builtin configurations that enables RWT and parameterizes the values for the <receive_port> and public_address property using XML configuration variables. This way allows you to reuse the configuration with different values for each deployed Cloud Discovery Service instance.

Note

With the above configuration, if CDS is behind a NAT-enabled router, the host_port must be the same as the public_port. If you want to use a different public_port, it will be necessary to configure the property dds.transport.UDPv4_WAN.builtin.comm_ports. For additional information on this property, see the Real-Time WAN Transport in the Core Libraries User’s Manual.

4.2.2. Application DomainParticipant configuration

This is a very simple step where the application DomainParticipant is configured to use RWT and include the Cloud Discovery Service instance as part of the initial peers.

To enable RWT, simply select the corresponding builtin transport element in the DomainParticipant QoS configuration:

<domain_participant_qos>
    ...

    <transport_builtin>
        <mask>UDPv4_WAN</mask>
    </transport_builtin>
</domain_participant_qos>

Then when you run the application, set the initial peers to the Cloud Discovery Service, which is identified as follows:

rtps@public_addr:public_port

where public_addr and public_port are the properties described above and determine the public IP transport address that shall be reachable by external applications. To set the initial peers, you can use two methods:

  • Using the NDDS_DISCOVERY_PEERS environment:

    export NDDS_DISCOVERY_PEERS=rtps@udpv4_wan://216.58.194.174:7400
    
  • Configuring the initial_peers QoS:

    <domain_participant_qos>
        ...
    
        <discovery>
            <initial_peers>
               <element>rtps@udpv4_wan://216.58.194.174:7400</element>
            </initial_peers>
       </discovery>
    </domain_participant_qos>
    

Warning

The assumption is that <accept_unknown_peers> is set to true (which is the default value). This is important or else communication between DomainParticipants will not occur.

Then just run your applications with this setup and they will communicate over the WAN using DDS, purely peer-to-peer. To understand how this is possible, let’s look at Figure 4.3.

_images/CdsNatTraversalConceptDetail.png

Figure 4.3 Resolution of public address for DomainParticipants behind Cone NATs

In this scenario, there are two DomainParticipants behind Cone NATs, each uniquely identified by a global unique identifier (GUID). The DomainParticipant with GUID=1 has two private IP transport addresses, iA1:iP1 and iA1:iP2 (for simplicity, Figure 4.3 only shows iA1:iP1). iA1:iP1 is used to exchange DDS discovery traffic, iA1:iP2 is used to exchange user data traffic. DomainParticipant GUID=1 sends a DomainParticipant announcement PA1 containing two UUID locators, each one associated with one of the private IP transport addresses.

Upon reception of PA1, Cloud Discovery Service inspects the received UDP packet that contains the announcement and extracts the public IP transport addresses (eA1:eP1 and eA2:eP2) for each one of the UUID locators. These are the service reflexive addresses (SRAs) described above. The key step occurs when Cloud Discovery Service modifies the original announcement PA1 to extend each UUID WAN locator so it contains the associated SRA. This extended announcement PA1' is the one forwarded to the DomainParticipant with GUID=2, which can then use the SRA addresses to communicate peer-to-peer with DomainParticipant GUID=1. The same process applies to DomainParticipant GUID=2 and, in general, to any remote DomainParticipant in the domain.

In some cases, it is desirable to use a single public address for communication. This can be achieved by updating the configuration of RWT in the DomainParticipants as follows:

<domain_participant_qos>
    ...
    <transport_builtin>
        <udpv4_wan>
            <comm_ports>
                <default>
                    <host>16000</host>
                </default>
            </comm_ports>
        </udpv4_wan>
    </transport_builtin>
</domain_participant_qos>

With this configuration, the DomainParticipant with GUID=1 will have only one private IP transport address, iA1:iP1, where iP1 is 16000. The communication with the DomainParticipant will occur on a single public address eA1:eP1.

For additional details on how to configure RWT, see the Real-Time WAN Transport in the Core Libraries User’s Manual.

4.2.3. Communication between DomainParticipants

So far, we have explained the address resolution step that Cloud Discovery Service provides so that application DomainParticipants that sit behind NATs can communicate between themselves.

The address resolution is just the first step in providing the DomainParticipants with the public addresses of their peers. The second step is to establish communication between them: that occurs solely through RWT, without needing Cloud Discovery Service. Figure 4.4 provides a simplified view of how the communication is possible when the DomainParticipants are configured to use a single UDP port for communication (single WAN locator).

_images/CdsUdpWanUserTraffic.png

Figure 4.4 Direct communication over the WAN between DomainParticipants behind Cone NATs

A local DomainParticipant P1 will receive the resolved public address of a peer application DomainParticipant P2 from Cloud Discovery Service, that is, eA2:eP2. This is the address DomainParticipant P1 uses to reach the peer remote DomainParticipant P2. In the process of sending DDS traffic D1 to DomainParticipant P2, the NAT will temporarily open a hole H1. When D1 arrives at the host of P2, the NAT will let the incoming traffic come through hole H2. This is possible because:

  • DomainParticipant P2 is in parallel performing the same communication protocol, hence opening a temporary hole H2.

  • Both DomainParticipants sit behind NATs that always perform the same mapping between a private address iA:iP and a public address eA:eP, no matter the destination. This category of NATs includes:

    • Full-cone

    • Restricted-cone

    • Port-restricted cone

    This is not true for Symmetric NATs, which change the mapping based on the destination, so it’s not possible to use the SRA that Cloud Discovery Service obtains.

4.3. Communication scenarios using Cloud Discovery Service

Cloud Discovery Service support two basic WAN connectivity secenarios:

  1. Communication between DomainParticipants behind Cone-NATs.

  2. Communication with a DomainParticipant with well-known, reachable public IP addresses. If the DomainParticipant is behind a NAT, these public addresses must be statically configured in the NAT-enabled router.

For additional information see the Real-Time WAN Transport in the Core Libraries User’s Manual.

4.4. Debugging Cloud Discovery Service with the UDP WAN Transport

You can find out how Cloud Discovery Service is resolving addresses and for which DomainParticipants. Locator content depends on the transport implementation. The locators for RTI Real-Time WAN Transport convey the following information:

  • Flags: Indicate the type of WAN locator and included information.

  • UUID: Unique identifier that typically refers to a single network interface.

  • Public address: Contains the public IPv4 network address and UDP public port.

See the locator format section in RTI Connext DDS Core Libraries User’s Manual for more information about locators.

You can obtain locator resolution information in two ways: logging and remote administration.

4.4.1. Logging

Run Cloud Discovery Service with -verbosity ALL to enable the output of resolution log messages. The WAN locators will be represented with the following string format:

f=<flags>,u={<uuid>,P=<eAddr:ePort>}

You will find two type of messages:

  • New resolution: This is a log message generated in the event of resolving the IP public address for a UUID WAN locator. The log message will provide two important pieces of information. In the log context, in the content between the [], you will find the full WAN locator address in hexadecimal; in the message portion of the log, you will find the UUID and its resolved IP public address. For example, this log:

    [...|RESOLVE{UUID+PUBLIC=0x07BD73FC,0x9ED500AB,0x6D40DCD4:0xBC4E31D3}] \
            f=7,u={BD,73,FC,9E,D5,00,AB,6D,40},P=188.78.49.211:56532
    

    shows the following information:

    • UUID: BD,73,FC,9E,D5,00,AB,6D,40. Note that these nine bytes are the same as the first portion of the hexadecimal address in the log context.

    • Public IPv4 Address: 188.78.49.211

    • Public UDP Source Port: 56532

  • Resolution status: This is a log message displayed upon reception and forwarding of a DomainParticipant announcement (PA). This message displays the set of DomainParticipant locators in JSON format, for both meta-traffic and user-traffic, including the original locators received in the announcement and their resolved equivalent. For example:

    [...|DATAP{GUID=0x0101C372,0x17D4CED6,0xEA7B3DA5:0x000001C1}]
    {
       "locators": {
         "original":{
             "metatraffic": [
                     "udpv4_wan://f=1,u={BD,73,FC,9E,D5,00,AB,6D,40},P=10.0.2.15:0:32410"
                 ],
                 "default":[
                     "udpv4_wan://f=1,u={BD,73,FC,9E,D5,00,AB,6D,40},P=10.0.2.15:0:32411"
                 ]
         },
         "resolved":{
             "metatraffic": [
                 "udpv4_wan://f=7,u={BD,73,FC,9E,D5,00,AB,6D,40},P=188.78.49.211:56532:32410"
             ],
             "default": [
                 "udpv4_wan://f=7,u={BD,73,FC,9E,D5,00,AB,6D,40},P=188.78.49.211:51788:32411"
             ]
         }
       }
    }
    

    The last part of the context portion of the log identifies the remote DomainParticipant for which the locators are displayed; in this case it provides the GUID in hexadecimal format (GUID=0x0101C372,...). The message portion of the log shows that there are two UUID locators, one for each type of traffic, and it shows that each of them has been resolved properly, displaying the resolved public address in a format similar to the resolution log shown above.

    Note that the number of items between the original and resolved lists may differ and, in fact, length(resolved) <= length(original). If a UUID locator is not resolved or the resolved list is empty, it may be an indication of a connectivity problem. For example, the following log indicates that UUID locators have not been resolved:

    [...|DATAP{GUID=0x0101C372,0x17D4CED6,0xEA7B3DA5:0x000001C1}]
    {
       "locators": {
         "original": {
             "metatraffic": [
                 "udpv4_wan://f=1,u={BD,73,FC,9E,D5,00,AB,6D,40},P=10.0.2.15:0:32410"
             ],
             "default": [
                 "udpv4_wan://f=1,u={BD,73,FC,9E,D5,00,AB,6D,40},P=10.0.2.15:0:32411"
             ]
         },
         "resolved":{
             "metatraffic": [],
             "default": []
         }
       }
     }
    

    If you run into this situation, you can check that:

    • Cloud Discovery Service and the host it runs on are properly configured to receive external traffic on the receive port.

    • The remote DomainParticipants have properly set their initial peers to the public transport address where Cloud Discovery Service is reachable. Note that this address will be different than the host address of Cloud Discovery Service if it runs behind a NAT.

4.4.2. Administration

You can obtain a one-time snapshot of the locator resolution state for a given DomainParticipant using the remote administration capabilities (Remote Administration). Cloud Discovery Service offers a remote operation to retrieve the locator resolution state for a specified remote DomainParticipant (see the API specification).

For example, consider the resolution state log shown above. You could obtain the DomainParticipant locators by issuing the following command:

method: GET
resource: /cloud_discovery_services/[name]/database/locators
string_body: "0x0101C372,0x17D4CED6,0xEA7B3DA5:0x000001C1"

and you will get a response containing the resolution state in JSON format:

{
  "locators": {
     "original":{
        "metatraffic":[
            "udpv4_wan://f=1,u={BD,73,FC,9E,D5,00,AB,6D,40},P=10.0.2.15:0:32410"
        ],
        "default":[
            "udpv4_wan://f=1,u={BD,73,FC,9E,D5,00,AB,6D,40},P=10.0.2.15:0:32411"
        ]
    },
    "resolved":{
        "metatraffic":[
            "udpv4_wan://f=7,u={BD,73,FC,9E,D5,00,AB,6D,40},P=188.78.49.211:56532:32410"
        ],
        "default":[
            "udpv4_wan://f=7,u={BD,73,FC,9E,D5,00,AB,6D,40},P=188.78.49.211:51788:32411"
        ]
    }
  }
}

4.4.3. Identifying the NAT type

As we have mentioned, peer-to-peer communication between the remote DomainParticipants can only occur if they sit behind Cone NATs. Communication will not be possible if any of them is behind a Symmetric NAT. Therefore, it is mandatory that you verify the type of NAT your applications run.

There are multiple third-party utilities that you can download to find out about the NAT shielding your computer. One example is natat, a small open-source utility you can run locally to find out your NAT kind.

4.5. Key Terms

NAT Traversal

A mechanism to establish peer-to-peer connections across gateways that sit behind NATs.

IP Transport Address (or Address)

The combination of the IPv4 address and the UDP port where an application accepts incoming traffic. Sometimes you will also see the term “address” being used to refer to an IP transport address when the context is clear.

Public IP Transport Address (or Public Address)

An IP transport address for an application that is routable on a WAN. When the WAN is the Internet, the term “Internet-routable address” can be used instead.

Private IP Transport Address (or Private Address)

The IP transport address of an application that sits behind a NAT. This address is not reachable from external applications running outside the NAT.

eAddr:ePort

A public IP transport address, where eAddr is the public or external IPv4 address and ePort is the UDP public or external port.

iAddr:iPort

A private IP transport address, where iAddr is the private IPv4 address and iPort is the UDP host port.

Service Reflexive Address

The public IP transport address that Cloud Discovery Service obtains from the incoming UDP packets and is used for address resolution.

RTPS Locator (or Locator)

A DDS endpoint (DataWriter or DataReader) address unit that consists of a transport class, RTPS port, and locator transport address (128-bit).

Reachable locator: Locator associated with a DDS endpoint (DataWriter

or DataReader) to which another DDS endpoint can send data.

RTPS WAN Locator (or WAN Locator)

A locator for RTI Real-Time WAN Transport.

RTPS UUID WAN Locator (or UUID Locator)

A WAN locator for RTI Real-Time WAN Transport that is not reachable. Cloud Discovery Service transforms UUID locators into UUID+PUBLIC locators by associating a public IP transport address to the UUID. The public IP transport address for the UUID locator is the service reflexive address.

RTPS UUID+PUBLIC WAN Locator (or UUID+PUBLIC Locator)

A WAN locator for RTI Real-Time WAN Transport that is reachable. The locator encapsulates a public IP transport address as part of the locator address.

Address Resolution

The process of identifying the public address at which an application behind a NAT is reachable.

NAT forwarding mapping

A static configuration in the NAT device that allows mapping a public address to a private address, so external applications can send and receive data.

Application or Remote DomainParticipant

A DomainParticipant that is part of a Connext DDS application.

UDP Hole-Punching

A NAT traversal mechanism that consists of creating a temporary UDP forwarding mapping for an internal address.

GUID string representation

A representation of a DomainParticipant GUID, in a hexadecimal string with the following notation: host_id,app_id,instance_id:object_id.