Compare commits

..
Author SHA1 Message Date
Quan HL 563ea405e9 wip 2023-10-24 12:56:07 +07:00
Quan HL 8cd91c19c9 support call to queue and application from registered user 2023-10-24 12:31:02 +07:00
Quan HL 994904e8e7 support call to queue and application from registered user 2023-10-24 12:27:12 +07:00
Quan HL 874d1804e1 support call to queue and application from registered user 2023-10-24 12:15:06 +07:00
Quan HL 9475b776be support device call to app 2023-10-23 14:14:26 +07:00
Hoan Luu Huu a3799576a2 add sentinelPassword option (#119) 2023-10-04 19:41:21 -04:00
Antony Jukesandajukes 63e72fbfce feat/MS Teams IP check improvement (#117)
* added ip in cidr utilities

* middleware add ms teams cidr check

* use cidr-matcher lib

* removed redundant require

* moved cidr-matcher require to top of file

* moved express require to top of file

---------

Co-authored-by: ajukes <ajukes@callable.io>
2023-09-18 10:35:04 -04:00
6 changed files with 82 additions and 10 deletions
+11 -3
View File
@@ -33,7 +33,10 @@ const JAMBONES_REDIS_SENTINELS = process.env.JAMBONES_REDIS_SENTINELS ? {
}),
...(process.env.JAMBONES_REDIS_SENTINEL_USERNAME && {
username: process.env.JAMBONES_REDIS_SENTINEL_USERNAME
})
}),
...(process.env.JAMBONES_REDIS_SENTINEL_SENTINAL_PASSWORD && {
sentinelPassword: process.env.JAMBONES_REDIS_SENTINEL_SENTINAL_PASSWORD
}),
} : null;
const Srf = require('drachtio-srf');
@@ -64,6 +67,7 @@ const {LifeCycleEvents} = require('./lib/constants');
const setNameRtp = `${(process.env.JAMBONES_CLUSTER_ID || 'default')}:active-rtp`;
const rtpServers = [];
const setName = `${(process.env.JAMBONES_CLUSTER_ID || 'default')}:active-sip`;
const Registrar = require('@jambonz/mw-registrar');
const {
pool,
@@ -77,7 +81,8 @@ const {
lookupAccountBySid,
lookupAccountCapacitiesBySid,
queryCallLimits,
lookupClientByAccountAndUsername
lookupClientByAccountAndUsername,
lookupAppBySid
} = require('@jambonz/db-helpers')({
host: process.env.JAMBONES_MYSQL_HOST,
port: process.env.JAMBONES_MYSQL_PORT || 3306,
@@ -97,6 +102,7 @@ const {
host: process.env.JAMBONES_REDIS_HOST,
port: process.env.JAMBONES_REDIS_PORT || 6379
}, logger);
const registrar = new Registrar(logger, redisClient);
const ngProtocol = process.env.JAMBONES_NG_PROTOCOL || 'udp';
const ngPort = process.env.RTPENGINE_PORT || ('udp' === ngProtocol ? 22222 : 8080);
@@ -117,6 +123,7 @@ srf.locals = {...srf.locals,
activeCallIds: new Map(),
getRtpEngine,
dbHelpers: {
registrar,
pool,
ping,
lookupAuthHook,
@@ -127,7 +134,8 @@ srf.locals = {...srf.locals,
lookupAccountBySipRealm,
lookupAccountCapacitiesBySid,
queryCallLimits,
lookupClientByAccountAndUsername
lookupClientByAccountAndUsername,
lookupAppBySid
},
realtimeDbHelpers: {
createSet,
+7 -1
View File
@@ -224,6 +224,12 @@ class CallSession extends Emitter {
if (this.req.locals.application_sid) {
Object.assign(headers, {'X-Application-Sid': this.req.locals.application_sid});
}
if (this.req.locals.queue_name) {
Object.assign(headers, {'X-Queue-Name': this.req.locals.queue_name});
}
if (this.req.locals.called_user) {
Object.assign(headers, {'X-Called-User': this.req.locals.called_user});
}
if (this.req.authorization) {
if (this.req.authorization.grant && this.req.authorization.grant.application_sid) {
Object.assign(headers, {'X-Application-Sid': this.req.authorization.grant.application_sid});
@@ -248,7 +254,7 @@ class CallSession extends Emitter {
'-Max-Forwards',
'-Record-Route',
'-Session-Expires',
'-X-Subspace-Forwarded-For'
'-X-Subspace-Forwarded-For',
],
proxyResponseHeaders: ['all', '-X-Trace-ID'],
localSdpB: spdOfferB,
+27 -4
View File
@@ -1,7 +1,7 @@
const debug = require('debug')('jambonz:sbc-inbound');
const assert = require('assert');
const parseUri = require('drachtio-srf').parseUri;
const {nudgeCallCounts, roundTripTime} = require('./utils');
const {nudgeCallCounts, roundTripTime, isMSTeamsCIDR} = require('./utils');
const digestChallenge = require('@jambonz/digest-utils');
const msProxyIps = process.env.MS_TEAMS_SIP_PROXY_IPS ?
process.env.MS_TEAMS_SIP_PROXY_IPS.split(',').map((i) => i.trim()) :
@@ -28,7 +28,9 @@ module.exports = function(srf, logger) {
lookupAccountBySipRealm,
lookupAccountBySid,
lookupAccountCapacitiesBySid,
queryCallLimits
queryCallLimits,
lookupAppBySid,
registrar
} = srf.locals.dbHelpers;
const {stats, writeCdrs} = srf.locals;
@@ -155,7 +157,7 @@ module.exports = function(srf, logger) {
...req.locals
};
}
else if (msProxyIps.includes(req.source_address)) {
else if (msProxyIps.includes(req.source_address) || isMSTeamsCIDR(req.source_address)) {
logger.info({source_address: req.source_address}, 'identifyAccount: incoming call from Microsoft Teams');
const uri = parseUri(req.uri);
@@ -196,11 +198,32 @@ module.exports = function(srf, logger) {
res.send(404);
return req.srf.endSession(req);
}
let deviceAppSid = null;
let called_user = null;
const queue_name = uri.user.startsWith('queue-') ? uri.user.match(/queue-(.*)/)[1] : null;
if (uri.user.startsWith('app-')) {
// Call from registered device to test application.
const appSid = uri.user.match(/app-(.*)/)[1];
const app = await lookupAppBySid(appSid);
if (app && app.account_sid === account.account_sid) {
deviceAppSid = app.application_sid;
}
} else if (!queue_name) {
// check if call to registered user
const {realm} = this.req.authorization.challengeResponse;
const calledAor = `${req.calledNumber}@${realm}`;
const reg = await registrar.query(calledAor);
if (reg) {
called_user = calledAor;
}
}
req.locals = {
service_provider_sid: account.service_provider_sid,
account_sid: account.account_sid,
account,
application_sid: account.device_calling_application_sid,
application_sid: deviceAppSid || account.device_calling_application_sid,
...(queue_name && ({queue_name})),
...(called_user && ({called_user})),
webhook_secret: account.webhook_secret,
realm: uri.host,
...(account.registration_hook && {
+19 -2
View File
@@ -1,5 +1,8 @@
const CIDRMatcher = require('cidr-matcher');
const express = require('express');
const rtpCharacteristics = require('../data/rtp-transcoding');
const srtpCharacteristics = require('../data/srtp-transcoding');
let idx = 0;
const isWSS = (req) => {
@@ -96,7 +99,6 @@ const handleErrors = (logger, app, resolve, reject, e) => {
const createHealthCheckApp = (port, logger) => {
const express = require('express');
const app = express();
app.use(express.urlencoded({ extended: true }));
@@ -178,6 +180,20 @@ const parseConnectionIp = (sdp) => {
return arr ? arr[1] : null;
};
/**
* Checks if ip is one of MS Teams sip signalling ips
* https://learn.microsoft.com/en-us/azure/communication-services/concepts
* /telephony/direct-routing-infrastructure#sip-signaling-fqdns
* @param ip IP address, example 172.31.0.1
* */
const isMSTeamsCIDR = (ip) => {
const cidrs = [
'52.112.0.0/14',
'52.120.0.0/14'
];
const matcher = new CIDRMatcher(cidrs);
return matcher.contains(ip);
};
module.exports = {
isWSS,
@@ -194,5 +210,6 @@ module.exports = {
createHealthCheckApp,
nudgeCallCounts,
roundTripTime,
parseConnectionIp
parseConnectionIp,
isMSTeamsCIDR
};
+17
View File
@@ -14,6 +14,7 @@
"@jambonz/db-helpers": "^0.9.1",
"@jambonz/digest-utils": "^0.0.3",
"@jambonz/http-health-check": "^0.0.1",
"@jambonz/mw-registrar": "^0.2.4",
"@jambonz/realtimedb-helpers": "^0.8.6",
"@jambonz/rtpengine-utils": "^0.4.3",
"@jambonz/siprec-client-utils": "^0.2.6",
@@ -1696,6 +1697,14 @@
"node": ">=14.x"
}
},
"node_modules/@jambonz/mw-registrar": {
"version": "0.2.5",
"resolved": "https://registry.npmjs.org/@jambonz/mw-registrar/-/mw-registrar-0.2.5.tgz",
"integrity": "sha512-+aBI2xpR6Ir140Hi7/ED+z5Hl7NgCalyVzTLNlgUVzTvsMLtyZZh6n9IQipKnuKvhh4nPM4aJ+JuFhi1UH9zEA==",
"dependencies": {
"debug": "^4.3.4"
}
},
"node_modules/@jambonz/realtimedb-helpers": {
"version": "0.8.6",
"resolved": "https://registry.npmjs.org/@jambonz/realtimedb-helpers/-/realtimedb-helpers-0.8.6.tgz",
@@ -7664,6 +7673,14 @@
"express": "^4.17.2"
}
},
"@jambonz/mw-registrar": {
"version": "0.2.5",
"resolved": "https://registry.npmjs.org/@jambonz/mw-registrar/-/mw-registrar-0.2.5.tgz",
"integrity": "sha512-+aBI2xpR6Ir140Hi7/ED+z5Hl7NgCalyVzTLNlgUVzTvsMLtyZZh6n9IQipKnuKvhh4nPM4aJ+JuFhi1UH9zEA==",
"requires": {
"debug": "^4.3.4"
}
},
"@jambonz/realtimedb-helpers": {
"version": "0.8.6",
"resolved": "https://registry.npmjs.org/@jambonz/realtimedb-helpers/-/realtimedb-helpers-0.8.6.tgz",
+1
View File
@@ -33,6 +33,7 @@
"@jambonz/stats-collector": "^0.1.9",
"@jambonz/time-series": "^0.2.5",
"@jambonz/digest-utils": "^0.0.3",
"@jambonz/mw-registrar": "^0.2.4",
"@aws-sdk/client-sns": "^3.360.0",
"@aws-sdk/client-auto-scaling": "^3.360.0",
"bent": "^7.3.12",