Телефония Asterisk за NAT и два провайдера

 30-08-2018 14:09   11146  


Задача:

  1. Наладить стабильную работу телефонной станции на базе Asterisk, расположенной в локальной сети клиента за маршрутизатором Микротик с двумя интернет каналами (основной и резервный).


1.    Подключение абонентских SIP-трубок к АТС обычно не вызывает затруднений, т.к. они расположены либо в одной локальной сети с АТС, либо подключаются через VPN-канал. Основная задача - это настроить SIP-trunk каналы до поставщиков телефонных услуг, чтобы абоненты могли не только общаться между собой в рамках АТС, но и звонить на городские, мобильные и международные номера. Подключение таких каналов, как правило, происходит через существующий интернет-канал. Для этого необходимо настроить правила "проброса" портов в NAT и фаервол, чтобы клиентская АТС могла взаимодействовать с телефонной станцией провайдера.

Правила для "проброса" UDP портов 5060 и 10000-20000 к серверу Asterisk на примере маршрутизатора Микротик:

/ip firewall filter add action=accept chain=forward dst-address=192.168.1.110 dst-port=5060,10000-20000 protocol=udp in-interface=ether1
/ip firewall nat add action=dst-nat chain=dstnat dst-port=5060,10000-20000 in-interface=ether1 protocol=udp to-addresses=192.168.1.110

192.168.1.110 - IP адрес телефонного сервера Asterisk, а ether1 - интерфейс подключения к интернету. Если у вас два провайдера или более, то соответственно необходимо добавить правила для каждого подключения к сети интернет.

 

2.     В нашем случае у клиента подключено два интернет-провайдера и необходимо, чтобы телефония могла работать через оба канала. Обратим внимание на файл с настройками sip.conf:

[general]
nat = yes
externip = 10.20.30.40
localnet = 192.168.1.0/24
allowsubscribe = yes
allowguest = no
alwaysauthreject = yes
notifyringing = yes
notifyhold = yes
limitonpeers = yes
qualify = yes

Можно заметить, что в значении externip указывается внешний IP-адрес нашего интернет соединения. Этот параметр модифицирует SIP-заголовок, сообщая провайдерскому SIP-серверу адрес на который надо слать ответы. Что делать если IP-адреса у нас два, т.к. два интернет канала.

Для решения этой задачи был написан скрипт на языке Python:

import urllib.request
from subprocess import call
import os
import smtplib

username = "yourmail@gmail.com"
password = "password"
recepient = "events@multeam.ru"
body = "Alert! Pereklyuchenie kanala"

def send_email():
 mail = smtplib.SMTP('smtp.gmail.com', 587)
 mail.ehlo()
 mail.starttls()
 mail.login(username,password)
 mail.sendmail(username, recepient, body)
 mail.close()

external_ip = urllib.request.urlopen('http://ident.me').read().decode('utf8')
s = open('/etc/asterisk/sip.conf').read().split('\n')[8]
ip = (s.split(' = '))[1]

if external_ip != ip:
  new_ip = s.replace(ip, external_ip)
  f = open('/etc/asterisk/sip.conf')
  lines = f.readlines()
  lines[8] = new_ip + '\n'
  f.close()
  save_changes = open('/etc/asterisk/sip.conf', 'w')
  save_changes.writelines(lines)
  save_changes.close()
  call(["/usr/sbin/asterisk", "-rx", "sip reload"])
  send_email()
else:
  pass

Cкрипт выполняется по заданию cron каждые 5 минут:

[visor@localhost asterisk]# crontab -l
*/5 * * * * /usr/bin/python3.6 /home/asterisk/SIP.py > /tmp/SIP.log 2>&1

Логика скрипта очень простая: каждые 5 минут мы проверяем свой внешний IP-адрес с помощью ресурса http://ident.me и храним это значение в переменной external_ip. Также мы храним IP-адрес externip = 10.20.30.40 (номер строки известен) из файла конфигурации  /etc/asterisk/sip.conf. Сравниваем эти значения: если они равны - ничего не делаем, если внешний IP изменился (произошло переключение канала), то перезаписываем наш новый IP-адрес в конфигурационный файл sip.conf и даем команду Asterisk перечитать его. После этого отправляем уведомление на E-mail, что произошло такое событие.

3.    Дополнительно на маршрутизаторе Микротик отключим SIP ALG  и в скрипт переключения между интернет-каналами добавим сброс зависших сессий:

/ip firewall service-port disable sip
:foreach i in=[/ip firewall connection find dst-address~":5060" protocol~"udp"] do={ /ip firewall connection remove $i }

 



Связаться с нами:

+7(812)602-75-74