[Frage] Inbound-Routen mit Mustern (FreePBX)

Zentronix

Mitglied
Mitglied seit
24 Jan 2010
Beiträge
631
Punkte für Reaktionen
31
Punkte
28
Hallo,

ich habe aufgrund der Schwierigkeiten mit Telefonkonferenzen bei Easybell nun eine eigene FreePBX aufgesetzt nur für diesen Zweck (FreePBX 15, Asterisk 16.6.2).

Dabei habe ich mehrere Konferenzräume angelegt, die anhand von Durchwahlen angewählt werden können. Beispiel:

04567 23344-11 zur Konferenz 1​
04567 23344-12 zur Konferenz 2​
04567 23344-13 zur Konferenz 3​
Es funktioniert mit diesen Inbound-Routes:

DID
4945672334411 -> Conferences: 1 ………
4945672334412 -> Conferences: 2 ………
4945672334413 -> Conferences: 3 ………
Jetzt hatte ich noch eine Einzelnummer hinzugefügt. Bei dieser kam aber überraschend statt "49………" als Zielnummer "0049………". Anscheinend ist das bei Easybell nicht einheitlich. Vermutlich bei Durchwahl-Trunks anders als bei Einzelnummern.

Also mußte ich die zusätzliche Inbound-Route wie folgt schreiben (Beispiel):

DID
004945675551234 -> Conferences: 4 ………
Diese unterschiedliche Schreibweise gefällt mir aber nicht. Auch weil Easybell vielleicht mal das Format ändert. Meine Experimente mit Mustern führen aber leider in die Irre. Zuletzt hatte ich Folgendes versucht:

DID
_X.2334411 -> Conferences: 1 ………
_X.2334412 -> Conferences: 2 ………
_X.2334413 -> Conferences: 3 ………
_X.5551234 -> Conferences: 4 ………
Testanrufe kamen aber leider beim falschen Konferenzraum an.

Hat vielleicht jemand einen Tip, was ich da falsch mache oder warum das nicht gehen kann?

Da das Muster "_." angeblich immer höchste Priorität hat, habe ich dieses bewußt nicht verwendet, sondern "_X.". Echte Regular-Expression kann man anscheinend bei der FreePBX nicht verwenden.

Danke und Grüße.
 
Du musst die DID vor dem Routen normalisieren auf die Schreibweise, die Du haben möchtest. Bei der Telekom kommt z.B. üblicherweise ein + am Anfang. Das bekommt man mit folgender Regel weg (ungetestet - geht hier nur darum, die grundsätzliche Vorgehensweise darzustellen - Du musst das für Deine Anforderungen umschreiben):

extensions_custom.conf
Code:
[from-pstn-remove-plus]
exten => _.,1,GotoIf($["${EXTEN}:0:1}" != "+"]?noplusatstart)
exten => _.,n,Set(${EXTEN}=${EXTEN}:1}) ; remove + from DID
exten => _.,n(noplusatstart),Noop()
exten => _.,n,Goto(from-pstn,${EXTEN},1)

Im Trunk musst Du dann den Kontext from-pstn-remove-plus angeben und im genannten Kontext auf den eigentlichen Kontext verweisen (hier: from-pstn) - Du machst im Prinzip nichts anderes, als einen eigenen Kontext dne FreePBX-Kontexten vorzuschieben.
 
Moinsen


Ich bin mehr ein Fan von: ExecIf()
Warum? - Weil jede Application/Funktion im then oder/und else Teil stehen kann, auch die GoTo() und GoToIf()
Dann würde dein Beispiel so aussehen...
Code:
[from-pstn-remove-plus]
exten => _.,1,ExecIf($["${EXTEN}:0:1}" != "+"]?Verbose(1,Kein Pluszeichen vorangestellt):Set(${EXTEN}=${EXTEN}:1}))
exten => _.,n,Goto(from-pstn,${EXTEN},1)
...und im ExecIf() lässt sich natürlich auch mit...
http://das-asterisk-buch.de/1.6/functions-regex.html
...was vergleichen ;)

PS: Der eigentliche Grund, warum _. keine Extension sein sollte sind die spezial Extensions wie: t h und i
...denn _. trifft auch auf diese zu und kann ganz merkwürdige Effekte hervorbringen.

Die höchste Priorität hat immer die Extension, die die meisten Übereinstimmungen hat.
${EXTEN}=123456 Dann gewinnt immer: exten => 123456,1,verbose(1, I am the greatest)
...vor: _X.
Checkt eure Wahlpläne mit: dialplan show nummer@kontextname
...oder alle Kontexte durchpflügen mit: dialplan show nummer@
...wobei die nummer beliebig sein kann/muss um die Wasserdichtigkeit zu Testen.
Zum Beispiel die hier...
https://de.wikihow.com/Den-Präsidenten-der-USA-kontaktieren
...ab: Im Weißen Haus anrufen
 
Zuletzt bearbeitet:
Hallo,

danke für die Vorschläge. Vielleicht werde ich mal so viel Verwegenheit zusammenbringen, es auszuprobieren.

Ich hatte mir aber auch einen Hinweis erhofft, warum das Routing mit den Platzhaltern so gar nicht funktioniert. Mit Dialplan kann ich sehen, daß zunächst der richtige Eintrag durchlaufen wird, und dann der hinzugefügte "_X.………" auch noch, obwohl er nicht passen dürfte.

Grüße.
 
Deswegen die Extensions mit "dialplan show" checken.
Es kann sein, wenn eine Extension nicht explizit mit "Hangup()" beendet wird, in der nächsten matchenden Extension ( _. bspw. ) in der nächsten Priorität weitergemacht wird.
Das ist genau dann der Fall, wenn die ungewollte Extension mehr Prioritäten hat als die Vorherige.

Beispiel:
Priorität _X. geht bis 3
Priorität _. geht bis 7
Endet nun _X. ohne Hangup() gehts in _. und Priorität 4 weiter.
Und wenn _. endet wird sie mit Prio 1 als h Extension angesprungen.
Sowas lässt sich auch vermeiden, indem mit GoTo() ein Kontext angesprungen wird, der nur eine Extension hat.
...und seine eigenen "special Extensions" ( h,i,t ).
Dieser Kontext wird dann der Channel, und es wird nicht zurückgesprungen zum aufrufenden Kontext.
 
Zuletzt bearbeitet:
Es kann sein, wenn eine Extension nicht explizit mit "Hangup()" beendet wird, in der nächsten matchenden Extension ( _. bspw. ) in der nächsten Priorität weitergemacht wird.

Mag sein, aber die nächste matcht gar nicht. Oder passen bspw. "_X.407" und "4945672334403" zusammen?

Ist in dem Muster alles nach dem Punkt "." unerheblich? Das würde das Verhalten erklären.

Das Muster soll nur zu Nummern passen, die mit bestimmten Ziffern enden. Die Länge ist nicht bekannt. Wenn das mit den Mustern nicht geht, ist das ganz schön ärmlich.

Grüße.
 
Naja, wenn du mal mit dialplan rumspielst, könnte dir eventuell auffallen, dass dem Punkt reichlich egal ist was danach kommt.
Der sollte, wie das Ausrufungszeichen, immer am Ende stehen.
Und ja, es ist demnach unerheblich.

Hier mal ein Superbeispiel...
Rich (BBCode):
osmc*CLI> dialplan add extension _X.[0].123,1,verbose(1,${EXTEN}) into osmc replace
Extension _X.[0].123@osmc (1) replace by '_X.[0].123,1,verbose(1,${EXTEN})'
[Nov 19 16:06:48]     -- Added extension '_X.[0].123' priority 1 to osmc
osmc*CLI> dialplan show 65748123@osmc
[ Context 'osmc' created by 'pbx_config' ]
  '_X.[0].123' =>   1. verbose(1,${EXTEN})                        [pbx_config]
  '_[0-9].' =>      1. verbose(1,${EXTEN})                        [pbx_config]
  '_[0-9]!' =>      1. verbose(1,${EXTEN})                        [pbx_config]
                    2. answer(250)                                [pbx_config]
                    3. waitexten(250,m)                           [pbx_config]

-= 3 extensions (5 priorities) in 1 context. =-
osmc*CLI> dialplan show 65748123321@osmc
[ Context 'osmc' created by 'pbx_config' ]
  '_X.[0].123' =>   1. verbose(1,${EXTEN})                        [pbx_config]
  '_[0-9].' =>      1. verbose(1,${EXTEN})                        [pbx_config]
  '_[0-9]!' =>      1. verbose(1,${EXTEN})                        [pbx_config]
                    2. answer(250)                                [pbx_config]
                    3. waitexten(250,m)                           [pbx_config]

-= 3 extensions (5 priorities) in 1 context. =-
osmc*CLI> dialplan remove extension _X.[0].123@osmc
Whole extension _X.[0].123@osmc removed

Unterschied zwischen . und !
Das Ausrufungszeichen im obigen Beispiel erlaubt einziffrige Nummern ( 0 - 9 ) bis beliebig Viele.
Das Selbe mit Punkt trifft mindestens auf Zweiziffrige (11, 12 etc. etc.) bis beliebig Viele zu.

Deswegen gibt es ja die Applikation RegEx().
Ich persönlich arbeite lieber mit einer Whitelist wo die Extension mit DB_EXISTS() nachschaut ob die ${EXTEN} eingetragen ist und wenn ja wird eine komplette Prioritätenapplikation aus der Datenbank ausgeführt.
Wenn nicht wird einfach wieder aufgelegt ( Hangup(17) ).
Seit dem brauch ich kaum noch die extensions.conf editieren.
Ich ändere/lösche oder lege einfach nur neue Datenbankeinträge an...
Rich (BBCode):
osmc*CLI> dialplan show spy@whitelist
[ Context 'whitelist' created by 'pbx_config' ]
  '_[a-z]!' =>      1. ExecIf($[${DB_EXISTS(${CONTEXT}/${EXTEN})}]?${DB_RESULT}:Hangup(17)) [pbx_config]

-= 1 extension (1 priority) in 1 context. =-
osmc*CLI> database show whitelist spy
/whitelist/spy                                    : chanspy()
1 results found.
...und ja, ich habe alle relevanten special Extensions auch in der Whitelist, die haben dann Priorität vor obigen _[a-z]!
 
Zuletzt bearbeitet:
Ok, dann ist jetzt klar, daß der Vergleich am Punkt endet. Das kommt in der Doku leider nicht so wirklich klar rüber. Meine ich.

Für weitere Möglichkeiten muß man anscheinend das FreePBX-GUI verlassen, was wohlüberlegt sein will.

Grüße.
 
Das Muster soll nur zu Nummern passen, die mit bestimmten Ziffern enden. Die Länge ist nicht bekannt. Wenn das mit den Mustern nicht geht, ist das ganz schön ärmlich.
Vielleicht gefällt dir ja sowas...
Rich (BBCode):
exten => 0/_100[5-9],2,waitexten(7200,m)
Nur Anrufer mit der Nummer 1005 bis 1009 kommen hier ( 0 ) durch ;)
Nennt sich: CID match


@Zentronix - Wenn dir das nichts bringt, weil obiges die ${CALLERID(num)} bestimmt, dann bleibt dir wirklich nur REGEX() wo mit dem Dollarzeichen das Ende von ${EXTEN} gecheckt werden kann.

Beispiel, lässt nur Nummern durch die 123 am Ende haben, nicht 3, nicht 23, nur exakt 123 :cool:
Rich (BBCode):
exten => _X.,1,execif($[${REGEX("123$" ${EXTEN})}]?verbose(1,MATCH: ${EXTEN}):verbose(1,MATCH: FAIL))
Mal die Nummer 4711007123 anrufen...
Rich (BBCode):
[Nov 19 21:12:25]   == Using SIP RTP CoS mark 5
[Nov 19 21:12:25]     -- Executing [4711007123@osmc:1] ExecIf("SIP/1007-0000002c", "1?verbose(1,MATCH: 4711007123):verbose(1,MATCH: FAIL)") in new stack
[Nov 19 21:12:25]  MATCH: 4711007123
Jetzt mal die 3 weglassen...
Rich (BBCode):
[Nov 19 21:14:00]   == Using SIP RTP CoS mark 5
[Nov 19 21:14:00]     -- Executing [471100712@osmc:1] ExecIf("SIP/1007-0000002d", "0?verbose(1,MATCH: 471100712):verbose(1,MATCH: FAIL)") in new stack
[Nov 19 21:14:00]  MATCH: FAIL
Nachteil: Kann nicht mit "dialplan show" auf positiven/negativen MATCH geprüft werden, nur mit einen Anruf gehts
 
Zuletzt bearbeitet:
Danke @koyaanisqatsi, Deine Ausführungen hier haben mich mal dazu gebracht, mich mit dem Dialplan intensiver zu beschäftigen. Ich habe daher meine Normalisierung für eingehende Calls jetzt umgeschrieben und auch noch gleich erweitert in der Funktionalität. Wer also eine Normalisierung gleich am Anfang machen möchte (ziemlich sinnvoll, damit man danach immer ein eindeutiges Format hat), kann ja mal damit starten:
Code:
[normalize]
exten => _+Z.,1,Goto(from-pstn-remove-plus,${EXTEN:1},3) ; remove + from DID
exten => _00Z.,n,Goto(from-pstn-remove-plus,${EXTEN:2},3) ; remove 00 from DID
exten => _Z.,n,ExecIf($["${CALLERID(num):0:1}" = "+"]?Set(CALLERID(num)=${CALLERID(num):1}))
same => n,ExecIf($["${CALLERID(num):0:2}" = "00"]?Set(CALLERID(num)=${CALLERID(num):2}))
same => n,Goto(from-pstn,${EXTEN},1)

Was machen die paar Zeilen Code?
=> Es wird das E.164-Format ohne führendes + eingestellt.

Die erste Priorität im Kontext entfernt ein potentiell führendes +-Zeichen in der DID (-> die angewählte Nummer) und ruft sich dann ohne das führende + gleich selbst wieder auf.
Die zweite Priorität entfernt führende Doppelnullen in der DID und ruft sich dann ebenfalls selbst wieder auf.

Der rekursive Aufruf startet den erneuten Aufruf des Kontexts übrigens immer gleich bei Priorität 3!

Die dritte Priorität entfernt das führende + bei der CID und die 4. Priorität entfernt führende Doppelnullen in der CID. Dann gehts ab in den eigentlichen from-pstn-Kontext.
 
Zuletzt bearbeitet:
Danke, höre lese ich gern, da das checken der Wahlpläne, besonders auf ungewollte Weiterleitungen, existenziell für den Geldbeutel sein kann.
Trotz Flatrates - Denn es gibt echt teure Verbindungen, beispielsweise nach Afrika :cool:
@Zentronix - Natürlich lässt sich das Ende von ${EXTEN} mit der Methode von @gehtdoch checken, aber mir persönlich ist das nicht so offensichtlich wie die Methode mit REGEX().
 
Zuletzt bearbeitet:
Auf das Ende einer Nummer unbekannter Länge hin prüfen - geht aus meiner Sicht nur mit Regex. Ich habe übrigens gerade versucht, Dein Beispiel
Code:
dialplan add extension _X.,1,execif($[${REGEX("123$" ${EXTEN})}]?verbose(1,MATCH: ${EXTEN}):verbose(1,MATCH: FAIL)) into test
über dialplan add extension on the fly reinzuhauen - hat aber nicht funktioniert, weil bereits beim Tippen immer seltsame Dinge passieren - asterisk passt da was automatisch an. Auch bei copy-paste wird da dann
Code:
dialplan add extension _X.,1,execif($[${REGEX("123$" into verbose(1,MATCH: ${EXTEN}):verbose(1,MATCH: FAIL)) into
draus - was natürlich nicht funktioniert.
Bug oder Feature (asterisk 18)?
 
Featurebug - Nenn ich es mal.
Das Fragezeichen lässt sich nicht über die Konsole eingeben, da es eine Funktion in der Konsole hat.
Deswegen:
Seit dem brauch ich kaum noch die extensions.conf editieren.
...bezieht sich auf die Applikationen, die ein Fragezeichen benötigen.
Wie: GotoIf() und ExecIf()

Tipp: Mach ein Backup deiner extensions.conf bevor du "dialplan save" benutzt
Denn "dialplan save" entfernt Kommentare und alle same werden durch exten ersetzt.
 
Der Hinweis mit dem dialplan save ist gut! Hatte ich jetzt konkret aber nicht im Kopf, weil ich sowieso mit FreePBX arbeite und dort - glücklicherweise - so gut wie nie im Dialplan rumfuhrwerken muss und wenn, dann nur über Config edit / save und dem FreePBX-internen reload. Da muss ich mir um derartige Dinge keinen Kopf machen.

Ich persönlich halte die Dialplan-Syntax, sagen wir mal, ziemlich gewöhnungsbedürftig.

Was das Thema Sicherheit angeht:
Für meinen Use case habe ich die asterisk Anbindung via iptables so eingeschränkt, dass außer dem Provider (via TCP/TLS) von Außen sowieso keiner drankommt. Bei TCP funktioniert connection tracking ja wunderbar. D.h., ein Angriff müsste dann schon direkt über einen Call des Providers an meine Nummer gehen. Welche Szenarien gäbe es da?
 
Naja, kann ich nicht sagen, dafür gibt es Pentests* die dir das aufzeigen könnten.
Mein Favorit zum Pentesten: SIPVicious
Lustige Schnellstartanleitungen gibt es auf YT.
Trotzdem gibt es immer mal wieder Ausnahmen die für Überraschungen sorgen können, wenn Anrufer ungeprüft im Dialplan weitergeleitet werden.

Beispiel:
In einer FRITZ!Box ist eine Nummer angelegt die sich am lokalen Asterisk registriert.
Eine angelegte VoIP Nummer in der FRITZ!Box ist via SIP URI Call aus dem Internet erreichbar.
Und die FRITZ!Box ist aus Asterisksicht authorisiert für Telefonie.
...da darf dann auf keinen Fall im Asterisk einfach mal nach Afrika weitergeleitet werden, wie auch immer.
Da muss der Dialplan drauf gecheckt werden.


* Pen steht für: Penetration und damit ist kein Bleistift gemeint ;)
 
Zuletzt bearbeitet:
Sowas wie eine FB oder Ähnliches kommt mir nicht ins Haus. An den Asterisk hier kommt von Außen ausschließlich der Provider-SIP-Server dran - und auch nur dann, wenn sich Asterisk vorher dort registriert hat. Klar habe ich zeitweise auch so was Ähnliches wie Weiterleitungen drin (follow me) - aber die gehen wiederrum auf meine eigenen Telefone.

Das Spannende wäre, wenn es möglich wäre, über einen regulären Call von Außen dieses follow me zu manipulieren. Ich wüsste aktuell nicht, dass das gehen würde - aber das heißt jetzt nicht viel.
 
Wenigstens führt sie ein Log, wo man ganz toll sehen kann, dass ich mir das mit den SIP URI Calls nicht aus den Fingern sauge.
Aus den erstellten erweiterten Support Daten...
Rich (BBCode):
2020-11-20 11:36:49.238 - IN: my=192.168.178.1%23:5060 peer=45.143.221.50 port=5063 UDP, sipiface=none:
OPTIONS sip:[email protected] 2.0
Via: SIP/2.0/UDP 45.143.221.50:5063;branch=z9hG4bK-1197832957;rport
From: "sipvicious" <sip:[email protected]>;tag=3265386530323665313363340134323533383137373037
To: "sipvicious" <sip:[email protected]>
Call-ID: 942817816335063430263007
CSeq: 1 OPTIONS
Contact: <sip:[email protected]:5063>
User-Agent: friendly-scanner
Max-Forwards: 70
Accept: application/sdp
Content-Length: 0
...von Heute - Und nicht selten.
Die FRITZ!Box beantwortet (unauthorisierte) OPTIONS zwar negativ, aber sie antwortet und der Scanner weiß Bescheid.
Das kann auch bezeichnet werden als: SIP Ping
Asterisk hingegen antwortet immer positiv auf sowas und ich bin mir relativ sicher, dass eine FRITZ!Box als Gateway für einen Asterisk die Sicherheit erhöht.
Deswegen gebe ich, solange ich mit Asterisk experimentiere, den Asterisk nicht fürs Internet (Portfreigaben, Registration bei einen externen Anbieter) frei.

So, wenn die OPTIONS Anfragen verebben dauerts auch nicht besonders lange bis sowas auftaucht...
Rich (BBCode):
2020-11-18 22:01:49.177 - IN: my=192.168.178.1%23:5060 peer=37.120.202.6 port=57884 UDP, sipiface=none:
INVITE sip:[email protected] 2.0
Via: SIP/2.0/UDP 0.0.0.0:57884;branch=z9hG4bK162177090
From: <sip:+4614213216:[email protected]>;tag=1215960744
To: <sip:[email protected]>
Call-ID: 848988928-1043863956-1653001973
CSeq: 1 INVITE
Contact: <sip:+4614213216:[email protected]:57884>
Max-Forwards: 70
User-Agent: pplsip
Content-Type: application/sdp
Content-Length:   205

v=0
o=+4614213216:5060 16264 18299 IN IP4 0.0.0.0
s=pplsip
c=IN IP4 0.0.0.0
t=0 0
m=audio 25282 RTP/AVP 100 6 0 8 3 18 5 101
a=rtpmap:0 pcmu/8000
a=rtpmap:101 telephone-event/8000
a=fmtp:101 0-11
Und in der Suchmaschine meines Vertrauens ( Begriff: tel 972592277524 ) bekomme ich ganz viele russische Webseiten geliefert.
 
Zuletzt bearbeitet:
Diese "Pings" sind mir bekannt (tauchen schön im tcpdump auf, der ja noch vor dem Portfilter sitzt). Die stören aber nicht, solange man den Portfilter so konfiguriert, dass eingehende Pakete auf den 5060/5061 nur zulässig sind, wenn vorher zu der entsprechenden IP eine ausgehende Verbindung initiiert wurde - klassisches connection tracking eben. Ansonsten, so wie Du schreibst - immer schön zu lassen. Gilt aber aus meiner Sicht für beliebige Programme. Daher habe ich hier aus- wie eingehend die gleiche Policy: erstmal alles verbieten und dann nur die gewünschten Verbindungen zulassen (whitelist-Konzept).
 
Holen Sie sich 3CX - völlig kostenlos!
Verbinden Sie Ihr Team und Ihre Kunden Telefonie Livechat Videokonferenzen

Gehostet oder selbst-verwaltet. Für bis zu 10 Nutzer dauerhaft kostenlos. Keine Kreditkartendetails erforderlich. Ohne Risiko testen.

3CX
Für diese E-Mail-Adresse besteht bereits ein 3CX-Konto. Sie werden zum Kundenportal weitergeleitet, wo Sie sich anmelden oder Ihr Passwort zurücksetzen können, falls Sie dieses vergessen haben.