I am trying to figure out how to test whether a STUN/TURN server is alive and properly responding to connections. Ideally this test would be performed from an external machine, just in case the STUN/TURN machine is down for this case should also be reported by the connectivity test.
Has anyone looked into this case in the past? What solutions would be recommended?
You can easily determine if your server works with both tools or with your own JavaScript: A STUN server works if you can gather a candidate with type "srflx" . A TURN server works if you can gather a candidate with type "relay" .
The STUN, TURN, and TURNS ProtocolsSession Traversal Utilities for NAT (STUN) - Used to establish a direct UDP connection between two clients. Traversal Using Relay around NAT (TURN) - Used to establish a relayed UDP or TCP connection between two clients.
ICE is used in WebRTC and in SIP for finding the possible media routes for a session. In essence, the process involves gathering candidates and checking connectivity to see if a connection between the parties is possible using each of the candidates.
Free and public Session Traversal Utilities for NAT serverThere are various free STUN servers available out there. It is lightweight and carry no real authentication mechanism to it. This makes it simple for developers to connect to freeservers without any technical hurdles. It is not advisable to do so.
Edit: A nice implementation in github.io taken from comment to another answer( choose "relay" in IceTransports value):
Test TURN Server
following Benjamin Trent's advice, I wrote the below code to test TURN server's connectivity, works on both firefox n chrome:
function checkTURNServer(turnConfig, timeout){ return new Promise(function(resolve, reject){ setTimeout(function(){ if(promiseResolved) return; resolve(false); promiseResolved = true; }, timeout || 5000); var promiseResolved = false , myPeerConnection = window.RTCPeerConnection || window.mozRTCPeerConnection || window.webkitRTCPeerConnection //compatibility for firefox and chrome , pc = new myPeerConnection({iceServers:[turnConfig]}) , noop = function(){}; pc.createDataChannel(""); //create a bogus data channel pc.createOffer(function(sdp){ if(sdp.sdp.indexOf('typ relay') > -1){ // sometimes sdp contains the ice candidates... promiseResolved = true; resolve(true); } pc.setLocalDescription(sdp, noop, noop); }, noop); // create offer and set local description pc.onicecandidate = function(ice){ //listen for candidate events if(promiseResolved || !ice || !ice.candidate || !ice.candidate.candidate || !(ice.candidate.candidate.indexOf('typ relay')>-1)) return; promiseResolved = true; resolve(true); }; }); }
example usage:
checkTURNServer({ urls: 'turn:127.0.0.1', username: 'test', credential: 'test' }).then(function(bool){ console.log('is TURN server active? ', bool? 'yes':'no'); }).catch(console.error.bind(console));
You can run the below snippet to check:
var res = id('result'); id('button').onclick = function(){ res.innerHTML = 'Checking TURN Server...'; var url = 'turn:'+id('url').value+':'+id('port').value, useUDP = id('udp').checked; url +='?transport=' + (useUDP ? 'udp': 'tcp'); checkTURNServer({ urls: url, username: id('name').value, credential: id('pass').value }, id('time').value).then(function(bool){ if(bool) res.innerHTML = 'Yep, the TURN server works...'; else throw new Error('Doesn\'t work'); }).catch(function(e){ console.log(e); res.innerHTML = 'TURN server does not work.'; }); }; function checkTURNServer(turnConfig, timeout){ console.log('turnConfig: ', turnConfig); return new Promise(function(resolve, reject){ setTimeout(function(){ if(promiseResolved) return; resolve(false); promiseResolved = true; }, timeout || 5000); var promiseResolved = false , myPeerConnection = window.RTCPeerConnection || window.mozRTCPeerConnection || window.webkitRTCPeerConnection //compatibility for firefox and chrome , pc = new myPeerConnection({iceServers:[turnConfig]}) , noop = function(){}; pc.createDataChannel(""); //create a bogus data channel pc.createOffer(function(sdp){ if(sdp.sdp.indexOf('typ relay') > -1){ // sometimes sdp contains the ice candidates... promiseResolved = true; resolve(true); } pc.setLocalDescription(sdp, noop, noop); }, noop); // create offer and set local description pc.onicecandidate = function(ice){ //listen for candidate events if(promiseResolved || !ice || !ice.candidate || !ice.candidate.candidate || !(ice.candidate.candidate.indexOf('typ relay')>-1)) return; promiseResolved = true; resolve(true); }; }); } function id(val){ return document.getElementById(val); }
#url{ width: 250px; } #port{ width: 70px; }
<h1> Test TURN server </h1> <div> TURN URL: <input id='url' placeholder='example.com or xxx.yyy.rrr.ddd' /> Port: <input type='number' value='3478' id='port' placeholder='enter a port number' /> </div> <div> Transport: <input type="radio" name="transport" id="tcp" value="tcp" /> TCP <input type="radio" name="transport" id="udp" value="udp" checked/>UDP </div> <div> Username: <input id="name" placeholder="turn username" /> </div> <div> password: <input id="pass" placeholder="turn password" /> </div> <div> checking Timeout: <input type='number' id="time" placeholder="wait time before checking timeout" value=5000 /> </div> <div> <button id='button'> Check TURN Server </button> </div> <h4 id='result'></h4>
You can test your servers here...
https://webrtc.github.io/samples/src/content/peerconnection/trickle-ice/
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With