Часто бывает, что оператор присылает номер звонящего в неудобном формате, а так же не корректно указывает номер DID. Рассмотрим как поправить эту ситуацию.
Для начала разберемся с понятиями:
DID (Direct Inward Dialing) — возможность АТС использовать несколько городских номеров для маршрутизации входящих вызовов. Попросту говоря, это ваш внешний номер, на который вам звонят клиенты
CID (Caller ID) — номер вызывающего абонента.
И так, провайдер присылает CID в формате +7XXXXXXXXX или 7XXXXXXXXXX а мы хотим 8XXXXXXXXXX (Причин тому может быть много: например возможность перезвонить абоненту нажатием одной кнопки на телефоне, или специфика используемой crm системы и т.д.)
Для решения данной проблемы нам нужно взять последние десять символов из CIDа и добавить к ним 8. Делается это путем создания своего контекста, в котором мы первично изменяем необходимые нам данные а потом дальше направляем во from-trunk. Соответственно в настройках нужного транка контекст нужно указать наш собственный (context=from-operator)
[from-operator] exten => _.,1,Set(CALLERID(all)=8$) ; :-10 означает что отчет начинам с десятого символа слева, :10 означает что берем с места отчета последующие 10 символов, и 8 означает что ко всему полученному номеру добавляем слева 8. exten => _.,2,Set(CALLERID(ANI-all)=$) ; подставляем измененныйcid для статистикиcdr exten => _.,3,Goto(from-trunk,$,1) ; направляем измененные данные воfrom-trunk для последующей обработки
Второй случай бывает гораздо реже, это когда оператор присылает DID в каком-нибудь коротком виде типа 687 который никак не связан с номером компании. На скриншоте ниже видно как астериск принимает от оператора DID с номером 687
Так же мы видим что астериск не получает CID звонящего, вернее получает (если просмотреть SIP дебаги то оператор присылает номер звонящего в графе CALLERID(name)), а это уже третий случай который встречается очень редко.
Для решения первой проблемы нам необходимо так же создать свой контекст в котором принудительно направить вызов на экстеншн (номер) которой будет равен вашему DID (внешнему номеру)
Для решения проблемы с CID нам нужно CallerID звонящего брать из CALLERID(name)
[from-operator] exten => _.,1,Set(CALLERID(all)=8$) ; все как и в первом случае за исключением того что беремCID изCALLERID(name) exten => _.,2,Set(CALLERID(ANI-all)=$) ; подставляем измененныйcid для статистикиcdr exten => _.,3,Goto(from-trunk,4952326666) ; направляем вызов дальше в обработку воfrom-trunk на экстеншн равный нужному номеру вашегоDID
Если все правильно то видим и CallerID звонящего и нужный DID
Только не забываем настроить входящую маршрутизацию, как это сделать можно посмотреть тут
Нетривиальная задача с callback + DID в Asterisk
40 различных ООО в составе холдинга Текущая задача: — сделать callback сервис для каждого номера DID (и соответственно от каждого ООО)
Казалось бы, «это же freePBX — там всё делается мышкой». Это не совсем так.
Шаг первый. Осознание проблемы.
Я использую веб интерфейс elastix для настройки. Он мне очень нравится. Идём в PBX->PBX Configuration->Callback и заполняем данные для калбэка. Идём в раздел IVR, выбираем нужное меню и настраиваем, например на «9» наш callback. Проверяю — всё работает. Позвонил с 28-xx-yy — вызов вернулся с 28-xx-yy Сделал аналогично для IVR на номере 28-xx-xx — вызов вернулся с 28-xx-yy Согласитесь, как то нелогично получается, когда ты звонишь заказать продукты, а тебе перезванивают с номера какого то завода. А у меня таких организаций довольно много. Отсюда и вытекла текущая задача: нужно, чтобы позвонив на 28-xx-xx — вызов возвращался с номера 28-xx-xx
Шаг второй. Поиск решения из веб интерфейса elastix/FreePBX
Скажу сразу. Может оно и есть, но я его не обнаружил.
Шаг третий. Изучение конфигурационных файлов напрямую
Контекст для callback находится в файле extensions_additional.conf
Видим что вызов осуществляется из php скрипта /var/lib/asterisk/bin/callback Полистав его, узнаём, что вызов осуществляется с канала Local, и уходит по правилам исходящих маршрутов (Outbound Routes) И спустя рабочий день попутных раздумий меня посетила идея — сделать нужный DID на основе префиксов при наборе из callback.
Шаг четвёртый. Решение задачи
Техническая сторона оказалось весьма «сложнее». Как известно, FreePBX перезатирает extensions_additional.conf при любом своём сохранении. Добавил нового пользователя через веб — применяй свои контексты заного. Решением этого является использование файла extensions_override_freepbx.conf — но у меня так и не получилось. Не стал тратить более часа на изучение — ведь решение главной задачи уже летало где то в воздухе. Я инстинктивно осознавал, что причина скорее всего в том, что на сервере уже много что переписано.
Смотрим контекст [callback] Нам нужно передать DID в переменную CALL. Через callback-custom это делать бесполезно — всё равно переменная переназначится ниже по основному контексту. И тогда, я вспомнил полезную статью. Добавляем в extensions_custom.conf контекст [callback-az], сделанный копированием [callback] и добавляем FROM_DID в переменную CALL
Замечу, что у моих операторов на телефонах высвечивается звонящий просто — «Callback» Забегу вперёд, это вызвало панику — ведь они обслуживают кучу организаций, и хотят видеть — куда пришёл звонок. Логично, не поспоришь. Поэтому в контексте выше я добавил переменную DESC, текстом, и отправил её в скрипт callback. Это всех устроило.
Дальше модифицируем сам скрипт /var/lib/asterisk/bin/callback — как уже было сказано, это простой php скрипт. Думаю, все уже поняли, что будет дальше. Ищем
Готово. Дальше нужно правильно делать вызов в контекст. Вспомню вышеприведённую полезную статью и картинки к ней. В Elastix нет модуля Custom Destinations, поэтому лезем непосредственно в FreePBX. Он находится по адресу: ip-add/admin логин и пароль стандартные, легко гуглятся.
Делаем вот так: Разъясню. Первая «1» в строке callback-az,1,1 это номер callback из контекста [callback-az] — у нас получится несколько callback в контексте (по 1 на каждый DID). Вторая «1» — это номер приоритета.
Ну и финальный штрих — указываем в IVR у нашего DID на цифру 9 — наш Custom Destination И так делается для каждого DID и Callback
Не забудьте добавить префикс в исходящие маршруты! Об этом не буду рассказывать, вот именно это легко можно сделать мышкой.
И ещё про «домашний» Asterisk
Прочитав этот пост, решил поделиться и своим опытом.
Выбираем DID number
Всё начинается с номера телефона, на который вам будут звонить, общепринятое название — Direct Inward Dialing (DID) number.
Самое дешёвое предложение с прямым московским номером — «Баzа» (предоставляется Центральным Телеграфом). На момент написания поста самый дешёвый тариф стоит 250 руб/мес, плюс разовая оплата за подключение номера в коде 499 или 495, на выбор. При подписании договора лучше сразу попросить, чтобы подключили переадресацию на SIP устройство (дополнительная услуга «Баzа-IP», подключение оплачивается разово). Переадресация на SIP бесплатная. Это мой выбор.
Если вам надо совсем дёшево и сердито, есть mango-office, московский номер с тоновым донабором за 30 руб/мес 🙂 Я этот вариант не пробовал.
У Localphone можно купить DID номер в 49 странах мира (России в списке нет) с оплатой от £0.75 (≈37 руб) в месяц. Этот вариант я тоже пока не пробовал, но планирую 🙂 Номер в Лондоне или Нью-Йорке может пригодиться.
На этом минимально необходимые настройки закончены.
Сервер для VoIP
Для Asterisk был выбран дешёвый виртуальный сервер в Германии на технологии Xen за €3/мес: 128Mb RAM, 256Mb swap, 10Gb disk, ОС Debian stable. На данный момент этого более чем достаточно.
И создаём контекст «from-baza» в плане нумерации с одним единственным номером, который был указан выше в параметре callbackextension. Самый простой вариант, в /etc/asterisk/extensions.conf:
Звоним одновременно на мобильный телефон через оператора TerraSIP и на стоящий на столе SIP телефон. Настройки последнего приводить не буду — всё стандартно.
Выбор оператора для терминации VoIP трафика
Тут не обошлось без приключений.
Вначале выбор казался очевидным — Betamax. Это немецкий VoIP оператор с очень вкусными тарифами и, вместе с этим, хорошим качеством связи. Он работает через несколько десятков своих реселлеров, поэтому вначале смотрим тарифы в сводной таблице, затем регистрируемся у реселлера с самыми выгодными расценками и наслаждаемся жизнью 🙂 Я так и сделал.
А вчера всё перестало работать. Сервера Betamax стабильно отдают моему астериску сообщение: «SIP/2.0 503 For wholesale traffic, check www.voicetrading.com».
Резюме: Betamax непригоден для моих целей, как это ни печально звучит.
Сейчас я использую оператора TerraSip. Тарифы тут немного выше, чем у Betamax и, главное, нет бесплатных минут, как у последнего. Настройки Asterisk для работы с TerraSip также приводить не буду — на их сайте всё подробно рассказано.
trixbox / PPX-in-a-Flash / Asterisk Admin GUI users click here
GENERAL INFORMATION
In this guide we will configure inbound routing based on the DID (number) information returned by Callcentric. In order to do this you will need to do further editing to your current Asterisk configuration.
Below we will provide the necessary information to configure your Asterisk installation to route based on the called DID in your Callcentric account.
Understand that this guide presents the most basic configuration for configuring DID based routing and is meant as a learning tool to assist you in configuring your own complex routing.
The setup information below is based on Asterisk 1.4; although most other older and newer versions should be very similar.
Please note that Callcentric is not responsible for preventing unwanted physical or remote access your IP PBX. If your IP PBX is compromised then you will be responsible for any damage caused. Please be sure to read this guide regarding securing your IP PBX solution.
CONFIGURATION
Prerequisites: In order to use this guide you will need a properly configured Asterisk installation which can receive incoming calls from Callcentric. You may double check our Asterisk setup guide to make sure that your system can at least initially receive incoming calls.
Once you can receive incoming calls properly you may configure DID based routing by following the instructions below:
1
Creating or editing the inbound context
Here we will configure the inbound context which will be used to handle the routing of inbound calls to your Asterisk installation. To create this context you can either use the command line or a text editor to edit the extensions.conf file.
Once you are able to access the extensions.conf file you can follow the steps below:
1. Enter the following context:
Where and are the exact information returned by Callcentric’s servers for your 1777 number and any DID on your account, respectively.
And where extension1 and extension2 are contexts which decide where to send the call. For example:
2
Configure your inbound routing to route to your DID routing context
In your extensions.conf file use the following, from-callcentric can also be your own incoming context:
Asterisk/FreePBX: How to get the DID of a SIP trunk when the provider doesn’t send it (and why some incoming SIP calls fail)
The symptom: On a SIP trunk, you can’t get an inbound route to work – it just doesn’t seem to recognize the number. You might be able to get the call to come in on your any DID/any CID route, or maybe the call doesn’t get answered at all. When you type sip debug from the CLI, you can see (when you scroll back to the point where the call came in) that a sip INVITE packet arrived, and perhaps it contained the DID number in the sip To: header (in the form To: ), but you also see that the FROM_DID was set to s. In other words, you see a line that looks like this:
EDIT: The most common reasons this happens are one or both of two things. Either you are not specifying the number of your DID in the format your provider is sending it (for example, they are sending 11 digits including a leading “1”, but you are only using ten digits in your inbound route), or they are sending the number in the SIP “To:” header. In the latter case, FreePBX has a much easier way to deal with this now. Before you do anything else, try changing the trunk context from from-trunk or from-pstn to from-pstn-toheader. This works for both SIP and PJSIP trunks, but only if the provider really is sending the number in the SIP “To:” header.
Only continue with this article if you have tried the above and it doesn’t work, as much of what is below simply shows an older and less intuitive way of doing the same thing. If the above did not work, don’t forget to change your trunk context back to whatever it was previously. (End of edit.)
Before you attempt anything else, you may want to try this suggestion by Dan Swartz: Check the registration string (in the trunk settings for the provider), and if it’s not already there, try putting the DID at the end of the registration string, prefixed by a ‘/’. It may (or may not) require a leading ‘1’ too. e.g. ‘/18005551212’ (or your country code if you are not in the U.S./Canada, etc.). So, your registration string would take this format:
(Oh, and for anyone who’s still trying to figure out how to turn off sip debugging, the CLI command is sip no debug)
Fortunately this isn’t a hard thing to work around, as long as the DID number really is in the sip To: header.
NOTE: In the following examples, we now use the s extension rather than _. – this is considered better practice (and safer) but the disadvantage is that the context will fail if the provider is sending any type of DID, even if it’s incorrect or incomplete. If the code doesn’t seem to work, try replacing the s extension with _X! (the extension is to the right of the => and space characters).
First, create a context in extensions_custom.conf that looks like this:
EDIT: Really, don’t do this next part, unless you are running an old version of FreePBX! Just change your trunk context to from-pstn-toheader and be done with it! (End of edit.)
Or, thanks to naftali5, you can cut the above down to one line of code that does the same thing, but is a bit less obvious to the casual reader:
(And speaking of naftali5, if you are using his Dialplan Injection module – which may not work with the most recent versions of FreePBX, so don’t run out and get it if you aren’t already using it unless you are sure it has been updated to work with the version of FreePBX that you are using – and want to put the above line in the Destination section, then you will need to use a slightly different syntax, changing the commas to bar characters, so it looks like this:
The part after Custom App: is what you paste into the text box. This ONLY applies to Dialplan Injection users)
Then, in the trunk associated with the provider, change the trunk context statement (which should read context=from-trunk) to:
(Or for Dialplan Injection users, just use
but replace n with the actual injection number, which will appear next to the injection name in the right-hand column menu of injections.)
And note that with such providers, you may have to move that context statement from the USER details to the PEER details section. This is why calls from some SIP providers sometimes fail to come in at all – they effectively never «see» the User context and details, therefore they don’t see the context statement there and have nowhere to go. It’s also why you sometimes see instructions for sip providers that leave the User context and User details sections totally blank, but include a context statement in the peer details – in most such cases it’s because the provider is treating the customer as an end user (like someone using a softphone or a VoiP adapter) rather than as a peer, and they aren’t sending DID information.
The above instructions may also solve the problem where you have two (or more) trunks from the same provider, but Asterisk always treats it as if all calls are coming in on one of the two trunks, therefore again not allowing you to set up separate inbound routes for each trunk. As long as the provider sends the number in the sip To header, the above code should set the DID properly.
If the first part of the To: statement is something other than a DID number (a user name, for example), then you may have to add a line just before the final Goto statement. For example, let’s say the provider is sending To: and your DID number (or at least, the number you want to use to denote your inbound route) is really 5551212. You’d then use code similar to this:
Or, as long as you only have ONE trunk from that provider, you could always just cheat a little and hardcode the desired DID in a separate custom context, like this:
And use the name of this context in the trunk settings. I hear you asking, why not just do it this way on all trunks with this issue? Well, because if you add a second trunk from the same provider, this won’t work correctly for both trunks, and if you ever change your number and then forget what you’ve done and just try to set your inbound route to the new number, it won’t work. And besides all that, if you have more than one SIP provider that doesn’t send proper DID, you’d have to create a separate custom context for each of them, instead of having one custom context that works for all of them.
One final note for Free World Dialup users, you may find that sip calls will still not come in until you put the following statement in sip.conf:
I have no idea why that works, but it seems to make a difference.
What if the provider doesn’t send the number in the sip To: header?
There is at least one provider that actually sends a s character instead of a number in the sip To: header. What can you do with a provider like that? Well, all may not be lost. If you only have a single trunk from that provider, you can just use the «cheat» shown above, since it doesn’t rely on the contents of the sip headers. If, however, you have TWO or more trunks from the same provider, you can do a sip debug from the CLI and watch as calls come in on each trunk and note whether there are any consistent differences.
For example, if you have two lines on the same account, the provider will often assume that you are using a VoIP adapter (such as a Sipura or Linksys) and will use port 5060 for line 1, and port 5061 for line 2. That difference might show up in the headers of the sip INVITE packet, for example:
In this case, you see that there is a colon (:) before the port number and a semicolon following, and that there are actually TWO colons on the line before the port number, so maybe this would work:
Or, if you only have two trunks from this provider, you probably could just condense the two test lines into one, by testing for one port number and assuming the other if the conditional test fails, like this:
Note that the code in this section is untested, it’s just to give you some ideas about how to possibly handle the really oddball situation were you have two (or more) lines from the same provider, and cannot find any other way to differentiate them. And, don’t automatically assume you have a bigger problem than you actually have – for example, it may well be that having different port numbers on the different trunks would allow Asterisk to distinguish them enough that the simple «cheat» method would work (you’d have to make one for each trunk, of course).
Addendum
There are a few other reasons that incoming calls may fail that have nothing to do with the main topic of this How-To, but are common enough that they should be mentioned anyway. The first is that in every trunk configuration, there must be a statement that reads: context=from-trunk Some providers will tell you to set the context statement to something else – don’t do it (unless you have a valid reason, such as following the instructions above). Providers are generally more familiar with Asterisk than FreePBX, and often don’t realize that you can’t just use any context name you like in FreePBX unless you also create that context somewhere (usually extensions_custom.conf).
Also the placement of that context= statement can be important. If a provider is treating you as an extension (which would likely be the case if most of their customers use VoIP adapters and/or you are a “Bring Your Own Device” customer) then in most cases you will not need to have a USER context or USER details at all in your trunk, but you still need to have a context=from-trunk statement (or another context= statement if you are following instructions elsewhere on this page) and in this case it will need to be in your PEER details, not your user details. So, if incoming calls aren’t working, try putting context=from-trunk in your trunk PEER details, and if that works, then totally remove the USER context and USER settings from your trunk configuration, since they aren’t doing any good anyway.
To further complicate matters, I have noted that with a couple of providers, nothing seems to work until you do the following. The symptom typically is that you have no problem connecting with other providers, and (if you have tried this) you have no problem connecting with the provider in question if you are using an external hardware device (such as an ATA), but no matter what you do you can’t receive calls from the provider. I hate recommending this because I don’t know exactly why it works, but it’s a trick I’ve used for a couple years now to resolve issues with a couple of specific providers. Don’t try this until you’ve first tried adding the DID at the end of the registration string, prefixed by a ‘/’, as shown near the top of this page.
Open the file /etc/asterisk/sip_general_custom.conf in any text editor and check to see if the following lines are in there:
If any of the above lines are missing, add them to the file. In my experience these lines will not cause problems with other providers but they do magically get things working with a select few providers that are more used to serving customers using an ATA than through a trunk into an Asterisk box. If this gets things working you can try removing lines one at a time to find out which are actually doing the trick, or you can just leave them all in place – as I say, in my experience they don’t seem to cause problems with other providers, although obviously your experience might be different.
Yet another issue that you may encounter, especially if you are upgrading from an earlier version of FreePBX, is that if you have disallow= and allow= statements in your trunk configuration (to specify the use of particular codecs), starting with Asterisk 1.4 the disallow= statement(s) (particularly if it’s disallow=all) must be placed above the allow= statements. This is one of many cases where Asterisk upgrades have broken existing functionality for no good reason whatsoever, other than that the Asterisk developers could not be bothered to ensure backward compatibility.
One other note: There is an obscure bug in Asterisk that can cause incoming calls to fail. If Asterisk ever receives a Caller ID NAME that contains only one quotation mark (usually a name with a quotation mark at the start of the string but not at the end) it will not handle the call properly, and may ignore the incoming call completely.