Дмитрий Кайдаш
19.02.2019
2995

Ограничение внутренних вызовов через AstDB

В данной статье будет рассмотрен способ настройки ограничения внутренней связи по группам. Реализация задач Для решения поставленных задач нам понадобится создать отдельный custom-context для целевого внутреннего номера. Создаём новый connectivity->custom-context->Add context Выставляем необходимые внешние маршруты, как входящие так и исходящие, при этом запрещая все внутренние. После чего назначаем внутреннему номеру новый контекст: И приступаем непосредственно […]

Запрет внутренних вызовов через AstDB

В данной статье будет рассмотрен способ настройки ограничения внутренней связи по группам.

Реализация задач

Для решения поставленных задач нам понадобится создать отдельный custom-context для целевого внутреннего номера. Создаём новый connectivity->custom-context->Add context

Выставляем необходимые внешние маршруты, как входящие так и исходящие, при этом запрещая все внутренние.

Создаём контекст

После чего назначаем внутреннему номеру новый контекст:

Назначаем контекст

И приступаем непосредственно к обработке логики диалпланом. Допустим нам необходимо разрешить вызов номера директора только от заместителя и представителей руководства. Номер первого: 771. Группа разрешенных номеров: 117, 131, 136, 169, 186, 194, 501, 508, 514, 540, 701, 702, 736, 901, 908, 921.

Небольшое отступление: причина использовать базу, не воспользовавшись стандартными возможностями диалплана asterisk вида:

exten => 771/_[1579][0-4689][ 1246-9],1,...

Очень проста. Во-первых чтобы поменять допустимое значение потребуется переписывать конфигурационный файл extensions_custom.conf и контекст [from-internal-custom], в частности. После чего будет необходимо выполнить применение настроек командой: dialplan reload. Что не всегда возможно и удобно. В тоже время добавив один раз небольшие правки в диалплан и AstDB мы получим гибкую систему настройки. Помимо прочего, которой можно будет управлять извне, какими-либо средствами.

Приступим к заполнению базы нашими номерами. Для этого потребуются следующие команды CLI-консоли:

  • добавление одной записи:
# asterisk -rx 'database put 771_ALLOW 115 1'
  • удаление одной записи:
 asterisk -rx 'database del 771_ALLOW 115'
  • удаление древа записей:
# asterisk -rx 'database deltree 771_ALLOW'
  • просмотр текущего древа:
# asterisk -rx 'database show 771_ALLOW'
Проверяем записи в AstDB

Подробнее о работе с AstDB рассказано в статье.

И наконец обработчик в диалплане будет выглядеть следующим образом:

; ------------------ Inbount calls ------------------
exten => 771,1,GotoIf(${DB_EXISTS(${EXTEN}_ALLOW/${CALLERID(num)})}?from-internal-additional,${EXTEN},1)
same => n,Busy(5)
same => n,Hangup

Здесь мы разрешаем вызов номера 771 только номерам разрешенным в базе.

; ------------------ Outbound calls ------------------
[for-771-custom]
exten => _X.,1,GotoIf(${DB_EXISTS(771_ALLOW/${EXTEN})}?from-internal,${EXTEN},1)
same => n,Busy(5)
same => n,Hangup

Здесь разрешаем самому внутреннему номеру 771 вызывать только номера указанные в базе. Остальным будет выдан сигнал «занято» и вызов завершится.

Как уже говорилось ранее, добавить в файл extensions_custom.conf, контекст [from-internal-custom]

Web-интерфейс

Пример приложения

Упростим эксплуатацию так, чтобы она была доступна пользователям без прямого доступа в терминал сервера. Для этого понадобится редактор и некоторый интерфейс, который будет переписывать значения в базе. Его можно написать самостоятельно или воспользоваться кодом ниже. Используем возможность гибридизации html и php для сокращения размера кода и наглядности. Подробных пояснений к разметке давать не будем, пройдёмся лишь по скриптам-обработчикам. Первый фрагмент:

$exec_out_1=[];
exec('mysql -u freepbxuser -pd45c7ea6a5460b03300977b1cd61f148 -D asterisk -N -e "select id from devices"',$exec_out_1);
foreach($exec_out_1 as $element){
	$check=($_POST['for_exten']==$element)?'checked':'';
	echo '<label><input type="radio" name="for_exten" value="'.$element.'" '.$check.' />'.$element.'</label>';
};

Объявляем массив для хранения переменных, запрашиваем у системы список внутренних номеров и сохраняем в нём. После чего выполняем проход по массиву и генерируем html-элементы соответствующие типу radio (для однозначного выбора).

Второй:

if(isset($_POST['give'],$_POST['for_exten'])){
	$exec_out_2=[];
	exec('asterisk -rx "database show IN_ALLOW_'.$_POST['for_exten'].'" | grep IN_ALLOW_',$exec_out_2);
	foreach($exec_out_1 as $element){
		$check=(in_array('/IN_ALLOW_'.$_POST['for_exten'].'/'.$element.'                                 : 1',$exec_out_2))?'checked':'';
		echo '<label><input type="checkbox" name="granted_in[]" value="'.$element.'" '.$check.' />'.$element.'</label>';
	};
}
if(isset($_POST['send'],$_POST['for_exten'],$_POST['granted_in'])){
	exec('asterisk -rx "database deltree IN_ALLOW_'.$_POST['for_exten'].'"',$null);
	foreach($_POST['granted_in'] as $element){
		exec('asterisk -rx "database put IN_ALLOW_'.$_POST['for_exten'].' '.$element.' 1"',$null);
	}
}
elseif(isset($_POST['send'],$_POST['for_exten'])){
	exec('asterisk -rx "database deltree IN_ALLOW_'.$_POST['for_exten'].'"',$null);
}

Здесь возможно три развития событий в зависимости от аргументов POST-запроса:

  1. Внутренний номер «for_exten» и параметр запроса «give».
    Получаем в массив все разрешения, выполнив запрос в AstDB, для текущего выбранного номера. После чего перебираем все внутренние номера и в зависимости от наличия в новом массиве строки разрешения генерируем html-элементы checkbox (для множественного выбора) в активном или пассивном состоянии.
  2. Внутренний номер «for_exten» и параметр сохранения «send».
    Удаляем древо базы AstDB по текущему выбранному номеру. Таким образом реализована очистка базы если не выбран ни один разрешенный номер.
  3. Внутренний номер «for_exten», параметр запроса «give» и массив новых правил «granted_in»

Выполняем перебор всех переданных правил и вносим их в AstDB под соответствующее древо и внутренний номер.

Третий:

if(isset($_POST['give'],$_POST['for_exten'])){
	$exec_out_3=[];
	exec('asterisk -rx "database show OUT_ALLOW_'.$_POST['for_exten'].'" | grep OUT_ALLOW_',$exec_out_3);
	foreach($exec_out_1 as $element){
		$check=(in_array('/OUT_ALLOW_'.$_POST['for_exten'].'/'.$element.'                                : 1',$exec_out_3))?'checked':'';
		echo '<label><input type="checkbox" name="granted_out[]" value="'.$element.'" '.$check.' />'.$element.'</label>';
	};
}
if(isset($_POST['send'],$_POST['for_exten'],$_POST['granted_out'])){
	exec('asterisk -rx "database deltree OUT_ALLOW_'.$_POST['for_exten'].'"',$null);
	foreach($_POST['granted_out'] as $element){
		exec('asterisk -rx "database put OUT_ALLOW_'.$_POST['for_exten'].' '.$element.' 1"',$null);
	}
}
elseif(isset($_POST['send'],$_POST['for_exten'])){
	exec('asterisk -rx "database deltree OUT_ALLOW_'.$_POST['for_exten'].'"',$null);
}

Выполняется аналогично трём пунктам предыдущего фрагмента с заменой наименования древа: с IN_ALLOW_<номер> на OUT_ALLOW_<номер>.

Совместив это всё с разметкой получим следующий скрипт:

<html>
	<head>
		<title>CallLimit</title>
		<link rel="shortcut icon" href="favicon.png" type="image/png">
		<link rel="stylesheet" href="style.css" type="text/css">
	</head>
	<body>
		<form action="" method="post">
			<fieldset>
				<legend>Ограничения вызовов</legend>
				<fieldset class="subfield">
					<legend>Внутренний номер</legend>
					<?php
						$exec_out_1=[];
						exec('mysql -u freepbxuser -pd45c7ea6a5460b03300977b1cd61f148 -D asterisk -N -e "select id from devices"',$exec_out_1);
						foreach($exec_out_1 as $element){
							$check=($_POST['for_exten']==$element)?'checked':'';
							echo '<label><input type="radio" name="for_exten" value="'.$element.'" '.$check.' />'.$element.'</label>';
						};
					?>
				</fieldset>
				<fieldset class="subfield">
					<legend>Входящие</legend>
					<?php
						if(isset($_POST['give'],$_POST['for_exten'])){
							$exec_out_2=[];
							exec('asterisk -rx "database show IN_ALLOW_'.$_POST['for_exten'].'" | grep IN_ALLOW_',$exec_out_2);
							foreach($exec_out_1 as $element){
								$check=(in_array('/IN_ALLOW_'.$_POST['for_exten'].'/'.$element.'                                 : 1',$exec_out_2))?'checked':'';
								echo '<label><input type="checkbox" name="granted_in[]" value="'.$element.'" '.$check.' />'.$element.'</label>';
							};
						}
						if(isset($_POST['send'],$_POST['for_exten'],$_POST['granted_in'])){
							exec('asterisk -rx "database deltree IN_ALLOW_'.$_POST['for_exten'].'"',$null);
							foreach($_POST['granted_in'] as $element){
								exec('asterisk -rx "database put IN_ALLOW_'.$_POST['for_exten'].' '.$element.' 1"',$null);
							}
						}
						elseif(isset($_POST['send'],$_POST['for_exten'])){
							exec('asterisk -rx "database deltree IN_ALLOW_'.$_POST['for_exten'].'"',$null);
						}
					?>
				</fieldset>
				<fieldset class="subfield">
					<legend>Исходящие</legend>
					<?php
						if(isset($_POST['give'],$_POST['for_exten'])){
							$exec_out_3=[];
							exec('asterisk -rx "database show OUT_ALLOW_'.$_POST['for_exten'].'" | grep OUT_ALLOW_',$exec_out_3);
							foreach($exec_out_1 as $element){
								$check=(in_array('/OUT_ALLOW_'.$_POST['for_exten'].'/'.$element.'                                : 1',$exec_out_3))?'checked':'';
								echo '<label><input type="checkbox" name="granted_out[]" value="'.$element.'" '.$check.' />'.$element.'</label>';
							};
						}
						if(isset($_POST['send'],$_POST['for_exten'],$_POST['granted_out'])){
							exec('asterisk -rx "database deltree OUT_ALLOW_'.$_POST['for_exten'].'"',$null);
							foreach($_POST['granted_out'] as $element){
								exec('asterisk -rx "database put OUT_ALLOW_'.$_POST['for_exten'].' '.$element.' 1"',$null);
							}
						}
						elseif(isset($_POST['send'],$_POST['for_exten'])){
							exec('asterisk -rx "database deltree OUT_ALLOW_'.$_POST['for_exten'].'"',$null);
						}
					?>
				</fieldset>
				<div>
					<button name="give" value="ok">Получить</button>
					<button name="send" value="ok">Сохранить</button>
				</div>
			</fieldset>
		</form>
	</body>
</html>

Дополнительно в архиве есть закреплённый файл CSS-стилей и иконка.

Таким образом у нас есть интерфейс редактирования разрешений дозвона средствами внутренней базы asterisk AstDB.

Результат работы в базе

Остаётся лишь подкорректировать диалплан для работы с новыми записями. В файл

# nano /etc/asterisk/extensions_custom.conf

Внести следующте изменения в контекст [from-internal-custom]

exten => _XXX,1,GotoIf(${DB_EXISTS(IN_ALLOW_${EXTEN}/${CALLERID(num)})}?from-internal-additional,${EXTEN},1)
same => n,GotoIf(${DB_EXISTS(OUT_ALLOW_${CALLERID(num)}/${EXTEN})}?from-internal-additional,${EXTEN},1)
same => n,Busy(5)
same => n,Hangup

Из приведённых примеров видно, что на 200ый могут звонить 101,103,105,107,109. В то же время номер 200 может вызывать номера: 101-108. Таким образом реализовано ограничение внутренних звонков по номеру звонящего средствами внутренней базы AstDB.

Подписаться
Уведомить о
guest
0 комментариев
Межтекстовые Отзывы
Посмотреть все комментарии

Остались вопросы?

Я - Виталий Шелест, менеджер компании Voxlink. Хотите уточнить детали или готовы оставить заявку? Укажите номер телефона, я перезвоню в течение 3-х секунд.

VoIP оборудование


ближайшие курсы

10 доводов в пользу Asterisk

Распространяется бесплатно.

Asterisk – программное обеспечение с открытым исходным кодом, распространяется по лицензии GPL. Следовательно, установив один раз Asterisk вам не придется дополнительно платить за новых абонентов, подключение новых транков, расширение функционала и прочие лицензии. Это приближает стоимость владения станцией к нулю.

Безопасен в использовании.

Любое программное обеспечение может стать объектом интереса злоумышленников, в том числе телефонная станция. Однако, сам Asterisk, а также операционная система, на которой он работает, дают множество инструментов защиты от любых атак. При грамотной настройке безопасности у злоумышленников нет никаких шансов попасть на станцию.

Надежен в эксплуатации.

Время работы серверов некоторых наших клиентов исчисляется годами. Это значит, что Asterisk работает несколько лет, ему не требуются никакие перезагрузки или принудительные отключения. А еще это говорит о том, что в районе отличная ситуация с электроэнергией, но это уже не заслуга Asterisk.

Гибкий в настройке.

Зачастую возможности Asterisk ограничивает только фантазия пользователя. Ни один конструктор шаблонов не сравнится с Asterisk по гибкости настройки. Это позволяет решать с помощью Asterisk любые бизнес задачи, даже те, в которых выбор в его пользу не кажется изначально очевидным.

Имеет огромный функционал.

Во многом именно Asterisk показал какой должна быть современная телефонная станция. За многие годы развития функциональность Asterisk расширилась, а все основные возможности по-прежнему доступны бесплатно сразу после установки.

Интегрируется с любыми системами.

То, что Asterisk не умеет сам, он позволяет реализовать за счет интеграции. Это могут быть интеграции с коммерческими телефонными станциями, CRM, ERP системами, биллингом, сервисами колл-трекинга, колл-бэка и модулями статистики и аналитики.

Позволяет телефонизировать офис за считанные часы.

В нашей практике были проекты, реализованные за один рабочий день. Это значит, что утром к нам обращался клиент, а уже через несколько часов он пользовался новой IP-АТС. Безусловно, такая скорость редкость, ведь АТС – инструмент зарабатывания денег для многих компаний и спешка во внедрении не уместна. Но в случае острой необходимости Asterisk готов к быстрому старту.

Отличная масштабируемость.

Очень утомительно постоянно возвращаться к одному и тому же вопросу. Такое часто бывает в случае некачественного исполнения работ или выбора заведомо неподходящего бизнес-решения. С Asterisk точно не будет такой проблемы! Телефонная станция, построенная на Asterisk может быть масштабируема до немыслимых размеров. Главное – правильно подобрать оборудование.

Повышает управляемость бизнеса.

Asterisk дает не просто набор полезных функций, он повышает управляемость организации, качества и комфортности управления, а также увеличивает прозрачность бизнеса для руководства. Достичь этого можно, например, за счет автоматизации отчетов, подключения бота в Telegram, санкционированного доступа к станции из любой точки мира.

Снижает расходы на связь.

Связь между внутренними абонентами IP-АТС бесплатна всегда, независимо от их географического расположения. Также к Asterisk можно подключить любых операторов телефонии, в том числе GSM сим-карты и настроить маршрутизацию вызовов по наиболее выгодному тарифу. Всё это позволяет экономить с первых минут пользования станцией.