Audiocodes LDAP-Routing

Voraussetzung für diese Funktion ist die Firmware 6.0 oder höher

Achtung
Die aktuelle Beschreibung scheint mit der aktuellsten Firmware so nicht mehr zu funktionieren. Ich arbeite an einer Korrektur.

Die meisten Installationen nutzen die AudioCodes-Gateways vermutlich mit "statischen" Routingeinträgen. Wer aber gerade in einer Migration steckt oder manuelle Einstellungen vermeiden möchte, kann auch das Active Directory nutzen, damit der Audiocodes abhängig von Feldinhalten die Rufe an das "richtige" System weiter gibt. Mit der Firmware 5.x musste dazu noch ein "ADRoute"-Hilfsprogramme installiert werden, welches im Kern eine angepasste Version von "FreeSwitch" war. Der Audiocodes hat den Ruf per SIP dann einfach an dieses Programm gesendet, welches im AD nachgeschaut und ein SIP-Redirect gemacht hat.

Interessant wird die Funktion per LDAP, wie Sie in der Version 6.0 seit Februar 2010 implementiert ist. Seit dieser Version kann der Audiocodes direkt per LDAP z.B. ein Active Directory fragen. Die Funktino wurde erstmals in den Release Notes zur Version 6.0 beschrieben, die aber nicht mehr bei Audiocodes zum Download bereit stehen. Die Beschreibung in dem Readme war aus meiner Sicht aber irreführend und für OCS nicht optimal. Durchsuchen Sie die passende Beschreibung zu ihrer Version nach LDAP.

Aktivieren von LDAP

Zuerst müssen die generell die LDAP-Funktion auf dem Mediant aktivieren.

In früheren Versionen konnten Sie hier gleich den LDAP-Server mit angeben. Hier noch mal ein älteres Bild.

Der "LDAP Bind DN" kann bei Windows Domain Controllern auch in der Form "domain\username" und vermutlich auch als "UPN" eingegeben werden. Bei anderen LDAP-Servern ist dies aber zu prüfen.

Achtung
Wenn Sie auf TLS verzichten, dann kann das Kennwort für dieses Dienstkonto mit einem Netzwerkmonitor, ARP-Spoofing mit wenig Aufwand mitgeschnitten werden. Achten Sie auf eine "sichere" Verbindung zwischen Gateway und LDAP-Server.

Definition der LDAP-Server

Im zweiten Schritt können Sie bei neueren Versionen die LDAP-Server hinterlegen:

Her werden die IP-Adresse des Server, Anmeldedaten etc. angelegt- Legen Sie bitte ein Dienstkonto für den Audiocodes an, welches sein Kennwort nie ändern muss und nicht abläuft und vor allem kein Administrator ist.

Bislang konnte der Mediant immer nur "LDAP SIMPLE BIND", bei dem das Kennwort in Klartext übertragen wird. Der Mediant kann aber auch SSL, wenn ihr LDAP-Server ein Zertifikat hat.

Achtung:
Ein Active Directory kann mehrere Domains und Partitionen haben. Wenn Sie die Objekte nicht in einem ADAM/AD LDS abgelegt haben, sollte der Mediant den globalen Katalog durchsuchen

LDAP-Felder

Der LDAP-Client nutzt die Rufnummer und sucht danach in verschiedenen LDAP-Feldern. Diese Felder sind wie folgt schon "sinnvoll" vorbelegt, so dass Sie hier in der Regel nichts ändern sollten.

Bitte beachten Sie genau den Entscheidungsbaum, der in der Audicodes-Dokumentation veröffentlicht ist. Wichtig sind hier das Feld "MS LDAP primäry Key" und "MS LDAP Secondary Key". Der Audiocodes sucht nach der Nummer in diesen Feldern um das Objekt zu finden und dann darauf die bis zu vier Felder zu übernehmen.

Zuerst wird mit der Nummer im Feld "MS LDAP primäry Key" gesucht, ersatzweise im Feld zu "PHOINE" (was Default "telephone" ist) und erst wenn das nichts hilft, wird ggfls. mit der Nummer im Feld "MS LDAP Secondary Key" gesucht. Das ist wichtig, wenn Sie z.B. die Nummer in "msRTCSIP-Line" und "msRTCSIP-PrivateLine" suchen lassen wollen.

Beachten Sie auf jeden Fall, dass die von ihnen zur "Suche" ausgewählten LDAP-Felder auch im Active Directory im Index sind.

Die für Skype für Business interessanten beiden Felder sind per Default im Index und im Globalen Katalog.

Schaut man sich im SYSLOG den Search an, dann sieht man am Beispiel von telephoneNumber die Anfrage:

2015-07-01 22:58:45 <133>[S=2709] [SID:533209509] (   lgr_psbrdif)(2150      )  send --> LDAP SearchID:0 key:telephoneNumber=+495251304613 UserData:533209509
2015-07-01 22:58:45 <133>[S=2710] (   lgr_psbrdex)(2151      )  recv <-- acEV_LDAP_SEARCH_RESULT SearchId:0 UserData:533209509 SearchResultStatus=2

Der Trace zeigt sehr einfach die Suche "telephoneNumber=+495251304613". Wer nun aber neben der eigentlichen Rufnummer auch noch eine "Private Line" hat, wird vielleicht die Konfiguration wie folgt anpassen wollen:

Nun sucht der Mediant einmal die "msRTCSIP-Line" und dann noch mal die "msRTCSIP-PrivateLine". Allerdings steht dort natürlich die Rufnummer mit eine, "tel:"-Prefix und darf auch nicht entfernt werden. Einige Nummern haben sogar noch eine Extension in der form ";ext=xxx". Hier gibt es nun mehrere Optionen das Dilemma zu lösen:

  • "TEL:" addieren
    Über die Normalisierung TEL2IP könnte auch ein "tel:" addiert werden, so dass hier die Suche trifft. Das bedeutet aber, dass die Nummer gefunden werden muss, da ansonsten die Nummer mit dem "TEL:" prefix beim Routing dann zum LDAP_ERR-Fall übertragen wird und dort erneut wegnormalisiert werden muss.
  • Anderes Feld
    Sie könnte natürlich ein anderes Feld zur Suche nutzen. Leider ist das Feld "Telephone" nur ein einzelner String. Aber dahinter gibt es noch den Button "Other", der das Feld "otherTelephone" pflegt.

    Diese Feld kann mehrere Nummern enthalten und auch durchsucht werden. Allerdings muss man bei all diesen Feldern sicherstellen, dass man nichts anders stört, dass Sie nicht unbeabsichtigt "sichtbar" werden und auch im Schema ist eine Kontrolle angeraten:

    Hier ist der Standard ungeschickt, da dieses Feld nicht indexiert wird. Aber zumindest ist Ambiguous Name Resolution (ANR) nicht aktiv. da ansonsten auch Teilnummern gefunden würden, was z.B. oft die Zentrale betrifft. Aber einen DirSync zum Abgleich der Nummern ist immer noch erforderlich und bedeutet
  • Eigene Objekte
    Als dritte Option könnten sie in einem eigenen LDAP-Server (z.B. ADAM/AD LDS ) einfach für jede Nummer ein Objekt anlegen, welches dann die bis zu vier für das Routing relevante Rufnummern gleich in einem geforderten Format vorhalten.

Insofern werden kleinere Umgebungen vermutlich einfach das Feld "TelephoneNumber" richtig eintragen und auf "PrivateLine" verzichten. Größere Umgebungen werden eher einen eigenen LDAP-Server für das Routing von Anrufen verwenden, indem die Rufnummern und nächsten Ziele auch für größere Umgebungen optimal hinterlegt werden können.

LDAP Routing mit AVDisabled

Es gibt mit Lync durchaus den Einsatzbereich, dass Anwender kein Audio/Video per Lync machen dürfen. Das kann mehrere Gründe haben:

  • TK-Telefon als Strategie
    Der Benutzer soll vielleicht Lync nur für IM/Presence nutzen und eben kein PC2PC-Call
  • WAN-Bandbreite
    Das ist gerade für schwach angebundene Niederlassungen der Fall, die weiterhin eine klassische TK-Anlage vor Ort haben und Lync nur für IM/Presence nutzen
  • TerminalServer
    Zwar gibt es mit den passenden Clients auch die Möglichkeit (Stichwort VDI), Audio/Video auf Terminal Server Clients zu bringen. Aber das erfordert weitere Komponenten

In allen Fällen kann der Administrator die AV-Funktion für den Anwender entweder komplett oder pro Windows Client abschalten. (Siehe auch AVDisabled) Damit die Anwender aber dennoch sehr einfach dann mit ihrem TK-Tischtelefon teilnehmen können, kann ein Administrator das Feld "msRTCSip-Line mit der TK-Rufnummer füllen. Der Anwender bekommt dann einen Anruf von Lync auf der Nummer.

Wenn aber nun genau dieses Feld von einem Gateway beim "LDAP-Routing" als Kriterium für "Lync Enterprise Voice User" genutzt wird, dann wird ein eingehender Call eben nicht zur TK-Anlage gesendet, sondern zu Lync. Insofern sollte die LDAP-Anfrage sich doch auch noch auf die EV-Aktivierung stützen.

Dazu ist das Feld "msrtcsip-optionflags" abzufragen, welches als Bitmaske die verschiedenen aktivierten Funktionen des Benutzers liefert.

Noch ein anderes "Feature" kann die Suche nach Rufnummern erschweren. Über das Suffix "ms-skiprnl" kann eine Reverse Number Resolution in Lync verhindert werden. Auch dieser String steht in der msrtcsip-Line

Auch dieser Sonderfall muss vielleicht mit einem "*" abgefangen werden.

Nutzung im TEL2IP Routing

Dann muss in der Routingtabelle als Ziel eben nicht die IP-Adresse eines Gateway eingetragen werden, sondern LDAP als Ziel addiert werden und weitere Einträge routen dann die Verbindung anhand der LDAP-Antwort.

Hier ist schön zu sehen, dass alle Rufe die aus dem Telefonnetz herein kommen (und vorher normalisiert wurden) zur LDAP-Abfrage gelenkt werden. Nur die Faxnummern 650-689 werden vorab schon anderweitig weiter gegeben. (Das Routen auf 127.0.0.1 erlaubt mir diese Rufe von dem ISDN S2M Anschluss über "Loopback" auf einen ISDN S0 Anschluss intern zu routen, bis auch das Fax auf FaxoverIP umgestellt ist. dann wird dort der Faxserver als Next Hop eingetragen).

ACHTUNG: Wenn die LDAP-Anfrage fehl schlägt, dann kommt danach nur noch die LDAP_ERR-Regel zum Tragen. Wenn Sie "Nummer" ohne LDAP wegrouten wollen, dann muss das vorher passieren oder Sie arbeiten mit der "Alternative Routing Rule"

Die LDAP-Abfrage liefert als Antwort dann die Ergebnisse:

  • OCS:
    Benutzer ist per OCS erreichbar
  • PBX:
    Benutzer ist über die alte PBX erreichbar. Das kann auch eine IP-PBX oder eine als ISDN-Unteranlage angeschaltete PBX sein
  • MOBILE:
    Der Benutzer ist über Mobilfunk zu erreichen
  • PRIVATE
    Dahinter verbirgt sich die Nummer der "PrivateLine" (msRTCSIP-PrivateLine)
  • LDAP_ERR
    Der Benutzer wurde nicht gefunden

Hinweis zum Einsatz von "telephonenumber"
Damit die Suche „schnell“ geht, sollten Sie im AD-Schema dieses Feld mit einem "Index“ versehen. Das ist „by default“ nicht der Fall: (Siehe auch Telephone-Number Attribute http://msdn.microsoft.com/en-us/library/ms680027(VS.85).aspx. Der Index kann recht problemlos eingeschaltet werden, siehe: http://blogs.technet.com/b/ad/archive/2008/04/01/how-to-create-a-mosiac-of-user-thumbnails-in-aduc-dsa-msc.aspx
Wobei Sie in dem Feld natürlich auch reines E164 ohne Klammern, Leerzeichen o.ä. verwenden sollten, damit die LDAP-Suche auch "trifft". Siehe auch "Globalization Step-by-Step http://msdn.microsoft.com/en-us/goglobal/bb688129.aspx

Damit ein Objekt gefunden wir, muss also der Inhalt des LDAP-Feld "telephonenumber" gefunden werden können. Dem Mediant ist es egal, ob es sich um einen Benutzer, Kontakt, Ordner o.ä., handelt, solange eine einfache LDAP-Anfrage eine Antwort liefert. Zusätzlich fordert der Mediant drei weitere Fehler ab, die in der Konfiguration angepasst werden können. Anhand der Antwort wird dann folgender Entscheidungsbaum durchlaufen:

Die Prefixes, die zum Routing verwendet werden, werden natürlich bei der Weitergabe ans Ziel wieder entfernt. So kann man mit dem Audiocodes aber sehr gut eine dynamische Umschaltung und zudem eine Ausfallsicherung bezüglich OCS, Lync oder PBX erreichen. Allerdings darf natürlich das LDAP-Verzeichnis nicht ausfallen. Da es sich aber um "Standard LDAP-Calls" handelt, können Sie gerne auch ein OpenLDAP oder ein ADAM/AD LDS einsetzen. Bei der Wahl des "richtigen" OCS/Lync-Felds ("msRTCSIP-Line" statt "msRTCSIPPrimaryUserAddress") werden Rufe nur dann zum Mediation Server geleitet, wenn der Benutzer auch für Enterprise Voice aktiviert ist, d..h. tatsächlich auch über Lync telefoniert.

Nutzung beim IP2IP Routing mit CallSetupRules

Die Anzahl der "Telefonanschlüsse" nimmt immer mehr ab und SIP-Trunks ersetzen die Verbindung zwischen TK-Anlagen. Damit entfallen natürlich auch TEL2IP und IP2TEL. An deren Stelle tritt dann die SBC-Funktion (Session Border Controller) und ihre eigene Routing-Tabelle. Hier trägt man nun nicht LDAP als Ziel ein, sondern nutzt die Funktion der "Call Setup Rules". Hier habe ich in der Zeile 1 so eine Route definiert, bei der INVITE-Pakete über die Call Setup Rule Set ID = 1 verarbeitet werden und nur bei einem "Match" dann zur Destination IP Group ID 2 geleitet werden.

Diese Nummer verweist dann auf die "Rules Set ID" in den CallSetupRules-Tabelle. Hier ein Beispiel. Die Felder haben folgende Bedeutung

  • Index
    Das ist einfach eine laufende Nummer der Einträge
  • Rules Set ID
    Alle Zeilen mit der gleichen Nummer gehören zu einer Gruppe die von der Routingtabelle (IP2IP oder TEL2IP etc) adressiert werden kann. die Zeilen werden sequentiell in der Reihenfolge des Index abgearbeitet
  • Attributes to Query
    Der Name ist etwas irreführend. Ich würde eher "Objects to Query" hier sehen, denn es handelt sich um den LDAP-Filter, mit dem die Abfrage gestartet wird und hat nichts mit den Attributen der gefundenen Objekte zu tun
  • Attributes to Get
    In diesem Feld werden die Attribute angegeben, die von den gefundenen Objekten gelesen werden sollen.
  • Row Roles
  • Condition
    Hier steht der Ausdruck, der mit den Parametern des Anrufs (param.call.*) und z.B. den Werten der LDAP-Anfrage (ldap.attr.*) formuliert und bewertet wird.
  • Action Subject
  • Action Type
    Hier wird definiert, was beim "zutreffen" der Condition passiert. Die 21 im Beispiel steht für das Ende der Verarbeitung
  • Action Value
    Damit wird der Routingtable mitgegeben, ob die Verarbeitung durch die CallSetupRule als "zutreffen" bewertet werden soll. Wenn hier ein "False" als Ergebnis steht, dann wird der nächste Eintrag in der Routingtabelle evaluiert.

Hier ein Beispiel einer einfachen "CalLSetupRule"

Alle drei Zeilen gehören zur gleichen "Rules Set ID" und werden sequentiell abgearbeitet. In dem Beispiel nutze ich nicht das Feld "telephoneNumber", in dem ja alles stehen kann sondern das Skype für Business Feld "msRTCSIP-Line", welches mit um den Prefix "tel:" und das Suffix "*" erweitere. So kann der LDAP-Client erst mal suchen und dann das Feld "msRTCSIPLine" holen. Danach wertet der Audiocodes die erste "Condition" aus. Wenn Sie passt, ist das Ergebnis "true" und die Route wird eingeschlagen. Ohne Übereinstimmung wird dann die zweite Zeile geprüft. So kann ich Objekte mit einem ";ext"-Suffix als auch mit der reinen Nummer erkennen.

Wenn Sie genau nachdenken, dann sollten Sie aber auch die Einschränkungen dieser "einfachen" Lösung erkennen.

  • ms-skip-rnl
    Wie ich auf AVDisabled beschrieben habe, kann ein Benutzer so konfiguriert werden, dass er keine Anrufe bekommt, weil Lync die Nummer im Feld ignoriert. Bei passendem Voice Routing werden die Audio-Anrufe also an ein TK-Telefon weiter gegeben. In Verbindung mit dem LDAP-Routing müsste man diesen Sonderfall natürlich noch lösen, damit die Anrufe nicht einmal durch den Mediation Server durch müssen.
  • PrivateLine
    Das Beispiel wertet noch nicht das Feld "msRTCSIP-PrivateLine" aus. Wer also auch dieses "Feature" nutzt, muss die CallSetupRules noch erweitern.

Sie sehen also, das es oft nicht ganz so einfach ist und die Regeln schnell etwas umfangreicher werden können als zuerst gedacht.

LDAP Werte in der INI-Datei mit Debugging

Bei einem Audiocodes Gateway können Sie die Konfiguration recht einfach als INI-Datei herunter landen und mit der entsprechenden Erfahrung auch offline bearbeiten. Das ist durchaus interessant, z.B. um nach Werten zu suchen. Ich habe hier einen Auszug einer INI-Datei abgelegt, die ich in meinem Lab genutzt habe:

[SYSTEM Params]

LDAPDEBUGMODE = 3
LDAPSERVICEENABLE = 1
LDAPCACHEENABLE = 1
LDAPSEARCHDNSINPARALLEL = 0
LdapSearchServerMethod = 0

[SIP Params]
MSLDAPOCSNUMATTRIBUTENAME = 'SkypefB-LineNumber'
MSLDAPPRIVATENUMATTRIBUTENAME = 'SkypefB-PrivateLineNumber'
MSLDAPPRIMARYKEY = 'SkypefB-LineNumber'
MSLDAPSECONDARYKEY = 'SkypefB-PrivateLineNumber'

[ LdapConfiguration ]

FORMAT LdapConfiguration_Index = LdapConfiguration_LdapConfServerIp, LdapConfiguration_LdapConfServerPort, LdapConfiguration_LdapConfServerMaxRespondTime, LdapConfiguration_LdapConfServerDomainName, LdapConfiguration_LdapConfPassword, LdapConfiguration_LdapConfBindDn, LdapConfiguration_LdapConfInterfaceType, LdapConfiguration_Type, LdapConfiguration_MngmAuthAtt, LdapConfiguration_useTLS, LdapConfiguration_ConnectionStatus;
LdapConfiguration 0 = 0.0.0.0, 636, 3000, "DC1.msxfaq.net", "$1$kennwort=", "svcgw@msxfaq.net", 0, 0, "", 1, 3;
LdapConfiguration 1 = 0.0.0.0, 636, 3000, "DC2.msxfaq.net", "$1$kennwort=", "svcgw@msxfaq.net", 0, 0, "", 1, 3;

[ \LdapConfiguration ]


[ LdapServersSearchDNs ]

FORMAT LdapServersSearchDNs_Index = LdapServersSearchDNs_Base_Path, LdapServersSearchDNs_LdapConfigurationIndex, LdapServersSearchDNs_SearchDnInternalIndex;
LdapServersSearchDNs 0 = "dc=msxfaq,dc=net", "0", 1;
LdapServersSearchDNs 1 = "cn=Application Contacts,cn=RTC Service,cn=Services,cn=Configuration,dc=msxfaq,dc=net", "0", 0;

[ \LdapServersSearchDNs ]


[ CallSetupRules ]

FORMAT CallSetupRules_Index = CallSetupRules_RulesSetID, CallSetupRules_AttributesToQuery, CallSetupRules_AttributesToGet, CallSetupRules_RowRole, CallSetupRules_Condition, CallSetupRules_ActionSubject, CallSetupRules_ActionType, CallSetupRules_ActionValue;
CallSetupRules 1 = 1, "'msRTCSIP-Line=tel:'+param.call.dst.user+'*'", "msRTCSIP-Line", 0, "ldap.attr.msRTCSIP-Line contains 'tel:'+param.call.dst.user+';ext='", "", 21, "true";
CallSetupRules 2 = 1, "", "", 0, "ldap.attr.msRTCSIP-Line == 'tel:'+param.call.dst.user", "", 21, "true";
CallSetupRules 3 = 1, "", "", 0, "", "", 21, "false";

[ \CallSetupRules ]

Hier sehen Sie auch die globalen Einstellungen z.B. um die LDAP-Aktionen im Syslog ausführlicher zu protokollieren und die Antworten zu Cachen.

Weitere Links