30-08-2018 14:09 12125
Задача:
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 }