3

I'm trying to create a minimal SIP Proxy that serves one purpose: redirects requests to another domain. The catch is the domain I'm redirecting to requires authorization so I assume I need to rewrite some SIP attributes since SIP authorization is based partly on the domain name of the destination.

I've tried issuing a 302 redirect as well as simply proxying and changing the values of each SIP request but none seem to quit do the trick. I'm using a node.js library (sip.js) and have tried the redirect and proxy modules (https://github.com/kirm/sip.js/blob/master/doc/api.markdown).

Any ideas exactly how I need to modify the SIP data to redirect requests to another domain and enable authentication to take place against that other domain?

Dan
  • 3,389
  • 5
  • 34
  • 44
  • Do you have the credentials available on your SIP Proxy? Or are you expecting the client to use its own stored credentials when it receives the redirect response from your Proxy? If the latter I doubt you'll have much success as it would be problematic from a security point of view; your Proxy could redirect to a premium number and incur a hefty charge against the client. – sipsorcery Feb 11 '14 at 00:55
  • @sipwiz I do have the credentials available to me so I could authenticate on the users behalf. Just not sure how. – Dan Feb 11 '14 at 02:50

1 Answers1

9

Below is a basic node script I got working with my own SIP server. You'll need to replace the credentials and IP address fro your own testing.

The proxy script does not send a redirect response to the client but instead initiates a new transaction to the server on the client's behalf. A SIP server operating in this mode is more correctly called a Back-to-Back User Agent (B2BUA). I haven't added all the functionality needed, such as matching up and passing responses back to the original client; there is a fair bit of work involved in that.

var sip = require('sip');
var digest = require('sip/digest');
var util = require('util');
var os = require('os');
var proxy = require('sip/proxy');

var registry = {
  'user': { user: "user", password: "password", realm: "sipserver.com"},
};

function rstring() { return Math.floor(Math.random()*1e6).toString(); }

sip.start({
  address: "192.168.33.116", // If the IP is not specified here the proxy uses a hostname in the Via header which will causes an issue if it's not fully qualified.
  logger: { 
    send: function(message, address) { debugger; util.debug("send\n" + util.inspect(message, false, null)); },
    recv: function(message, address) { debugger; util.debug("recv\n" + util.inspect(message, false, null)); }
  }
},
function(rq) {
  try {
    if(rq.method === 'INVITE') {  

       proxy.send(sip.makeResponse(rq, 100, 'Trying'));

      //looking up user info
      var username = sip.parseUri(rq.headers.to.uri).user;    
      var creds = registry[username];

      if(!creds) {  
        proxy.send(sip.makeResponse(rq, 404, 'User not found'));
      }
      else {
        proxy.send(rq, function(rs) {

            if(rs.status === 401) {

                // Update the original request so that it's not treated as a duplicate.
                rq.headers['cseq'].seq++;
                rq.headers.via.shift ();
                rq.headers['call-id'] = rstring();

                digest.signRequest(creds, rq, rs, creds);

                proxy.send(rq);
            }
        });
      }
    }
    else {
      proxy.send(sip.makeResponse(rq, 405, 'Method Not Allowed'));
    }
  } catch(e) {
    util.debug(e);
    util.debug(e.stack);

   proxy.send(sip.makeResponse(rq, 500, "Server Internal Error"));
  }
});
sipsorcery
  • 30,273
  • 24
  • 104
  • 155