artem
23.05.2017
11990

Резервирование интернет-канала на маршрутизаторах Mikrotik

В этой статье будет описана настройка резервирования интернет-канала на маршрутизаторах Mikrotik. Приведённая схема резервирования подходит, также, для того случая, когда у одного или более интернет-каналов динамический IP-адрес и/или динамический шлюз (достаточно, чтобы у каждого интернет-канала был интерфейс с постоянным именем).

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

 

Исходные данные:
Интерфейс основного провайдера — pppoe-isp1 (PPPoE-клиент)
Интерфейс резервного провайдера — ether2-isp2

 

Настройка

 

Повышение distance маршрутов по умолчанию

Для начала нужно повысить distance маршрутов по умолчанию, автоматически добавляемых подключениями к провайдерам. Это делается для того, чтобы скрипт мог обнаружить и применить изменения маршрутов по умолчанию, и чтобы автоматически добавляемые маршруты не мешали резервированию.
PPPoE-подключение основного провайдера (distance 11):

/interface pppoe-client
add add-default-route=yes default-route-distance=11 disabled=no interface=ether1-isp1 keepalive-timeout=disabled name=pppoe-isp1 password=secret_password user=user1 allow=mschap2

DHCP-клиент на интерфейсе резервного провайдера (distance 12):

/ip dhcp-client
add default-route-distance=12 disabled=no interface=ether2-isp2 use-peer-dns=no

Описанное выше действие не нужно выполнять для провайдеров со статическим шлюзом по умолчанию.

 

Маркировка трафика

Нужно заставить маршрутизатор отправлять все пакеты соединения через тот интерфейс, через который пришел первый пакет соединения. Для этого добавляем правила в таблицу mangle (комментарии «ISP1 mark conn», «ISP2 mark conn»):

/ip firewall mangle
add comment=»ISP1 mark conn» action=mark-connection chain=prerouting connection-state=new in-interface=pppoe-isp1 new-connection-mark=from-ISP1
add comment=»ISP2 mark conn» action=mark-connection chain=prerouting connection-state=new in-interface=ether2-isp2 new-connection-mark=from-ISP2
add action=mark-routing chain=prerouting connection-mark=from-ISP1 new-routing-mark=to-ISP1
add action=mark-routing chain=prerouting connection-mark=from-ISP2 new-routing-mark=to-ISP2
 
add action=mark-routing chain=output connection-mark=from-ISP1 new-routing-mark=to-ISP1
add action=mark-routing chain=output connection-mark=from-ISP2 new-routing-mark=to-ISP2
add action=mark-routing chain=output comment=»ISP1 mangle» new-routing-mark=to-ISP1 src-address=1.1.1.10
add action=mark-routing chain=output comment=»ISP2 mangle» new-routing-mark=to-ISP2 src-address=2.2.2.20

Для правил в цепочке output, проставляющих routing mark в зависимости от IP-адреса отправителя, проставляем комментарии «ISP1 mangle» и «ISP2 mangle», чтобы скрипт мог находить их. IP-адреса в src-address можно указать любые, т.к. скрипт заменит их при первом выполнении (здесь и далее будет использоваться 1.1.1.10 вместо IP-адреса основного провайдера, 2.2.2.20 вместо IP-адреса резервного провайдера).

 

Правила NAT

Добавляем NAT-правила для провайдеров (здесь используются комментарии «ISP1 NAT» и «ISP2 NAT»):

/ip firewall nat
add action=src-nat chain=srcnat comment=»ISP1 NAT» out-interface=pppoe-isp1 to-addresses=1.1.1.10
add action=src-nat chain=srcnat comment=»ISP2 NAT» out-interface=ether2-isp2 to-addresses=2.2.2.20

 

Маршруты и правила маршрутизации

Добавляем маршруты и правила маршрутизации.

/ip route
# Отдельные таблицы маршрутов для провайдеров, в каждую таблицу будет входить только маршрут по умолчанию
# (комментарии «ISP1 route» и «ISP2 route», 1.1.1.1 и 2.2.2.1 — шлюзы по умолчанию):
add comment=»ISP1 route» distance=1 gateway=1.1.1.1 routing-mark=ISP1
add comment=»ISP2 route» distance=1 gateway=2.2.2.1 routing-mark=ISP2
 
# Маршруты по умолчанию основной и резервный с distance 1 и 2 соответственно (комментарии «GW1» и «GW2»).
add comment=GW1 distance=1 gateway=1.1.1.1
add comment=GW2 distance=2 gateway=2.2.2.1
/ip route rule
 
# Правила маршрутизации для отправки пакетов с внешнего IP-адреса через соответствующий маршрут (комментарии «ISP1 rule» и «ISP2 rule»).
# Пакеты GRE-туннелей не будут уходить через правильный интерфейс без этих правил.
add comment=»ISP1 rule» src-address=1.1.1.10/32 table=ISP1
add comment=»ISP2 rule» src-address=2.2.2.20/32 table=ISP2
 
# Правила для маршрутизации пакетов, адресованных в локальные сети, через таблицу main.
# Благодаря этим правилам, в таблицах маршрутов ISP1 и ISP2 достаточно указать только маршруты по умолчанию.
add dst-address=192.168.0.0/16 table=main
add dst-address=10.0.0.0/8 table=main
add dst-address=172.16.0.0/12 table=main
 
# Правила для маршрутизации пакетов с метками провайдеров через правильную таблицу маршрутов.
add routing-mark=to-ISP1 table=ISP1
add routing-mark=to-ISP2 table=ISP2

 

Запрет отправки исходящих пакетов с неправильным IP-адресом отправителя через интерфейсы провайдеров

Правила, описанные в этом разделе нужны для решения проблемы, возникающей при потере линка на интерфейсе одного из провайдеров. В этом случае трафик с фиксированным адресом отправителя (такой как GRE), уходящий через интерфейс провайдера, на котором потерян линк, начнёт уходить через интерфейс другого провайдера, проходя при этом NAT. Это создаст проблему — после восстановления линка трафик продолжит натироваться, т.к. информация о NAT будет добавлена в запись о соединении в таблице соединений, из-за чего соединение не будет функционировать до удаления его записи из таблицы соединений.

 

Сперва нужно создать списки адресов с адресами, с которых разрешено отправлять исходящие пакеты через каждый из интерфейсов провайдеров (комментарии «ISP1 src IP» и «ISP2 src IP»).

Списки адресов нужны на тот случай, если на интерфейсе провайдера будет более одного IP-адреса — скрипт будет изменять только IP-адрес в записи с соответствующим комментарием, остальные IP-адреса интерфейса нужно добавлять в список адресов без комментария или с другими комментариями.

/ip firewall address-list
add address=1.1.1.10 comment=»ISP1 src IP» list=ISP1_src_IPs
add address=2.2.2.20 comment=»ISP2 src IP» list=ISP2_src_IPs

 

Теперь нужно добавить правила, сбрасывающие исходящий трафик на интерфейсах провайдеров с IP-адресов, отличных от разрешённых (комментарии «ISP1 restrict output» и «ISP2 restrict output»).

/ip firewall filter
add action=drop chain=output comment=»ISP1 restrict output» out-interface=pppoe-isp1 src-address-list=!ISP1_src_IPs
add action=drop chain=output comment=»ISP2 restrict output» out-interface=ether2-isp2 src-address-list=!ISP2_src_IPs

 

Скрипт для переключения провайдеров

Добавляем скрипт в system scripts через консоль или GUI, в данном примере имя скрипта — «upd_route_rules». Для скрипта должны быть включены политики read, write и test.
В переменной Iface1 нужно указать имя интерфейса основного провайдера, в переменной Iface2 — имя интерфейса резервного провайдера. Если потом понадобится поменять состав интерфейсов провайдеров или их приоритеты, нужно отключить периодическое выполнение скрипта (описано в конце статьи), указать для переменных Iface1 и Iface2 новые значения и выполнить скрипт, остальные изменения будут внесены автоматически (после этого нужно снова включить периодическое выполнение скрипта).
В массиве PingTargets можно указать свой список IP-адресов для тестирования доступности провайдера.

:local Iface1 «pppoe-isp1»
:local Iface2 «ether2-isp2»
:local Iface1Disabled true
:local Iface2Disabled true
:local GW1 «»
:local GW2 «»
:local IP1 «»
:local IP2 «»
:local IP1changed false
:local IP2changed false
 
:do {
:set Iface1Disabled [/interface get [/interface find name=$Iface1] disabled]
} on-error={}
:do {
:set Iface2Disabled [/interface get [/interface find name=$Iface2] disabled]
} on-error={}
 
:foreach i in=[/ip route find gateway-status~»reachable .* $Iface1$» and dst-address=»0.0.0.0/0″] do={
:if ([/ip route get $i comment] = «») do={:set GW1 [/ip route get $i gateway]}
}
 
:foreach i in=[/ip route find gateway-status~»reachable .* $Iface2$» and dst-address=»0.0.0.0/0″] do={
:if ([/ip route get $i comment] = «») do={:set GW2 [/ip route get $i gateway]}
}
 
#:put $GW1
#:put $GW2
:local h
:local hID
 
:if («$GW1» != «») do={
:do {
:foreach i in=[/ip route find comment=»ISP1 route»] do={
:if ($GW1 != [/ip route get $i gateway]) do={ /ip route set $i gateway=$GW1; :put «updated ISP1 route»; /log info «updated ISP1 route» }
}
} on-error={}
:do {
:set h [/ip route find comment=»GW1″]
:if ($GW1 != [/ip route get $h gateway]) do={ /ip route set $h gateway=$GW1; /log info «updated GW1» }
} on-error={}
}
 
:if («$GW2» != «») do={
:do {
:foreach i in=[/ip route find comment=»ISP2 route»] do={
:if ($GW2 != [/ip route get $i gateway]) do={ /ip route set $i gateway=$GW2; :put «updated ISP2 route»; /log info «updated ISP2 route» }
}
} on-error={}
:do {
:set h [/ip route find comment=»GW2″]
:if ($GW2 != [/ip route get $h gateway]) do={ /ip route set $h gateway=$GW2; /log info «updated GW2» }
} on-error={}
}
 
:foreach i in=[/ip address find interface=$Iface1] do={
:if ([/ip address get $i comment] ~ «secondary» or [/ip address get $i disabled]) do={} else={:set IP1 [/ip address get $i address]}
}
 
:foreach i in=[/ip address find interface=$Iface2] do={
:if ([/ip address get $i comment] ~ «secondary» or [/ip address get $i disabled]) do={} else={:set IP2 [/ip address get $i address]}
}
 
#:put $IP1
#:put $IP2
:local pos «»
:local curIP «»
:local curIFACE «»
:local curSAIP
 
:if («$IP1» != «») do={
:set pos [:find «$IP1» «/»]
:if ($pos >= 0) do={ :set IP1 [:pick «$IP1″ 0 $pos] }
:do {
:set h [/ip route rule find comment=»ISP1 rule»]
:set curIP [/ip route rule get $h src-address]
:set pos [:find «$curIP» «/»]
:if ($pos >= 0) do={ :set curIP [:pick «$curIP» 0 $pos] }
:if («$IP1» != «$curIP») do={ /ip route rule set $h src-address=$IP1; :put «updated ISP1 rule»; /log info «updated ISP1 rule»; :set IP1changed true }
} on-error={}
 
:do {
:set h [/ip firewall mangle find comment=»ISP1 mangle»]
:set curIP [/ip firewall mangle get $h src-address]
:set pos [:find «$curIP» «/»]
:if ($pos >= 0) do={ :set curIP [:pick «$curIP» 0 $pos] }
:if («$IP1» != «$curIP») do={ /ip firewall mangle set $h src-address=$IP1; :put «updated ISP1 mangle»; /log info «updated ISP1 mangle»; :set IP1changed true }
} on-error={}
 
:do {
:set h [/ip firewall nat find comment=»ISP1 NAT»]
:set curIP [/ip firewall nat get $h to-addresses]
:if («$IP1» != «$curIP») do={ /ip firewall nat set $h to-addresses=$IP1; :put «updated ISP1 NAT»; /log info «updated ISP1 NAT»; :set IP1changed true }
:set curIFACE [/ip firewall nat get $h out-interface]
:if («$Iface1» != «$curIFACE») do={ /ip firewall nat set $h out-interface=$Iface1; :put «updated ISP1 NAT interface»; /log info «updated ISP1 NAT interface» }
} on-error={}
 
:do {
:foreach h in=[/ip ipsec policy find comment=»ISP1 IPSec policy»] do={
:set curSAIP [/ip ipsec policy get $h sa-src-address]
:set curIP [/ip ipsec policy get $h src-address]
:set pos [:find «$curIP» «/»]
:if ($pos >= 0) do={ :set curIP [:pick «$curIP» 0 $pos] }
:if («$IP1» != «$curSAIP» || «$IP1» != «$curIP») do={ /ip ipsec policy set $h sa-src-address=$IP1 src-address=»$IP1/32″; :put «updated ISP1 IPSec policy»; /log info «ISP1 IPSec policy» }
}
} on-error={}
 
:do {
:foreach h in=[/interface gre find comment=»ISP1 GRE»] do={

:set curIP [/interface gre get $h local-address]
:if («$IP1» != «$curIP») do={ /interface gre set $h local-address=$IP1; :put «updated ISP1 GRE»; /log info «updated ISP1 GRE» }
}
} on-error={}
 
:do {
:set h [/ip firewall address-list find comment=»ISP1 src IP»]
:set curIP [/ip firewall address-list get $h address]
:if («$IP1» != «$curIP») do={ /ip firewall address-list set $h address=$IP1; :put «updated ISP1 src IP in address list»; /log info «updated ISP1 src IP in address list»; :set IP1changed true }
} on-error={}
 
:do {
:set h [/ip firewall filter find comment=»ISP1 restrict output»]
:set curIFACE [/ip firewall filter get $h out-interface]
:if («$Iface1» != «$curIFACE») do={ /ip firewall filter set $h out-interface=$Iface1; :put «updated ISP1 restrict output interface»; /log info «updated ISP1 restrict output interface» }
} on-error={}
}
 
:do {
:set h [/ip firewall mangle find comment=»ISP1 mark conn»]
:set curIFACE [/ip firewall mangle get $h in-interface]
:if («$Iface1» != «$curIFACE») do={ /ip firewall mangle set $h in-interface=$Iface1; :put «updated ISP1 mark conn interface»; /log info «updated ISP1 mark conn interface» }
} on-error={}
 
:if («$IP2» != «») do={
:set pos [:find «$IP2» «/»]
:if ($pos >= 0) do={ :set IP2 [:pick «$IP2″ 0 $pos] }
:do {
:set h [/ip route rule find comment=»ISP2 rule»]
:set curIP [/ip route rule get $h src-address]
:set pos [:find «$curIP» «/»]
:if ($pos >= 0) do={ :set curIP [:pick «$curIP» 0 $pos] }
:if («$IP2» != «$curIP») do={ /ip route rule set $h src-address=$IP2; :put «updated ISP2 rule»; /log info «updated ISP2 rule»; :set IP2changed true }
} on-error={}
 
:do {
:set h [/ip firewall mangle find comment=»ISP2 mangle»]
:set curIP [/ip firewall mangle get $h src-address]
:set pos [:find «$curIP» «/»]
:if ($pos >= 0) do={ :set curIP [:pick «$curIP» 0 $pos] }
:if («$IP2» != «$curIP») do={ /ip firewall mangle set $h src-address=$IP2; :put «updated ISP2 mangle»; /log info «updated ISP2 mangle»; :set IP2changed true }
} on-error={}
 
:do {
:set h [/ip firewall nat find comment=»ISP2 NAT»]
:set curIP [/ip firewall nat get $h to-addresses]
:if («$IP2» != «$curIP») do={ /ip firewall nat set $h to-addresses=$IP2; :put «updated ISP2 NAT»; /log info «updated ISP2 NAT»; :set IP2changed true }
:set curIFACE [/ip firewall nat get $h out-interface]
:if («$Iface2» != «$curIFACE») do={ /ip firewall nat set $h out-interface=$Iface2; :put «updated ISP2 NAT interface»; /log info «updated ISP2 NAT interface» }
} on-error={}
 
:do {
:foreach h in=[/ip ipsec policy find comment=»ISP2 IPSec policy»] do={
:set curSAIP [/ip ipsec policy get $h sa-src-address]
:set curIP [/ip ipsec policy get $h src-address]
:set pos [:find «$curIP» «/»]
:if ($pos >= 0) do={ :set curIP [:pick «$curIP» 0 $pos] }
:if («$IP2» != «$curSAIP» || «$IP2» != «$curIP») do={ /ip ipsec policy set $h sa-src-address=$IP2 src-address=»$IP2/32″; :put «updated ISP2 IPSec policy»; /log info «ISP2 IPSec policy» }
}
} on-error={}
 
:do {
:foreach h in=[/interface gre find comment=»ISP2 GRE»] do={
:set curIP [/interface gre get $h local-address]
:if («$IP2» != «$curIP») do={ /interface gre set $h local-address=$IP2; :put «updated ISP2 GRE»; /log info «updated ISP2 GRE» }
}
} on-error={}
 
:do {
:set h [/ip firewall address-list find comment=»ISP2 src IP»]
:set curIP [/ip firewall address-list get $h address]
:if («$IP2» != «$curIP») do={ /ip firewall address-list set $h address=$IP2; :put «updated ISP2 src IP in address list»; /log info «updated ISP2 src IP in address list»; :set IP2changed true }
} on-error={}
 
:do {
:set h [/ip firewall filter find comment=»ISP2 restrict output»]
:set curIFACE [/ip firewall filter get $h out-interface]
:if («$Iface2» != «$curIFACE») do={ /ip firewall filter set $h out-interface=$Iface2; :put «updated ISP2 restrict output interface»; /log info «updated ISP2 restrict output interface» }
} on-error={}
}
 
:do {
:set h [/ip firewall mangle find comment=»ISP2 mark conn»]
:set curIFACE [/ip firewall mangle get $h in-interface]
:if («$Iface2» != «$curIFACE») do={ /ip firewall mangle set $h in-interface=$Iface2; :put «updated ISP2 mark conn interface»; /log info «updated ISP2 mark conn interface» }
} on-error={}
 
#:put $IP1
#:put $IP2
#:put $IP1changed
#:put $IP2changed
 
:local PingCount 1
:local PingTargets {77.88.8.8; 8.8.8.8; 94.100.180.200; 208.67.222.222}
:local GW1InetOk false
:local GW2InetOk false
:local GW1Pings 0
:local GW2Pings 0
 
:foreach host in=$PingTargets do={
:if (!$Iface1Disabled) do={
:local res [/ping $host count=$PingCount interface=$Iface1]
:set GW1Pings ($GW1Pings + $res)
}
:if (!$Iface2Disabled) do={
:local res [/ping $host count=$PingCount interface=$Iface2]
:set GW2Pings ($GW2Pings + $res)
}
:delay 1
}
:set GW1InetOk ($GW1Pings >= 1)
:set GW2InetOk ($GW2Pings >= 1)
 
:local GW1h [/ip route find comment=»GW1″]
:local GW2h [/ip route find comment=»GW2″]
:local GW1distance [/ip route get $GW1h distance]
:local GW2distance [/ip route get $GW2h distance]
 
:if ($GW1InetOk && ($GW1distance >= $GW2distance)) do={
/ip route set $GW1h distance=1
/ip route set $GW2h distance=2
/ip firewall connection remove [find dst-address ~ «.*:5060»]
/ip firewall connection remove [find dst-address ~ «.*:4569»]
/ip firewall connection remove [find dst-address ~ «.*:4500»]
/ip firewall connection remove [find dst-address ~ «.*:500»]
/ip firewall connection remove [find dst-address ~ «.*:1701″]
/ip firewall connection remove [find protocol=»ospf»]
:put «Switched to GW1»
/log info «Switched to GW1»
}
 
:if (!$GW1InetOk && $GW2InetOk && ($GW2distance >= $GW1distance)) do={
/ip route set $GW1h distance=2
/ip route set $GW2h distance=1
/ip firewall connection remove [find dst-address ~ «.*:5060»]
/ip firewall connection remove [find dst-address ~ «.*:4569»]
/ip firewall connection remove [find dst-address ~ «.*:4500»]
/ip firewall connection remove [find dst-address ~ «.*:500»]
/ip firewall connection remove [find dst-address ~ «.*:1701″]
/ip firewall connection remove [find protocol=»ospf»]
:put «Switched to GW2»
/log info «Switched to GW2»
}

 

ПРИМЕЧАНИЯ

1) В скрипте также упоминаются комментарии «ISP1 GRE», «ISP2 GRE», «ISP1 IPSec policy» и «ISP2 IPSec policy», эти комментарии нужны для обновления локальных IP-адресов в настройках GRE-туннелей и политик IPSec. Их использование будет описано в одной из последующих статей.

2) Скрипт берёт первый IP-адрес, настроенный на интерфейсе провайдера и не имеющий комментария. Если вы используете более одного IP-адреса на каком-либо интернет-канале, отметьте все кроме одного каким-либо комментарием (например «secondary»).

 

Лучше сделать тестовый запус скрипта (и включить перед этим safe mode):

/system script run upd_route_rules

При запуске скрипт должен актуализировать настройки провайдеров и вывести уведомления о всех изменённых пунктах.

Если скрипт отрабатывает правильно, можно добавлять периодическое выполнение скрипта, например, раз в 45 секунд.

/system scheduler
add interval=45s name=upd_route_rules on-event=upd_route_rules policy=read,write,test start-date=jan/01/1970 start-time=00:00:00  

Книга 101 функция Asterisk
Познакомьтесь с возможностями Asterisk. Найдите инструменты, которые помогут вашей компании развиваться.
Скачать книгу
Подписаться
Уведомить о
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 сим-карты и настроить маршрутизацию вызовов по наиболее выгодному тарифу. Всё это позволяет экономить с первых минут пользования станцией.