Calls Blocken via MSPL Scripting

Hallo an alle, heute ergab sich die Anforderung bei einem Kunden Anrufe von einer bestimmten Nummer zu blockieren. Diese liess sich auf Gateway Seite nicht so einfach realisieren. MSPL Scripting war die Lösung dann doch greifbar. Mit diesen Skripten kann man den Lync/SfB Server um Routing/Funktionen erweitern. Schlussendlich kann man hiermit SIP Nachrichten Filtern/Manipulieren/Routen und einiges mehr. Die Syntax hierzu findet Ihr hier: https://msdn.microsoft.com/en-us/library/gg439378.aspx

Hier nun also zu unserer Anforderung: Audio Calls einer bestimmten Absendernummer blocken. Ein MSPL Script ist folgendermassen aufgebaut: Es gibt eine Manifest Datei mit der Endung .am in der Struktur einer ordinären XML Datei. der Header sieht ungefähr so aus:

<?xmlversion="1.0"?>
<lc:applicationManifest
Hier muss man lediglich das appUri (Namespace Attribut für sich anpassen (aus die Case Sensitivität achten ;-)), diese wird nach im Application Deployment auf der Lync Plattform noch benötigt.
Nun kann man noch die Anfragen und Antworten Filtern:
<lc:requestFiltermethodNames="ALL"strictRoute="false"
    registrarGenerated="true"domainSupported="true"/ >
<lc:responseFilterreasonCodes="ALL"/>
Hier hat man die Möglichkeit nach ALL, NONE oder Komma getrennt Methoden bzw. Reason Codes anzugeben.
Ein sehr wichtiges Attribut ist das folgende:
<lc:proxyByDefaultaction="false"/>
hier wird bestimmt ob Nachrichten die nicht durch unsere Logik laufen von Lync/SfB geproxied werden (true, wie sonst auch) oder nicht (false, also gedroppt werden).
Damit wir die zu blockenden Absendernummern nicht fest im Code hinterlegen müssen (dies hätte zur Folge, dass bei Änderung einer Nummer oder des Scripts die Application deregistriert und neu registriert werden muss oder die RTCSRV Dienst neu gestartet werden muss) hinterlegen wir diese Nummern in einer simplen Textdatei (bei einem Enterprise Pool empfiehlt sich das Lync Share bei einem STD Pool kann das ein lokaler Pfad sein).
In unserem Script wird dies mit folgenden Elementen gemacht:
<lc:file Name="BlockedTelephoneNumbers"
path = "\\<Lync Share>\BlockCaller\BlockedTelephoneNumbers.txt"
delimitedBy="comma"
keyColumnName="Phone"
static="false">
<lc:column name="Phone" />
<lc:column name="Action" />
</lc:file>
Hiermit Tteilen wir dem Script den Namen, den Pfad und die Spalten der CSV Datei mit. diese sieht bei mir so aus:
Phone,Action
+XXXXXXXXXXXX,block
bei den Nummern daran denken, dass es exakt die Nummer sein muss, welche vom Gateway an den Lync/SfB geliefert wird (bei uns E.164 inkl führendem „+“).
Nun teilen wir unserem Script noch mit, ab unsere Logik nur in dieser Skript Datei steckt, oder ob wir managed Code zusätzlich benutzen:
<lc:scriptOnly/>
Unsere Logik steckt in unserem Script, daher ScriptOnly (ohne managed Code in anderen Dateien).
Zusammen sieht unser Script nun so aus:
<?xmlversion="1.0"?>
<lc:applicationManifest
<lc:requestFiltermethodNames="ALL"strictRoute="false"
    registrarGenerated="true"domainSupported="true"/ >
<lc:responseFilterreasonCodes="ALL"/>
<lc:proxyByDefaultaction="false"/>
<lc:file Name="BlockedTelephoneNumbers"
path = "\\<Lync Share>\BlockCaller\BlockedTelephoneNumbers.txt"
delimitedBy="comma"
keyColumnName="Phone"
static="false">
<lc:column name="Phone" />
<lc:column name="Action" />
</lc:file>
<lc:scriptOnly/>
Zum Abschluss unserer Datei muss nun noch etwas Logik abgebildet werden. Dies tun wir in den folgenden Elementen:
<lc:splScript>
    <![CDATA[ /* Hier kommt unsere Logik */ ]]>
</lc:splScript>
Diese Logik sieht bei uns so aus:
if(sipRequest.Method == „INVITE“){
fromUser = GetUserName(GetUri(sipRequest.From));
toUser = GetUserName(GetUri(sipRequest.To));
sep = IndexOfString(fromUser, „;“);
      Log („Debugr“, false, „CallerIDBlock processing request:“);
Log („Debugr“, false, „From – „, fromUser);
Log („Debugr“, false, „To – „, toUser);
if(sep != -1) {
fromUser = SubString(fromUser, 0, sep);
}
      action = BlockedTelephoneNumbers[fromUser].Action;
if(action == „block“) {
Log („Debugr“, false, „Rejected by CallerIDBlock“);
Respond(403, „Forbidden“);
} else {
Log („Debugr“, false, „Allowed by CallerIDBlock“);
}
}
return;

Nun haben wir also unsere Script Datei: BlockCaller

Der Letzte Schritt ist das Script in unserer Lync/SfB Umbgebung einzubinden. Hier sind zwei Dinge zu beachten:
1) Die Script Datei muss von jedem Frontendserver im Pool erreichbar sein (als empfiehlt sich bei einem Ent. Pool das Lync Share für Script und Resourcen Datei (unsere CSV)
2) unsere Namspace URI im Header
Mittels Lync Management Shell wird nun ein ApplicationServer erzeugt und Ihm die Logik unseres Scriptes mitgegeben:
New-CsServerApplication -Name „BlockCaller“ -Uri „http://blog.rouven-hausner.de/BlockCaller“ -Enabled $true -ScriptName ‚C:\MSPL Scripting\BlockCaller.am‘ -Critical $false -Priority 5 -Parent „service:<Euer FrontPool FQDN>“
Nun werden alle Calls mit den Absendernummern in der CSV Datei mit 403 abgewiese (geblockt)!
Viel Spass und Erfolg!

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert