12 min read

In the article written by Giovanni Maruzzelli, author of FreeSWITCH 1.6 Cookbook, we learn how WebRTC is all about security and encryption. Theye are not an afterthought. They’re intimately interwoven at the design level and are mandatory. For example, you cannot stream audio or video clearly (without encryption) via WebRTC.

(For more resources related to this topic, see here.)

Getting ready

To start with this recipe, you need certificates. These are the same kind of certificates used by web servers for SSL-HTTPS.

Yes, you can be your own Certification Authority and self-sign your own certificate. However, this will add considerable hassles; browsers will not recognize the certificate, and you will have to manually instruct them to make a security exception and accept it, or import your own Certification Authority chain to the browser. Also, in some mobile browsers, it is not possible to import self-signed Certification Authorities at all.

The bottom line is that you can buy an SSL certificate for less than $10, and in 5 minutes. (No signatures, papers, faxes, telephone calls… nothing is required. Only a confirmation email and a few bucks are enough.) It will save you much frustration, and you’ll be able to cleanly showcase your installation to others.

The same reasoning applies to DNS Full Qualified Domain Names (FQDN)—certificates belonging to FQDN’s. You can put your DNS names in /etc/hosts, or set up an internal DNS server, but this will not work for mobile clients and desktops outside your control. You can register a domain, point an fqdn to your machine’s public IP (it can be a Linode, an AWS VM, or whatever), and buy a certificate using that fqdn as Common Name (CN).

Don’t try to set up the WebRTC server on your internal LAN behind the same NAT that your clients are into (again, it is possible but painful).

How to do it…

Once you have obtained your certificate (be sure to download the Certification Authority Chain too, and keep your Private Key; you’ll need it), you must concatenate those three elements to create the needed certificates for mod_sofia to serve SIP signaling via WSS and media via SRTP/DTLS.

FreeSWITCH 1.6 Cookbook

With certificates in the right place, you can now activate ssl in Sofia. Open /usr/local/freeswitch/conf/vars.xml:

FreeSWITCH 1.6 Cookbook

As you can see, in the default configuration, both lines that feature SSL are false. Edit them both to change them to true.

How it works…

By default, Sofia will listen on port 7443 for WSS clients. You may want to change this port if you need your clients to traverse very restrictive firewalls. Edit /usr/local/freeswitch/conf/sip-profiles/internal.xml and change the “wss-binding” value to 443. This number, 443, is the HTTPS (SSL) port, and is almost universally open in all firewalls. Also, wss traffic is indistinguishable from https/ssl traffic, so your signaling will pass through the most advanced Deep Packet Inspection. Remember that if you use port 443 for WSS, you cannot use that same port for HTTPS, so you will need to deploy your secure web server on another machine.

There’s more…

A few examples of such a configuration are certificates, DNS, and STUN/TURN.

Generally speaking, if you set up with real DNS names, you will not need to run your own STUN server; your clients can rely on Google STUN servers. But if you need a TURN server because some of your clients need a media relay (which is because they’re behind and demented NAT got UDP blocked by zealous firewalls), install on another machine rfc5766-turn-server, and have it listen on TCP ports 443 and 80. You can also put certificates with it and use TURNS on encrypted connection. The same firewall piercing properties as per signaling.

SIP signaling in JavaScript with SIP.js (WebRTC client)

Let’s carry out the most basic interaction with a web browser audio/video through WebRTC. We’ll start using SIP.js, which uses a protocol very familiar to all those who are old hands at VoIP.

A web page will display a click-to-call button, and anyone can click for inquiries. That call will be answered by our company’s PBX and routed to our employee extension (1010). Our employee will wait on a browser with the “answer” web page open, and will automatically be connected to the incoming call (if our employee does not answer, the call will go to their voicemail).

Getting ready

To use this example, download version 0.7.0 of the SIP.js JavaScript library from www.sipjs.com.

We need an “anonymous” user that we can allow into our system without risks, that is, a user that can do only what we have preplanned. Create an anonymous user for click-to-call in a file named /usr/local/freeswitch/conf/directory/default/anonymous.xml :

<include>
<user id="anonymous">
   <params>
     <param name="password" value="welcome"/>
   </params>
   <variables>
     <variable name="user_context" value="anonymous"/>
     <variable name="effective_caller_id_name" value="Anonymous"/>
     <variable name="effective_caller_id_number" value="666"/>
     <variable name="outbound_caller_id_name" value="$${outbound_caller_name}"/>
     <variable name="outbound_caller_id_number" value="$${outbound_caller_id}"/>
   </variables>
</user>
</include>

Then add the user’s own dialplan to /usr/local/freeswitch/conf/dialplan/anonymous.xml:

<include>
<context name="anonymous">
   <extension name="public_extensions">
     <condition field="destination_number" expression="^(10[01][0-9])$">
       <action application="transfer" data="$1 XML default"/>
     </condition>
   </extension>
   <extension name="conferences">
     <condition field="destination_number" expression="^(36d{2})$">
       <action application="answer"/>
       <action application="conference" data="$1-${domain_name}@video-mcu"/>
     </condition>
   </extension>
   <extension name="echo">
     <condition field="destination_number" expression="^9196$">
       <action application="answer"/>
       <action application="echo"/>
     </condition>
   </extension>
</context>
</include>

How to do it…

In a directory served by your HTPS server (for example, Apache with an SSL certificate), put all the following files.

Minimal click-to-call caller client

HTML (call.html):
<html>
<body>
       <button id="startCall">Start Call</button>
       <button id="endCall">End Call</button>
       <br/>
       <video id="remoteVideo"></video>
       <br/>
       <video id="localVideo" muted="muted" width="128px" height="96px"></video>
       <script src="js/sip-0.7.0.min.js"></script>
       <script src="call.js"></script>
</body>
</html>

JAVASCRIPT (call.js):

var session;
 
var endButton = document.getElementById('endCall');
endButton.addEventListener("click", function () {
       session.bye();
       alert("Call Ended");
}, false);
 
var startButton = document.getElementById('startCall');
startButton.addEventListener("click", function () {
       session = userAgent.invite('sip:[email protected]', options);
       alert("Call Started");
}, false);
 
var userAgent = new SIP.UA({
       uri: '[email protected]',
       wsServers: ['wss://self2.gmaruzz.org:7443'],
       authorizationUser: 'anonymous',
       password: 'welcome'
});
 
var options = {
       media: {
               constraints: {
                       audio: true,
                       video: true
               },
               render: {
                       remote: document.getElementById('remoteVideo'),
                       local: document.getElementById('localVideo')
               }
       }
};

Minimal callee

HTML (answer.html):

<html>
<body>
       <button id="endCall">End Call</button>
       <br/>
       <video id="remoteVideo"></video>
       <br/>
       <video id="localVideo" muted="muted" 
width="128px" height="96px"></video>        <script src="js/sip-0.7.0.min.js"></script>        <script src="answer.js"></script> </body> </html> JAVASCRIPT (answer.js): var session;   var endButton = document.getElementById('endCall'); endButton.addEventListener("click", function () {        session.bye();        alert("Call Ended"); }, false);   var userAgent = new SIP.UA({        uri: '[email protected]',        wsServers: ['wss://self2.gmaruzz.org:7443'],        authorizationUser: '1010',        password: 'ciaociao' });   userAgent.on('invite', function (ciapalo) {        session = ciapalo;        session.accept({                media: {                        constraints: {                               audio: true,                                video: true                        },                        render: {                                remote:
document.getElementById('remoteVideo'),                                local:
document.getElementById('localVideo')                        }                  }        }); });

How it works…

Our employee (the callee, or the person who will answer the call) will sit tight with the answer.html web page open on their browser. Upon page load, JavaScript will have created the SIP agent and registered it with our FreeSWITCH server as SIP user “1010” (just as our employee was on their own regular SIP phone).

FreeSWITCH 1.6 Cookbook

Our customer (the caller, or the person who initiates the communication) will visit the call.html webpage (while loading, this web page will register as an SIP “anonymous” user with FreeSWITCH), and then click on the Start Call button. This clicking will activate the JavaScript that creates the communication session using the invite method of the user agent, passing as an argument the SIP address of our employee.

FreeSWITCH 1.6 Cookbook

The Invite method initiates a call, and our FreeSWITCH server duly invites SIP user 1010. That happens to be the answer.html web page our employee is in front of.

The Invite method sent from FreeSWITCH to answer.html will activate the JavaScript local user agent, which will create the session and accept the call.

At this moment, the caller and callee are connected, and voice and video will begin to flow back and forth. The received audio or video stream will be rendered by the RemoteVideo tag in the web page, while its own stream (the video that is sent to the peer) will show up locally in the little localVideo tag. That’s muted not to generate Larsen whistles.

See also

The Configuring a SIP phone to register with FreeSWITCH recipe in Chapter 2, Connecting Telephones and Service Providers, and the documentation at http://sipjs.com/guides/.confluence/display/FREESWITCH/mod_verto

Summary

This article features the new disruptive technology that allows real-time audio/video/data-secure communication from hundreds of millions of browsers. FreeSWITCH is ready to serve as a gateway and an application server.

Resources for Article:


Further resources on this subject:


LEAVE A REPLY

Please enter your comment!
Please enter your name here