Suggestions

close search
Speed up your development
Create a Fast Track

Add Messaging, Voice, and Authentication to your apps with Vonage Communications APIs

Visit the Vonage API Developer Portal

Configurable TURN servers

You can configure the TURN servers used by an OpenTok client.

This feature is available as an add-on feature.

This topic includes the following sections:

Overview

You can customize TURN server usage for each client in the session in the following ways:

Adding your own TURN servers can help users connect in restrictive network environments where OpenTok TURN servers might be blocked.

If you chose to override the OpenTok TURN servers and only use your own TURN servers, you can make sure that media streams never leave your network.

You can add your own TURN servers for each client connecting to the session, using OpenTok.js (for web clients), the OpenTok iOS SDK, or the OpenTok Android SDK. The custom TURN server API was added in version 2.13.0 of these client SDKs.

There is also an IP proxy add-on feature that lets you use your own proxy server to route non-media traffic—such as Video API calls, WebSocket connections, and log traffic.

OpenTok.js

The options parameter of the OT.initSession() method includes an iceConfig property. This property includes the following properties:

Note: To have the client only use the TURN servers you specify (and not use the OpenTok TURN servers): set the includeServers property to 'custom', set the transportPolicy property to 'relay', and set the customServers property to list your TURN servers.

To update custom TURN credentials dynamically, use the Session.setIceConfig() method.

The following example shows how to configure TURN servers for the client:

const session = OT.initSession(projectId, sessionId, {
  iceConfig: {
    includeServers: 'custom',
    transportPolicy: 'relay',
    customServers: [
      {
        urls: [
          'turn:123.124.125.126:3478?transport=udp',
          'turn:123.124.125.126:3478?transport=tcp'
        ],
        username: 'webrtc',
        credential: 'foO0Bar1'
      },
      {
          urls: [
            'turns:turntls.example.com:3478?transport=tcp'
          ],
          username: 'webrtc',
          credential: 'foO0Bar2',
      },
    ],
  },
});

OpenTok Android SDK

The Session.Builder class includes two methods for configuring TURN server usage for the client:

In addition to the two new methods, two new enums define TURN server options:

Note: To have the client only use the TURN servers you specify (and not use the OpenTok TURN servers), call the following methods of the Session.Builder object you use to create the Session object:

The following example shows how to configure TURN servers for the client:

List<IceServer> serverList = new IceServer(
  'turn:123.124.125.126:3478?transport=udp', // TURN server URL
  'webrtc', // Username
  'foO0Bar1' // Credential
);
mSession = new Session.Builder(this, apiKey, sessionId)
  .setCustomIceServers(serverList, IncludeServers.Custom)
  .setIceRouting(TransportPolicy.TURN)
  .build();
mSession.setSessionListener(this);
mSession.connect(token);

OpenTok iOS SDK

When you initialize an OTSession object, set the OTSessionSettings.iceConfig property to define custom TURN server configuration for the client. The OTSessionICEConfig class defines the OTSessionSettings.iceConfig property.

Note: To have the client only use the TURN servers you specify (and not use the OpenTok TURN servers), call the [OTSessionSettings addICEServerWithURL:] method of the OTSessionSettings object you use to create the OTSession object. Then set the following properties of the OTSessionSettings object:

You can set the OTSessionICEConfig.filterOutLanCandidates property to prevent subscribing to clients on the same local network in relayed sessions, which results in the app prompting the user for permission in iOS 14+. Note that this feature does not require the configurable TURN add-on. For more info, see this topic. joliveraortega marked this conversation as resolved.

The following example shows how to configure TURN servers for the client:

OTSessionICEConfig *myICEServerConfiguration = [[OTSessionICEConfig alloc] init];
myICEServerConfiguration.includeServers = OTSessionICEIncludeServersCustom;
myICEServerConfiguration.transportPolicy = OTSessionICETransportRelay;

NSError *error = nil;
[myICEServerConfiguration addICEServerWithURL:@"turn:123.124.125.126:3478?transport=udp"
                                     userName:@"webrtc"
                                   credential:@"foO0Bar1"
                                        error:&error];

OTSessionSettings *settings = [[OTSessionSettings alloc] init];
settings.iceConfig = myICEServerConfiguration;

_session = [[OTSession alloc] initWithApiKey:kApiKey
                                   sessionId:kSessionId
                                    delegate:self
                                    settings:settings];

OpenTok Windows SDK

Use the IceConfig class to set the custom ICE configuration to be used by the client.

The IceConfig() constructor method includes the following parameters:

The Session.Builder class includes an IceConfig property. Set this to an IceConfig object when building the Session object.

The following example shows how to configure TURN servers for the client:

List<IceServer> iceServers = new List<IceServer>() {
  new IceServer(
    "turn:123.124.125.126:3478?transport=udp", "webrtc", "fo0Bar1"
  )
};
IceConfig iceConfig = new IceConfig(
  iceServers,
  ICETransport.Relayed,
  ICEIncludeServers.Custom
);
session = new Session.Builder(context, apiKey, sessionId){
  IceConfig = iceConfig
}.Build();

OpenTok macOS SDK

The type otc_custom_ice_config defines a struct that includes the following members:

Call the otc_session_settings_set_custom_ice_config() function and pass in the otc_custom_ice_config instance:

otc_session_settings_set_custom_ice_config(session_settings,
                                           &ice_config);

The following example shows how to configure TURN servers for the client:

// Provide the ICE configuration here.
struct otc_custom_ice_config ice_config;
ice_config.num_ice_servers = 1;
ice_config.ice_url = (char **)malloc(sizeof(char *) * ice_config.num_ice_servers);
ice_config.ice_url[0] = strdup("turn:123.124.125.126:3478?transport=udp");
ice_config.ice_user = (char **)malloc(sizeof(char *) * ice_config.num_ice_servers);
ice_config.ice_user[0] = strdup("webrtc");
ice_config.ice_credential = (char **)malloc(sizeof(char *) * ice_config.num_ice_servers);
ice_config.ice_credential[0] = strdup("foO0Bar1");
ice_config.force_turn = OTC_TRUE;
ice_config.use_custom_turn_only = OTC_FALSE;

otc_session_settings *session_settings = otc_session_settings_new();
if (session_settings != NULL) {
  otc_session_settings_set_custom_ice_config(session_settings,
                                             &ice_config);
}

otc_session *session = NULL;

session = otc_session_new_with_settings(API_KEY,
                                        SESSION_ID,
                                        &session_callbacks,
                                        session_settings);

if (session == NULL) {
  printf("Could not create OpenTok session successfully");
  return EXIT_FAILURE;
}

otc_session_connect(session, TOKEN);

OpenTok Linux SDK

The type otc_custom_ice_config defines a struct that includes the following members:

Call the otc_session_settings_set_custom_ice_config() function and pass in the otc_custom_ice_config instance:

otc_session_settings_set_custom_ice_config(session_settings,
                                           &ice_config);

The following example shows how to configure TURN servers for the client:

// Provide the ICE configuration here.
struct otc_custom_ice_config ice_config;
ice_config.num_ice_servers = 1;
ice_config.ice_url = (char **)malloc(sizeof(char *) * ice_config.num_ice_servers);
ice_config.ice_url[0] = strdup("turn:123.124.125.126:3478?transport=udp");
ice_config.ice_user = (char **)malloc(sizeof(char *) * ice_config.num_ice_servers);
ice_config.ice_user[0] = strdup("webrtc");
ice_config.ice_credential = (char **)malloc(sizeof(char *) * ice_config.num_ice_servers);
ice_config.ice_credential[0] = strdup("foO0Bar1");
ice_config.force_turn = OTC_TRUE;
ice_config.use_custom_turn_only = OTC_FALSE;

otc_session_settings *session_settings = otc_session_settings_new();
if (session_settings != NULL) {
  otc_session_settings_set_custom_ice_config(session_settings,
                                             &ice_config);
}

otc_session *session = NULL;

session = otc_session_new_with_settings(API_KEY,
                                        SESSION_ID,
                                        &session_callbacks,
                                        session_settings);

if (session == NULL) {
  printf("Could not create OpenTok session successfully");
  return EXIT_FAILURE;
}

otc_session_connect(session, TOKEN);

OpenTok React Native SDK

The options prop of the OTSession component includes an iceConfig property. This object includes the following properties:

Note: To have the client only use the TURN servers you specify (and not use the OpenTok TURN servers): set the includeServers property to 'custom', set the transportPolicy property to 'relay', and set the customServers property to list your TURN servers.

The following example shows how to configure TURN servers for the client:

<OTSession
  apiKey="your-api-key"
  sessionId="your-session-id"
  token="your-session-token"
  options={{
    iceConfig:{
      transportPolicy: 'all',
      includeServers: 'all',
      customServers: [
        {
        urls: [
          'turn:123.124.125.126:3478?transport=udp',
          'turn:123.124.125.126:3478?transport=tcp'
        ],
        username: 'webrtc',
        credential: 'foO0Bar1'
        },
      ],
    }
  }}
>
  <OTPublisher style={{ width: 600, height: 400 }}/>
  <OTSubscriber style={{ width: 600, height: 400 }} />
</OTSession>

Known issue

If you set a client to always use TURN servers in a relayed session, it will not be able to subscribe to its own streams (streams it publishes).

FAQs

Does the configurable TURN API address the issue for HTTP traffic?

No. Configurable TURN allays customers’ concerns around connecting to trusted end-points for media traffic only.

For HTTP traffic, customers will have to do one of the following:

How is the media path being selected between the available TURN targets. Does it take into account the round-trip latency, or is it influenced by the order in which we list the targets, or is it random?

Order of TURN servers is not guaranteed based on the list provided. Instead, when the media starts flowing, the ICE implementation selects which candidate/server has the best connectivity and successfully negotiated first.

If the TURN server URL maps to multiple IP addresses, how is the specific TURN server selected for the session? Is this random?

Most implementations, including the ones used in Chrome and Firefox, take the first IP returned by the DNS lookup. This results in a random round-robin selection typically.

If both TCP and UDP TURN servers are provided and are reachable, is it possible to prioritize UDP targets and only fall back to TCP if required?

UDP relay candidates will be preferred over TCP relay candidates since those candidates have a lower local type preference and therefore a lower priority. Refer to RFC 8445 for details. The order of ICE servers passed in does not influence this.

Can a single client use different media paths for different streams?

Yes, this is expected behavior as OpenTok treats each individual media stream separately.

How much control does the Configurable TURN API have in the media path selection?

Media path selection is handled by ICE (Interactive Connectivity Establishment) inside WebRTC, and we have no way to modify this behavior. The Configurable TURN API only helps modify the list of ICE servers provided by the client to WebRTC and does not influence the selection process.

Is direct connection to OpenTok Media Server over UDP always preferred?

Yes, direct connection to OpenTok Media Server is always preferred. It fails over to using TURN if connection to the OpenTok Media Server is unsuccessful or if the "Force TURN" option is used in the Configurable TURN API.

Can I use multiple TURN servers of the same type for load balancing?

This is not recommended as it will result in a random server being picked by the client and that server can change over the duration of the connection.

How do I load-balance my custom TURN server deployment?

Please contact us for more information.

Can the TURN server decrypt media?

No, the TURN server does not have access to the SRTP keys that are exchanged using DTLS-SRTP and only available to the endpoints of the connection.

What happens if a TURN server crashes during a session and how to recover

If a TURN server crashes while it is being used this will result in the client's connection becoming disconnected. The client will try to re-establish a connection using an ICE Restart.

How can I test a TURN server?

You can test your TURN server either using the Video API Playground, the Trickle Ice test page or the coturn turnutils_uclient.