Raspberry Pi + FreeBPX(asterisk) + Mikrotik = АТС мини

от автора

Настройка «с нуля»

  • Введение, начало

  • Установка и настройка FreePBX

  • Подключение GSM модема

  • Настройка fail2ban

  • Настройка Mikrotik

Введение, начало

В небольшой офис потребовалась АТС, для звонков по России и между сотрудниками. Был выбор между использованием готовых решений от SIP провайдеров и самодельной личной АТС. У каждой стороны есть свои плюсы и минусы. Так как офис только запускался, сотрудников мало, тотальный режим экономии, то от провайдеров отказался — абонентская плата за номер (при том что номер дается городской, к которому сложно привязать мессенджеры, мобильные номера от провайдера у клиентов не вызывают доверия и так же имеют проблемы с привязкой к мессенджерам) и тарифы на звонки на мобильные номера клиентов у всех не менее 1,5 руб./мин.

Т.к. в наличии был не используемый Raspberry Pi 3B+, то решено было использовать его в качестве АТС с Asterisk. MicroSD карта, от 8Гб, желательно 16Гб для установки системы. Были попытки установки голой версии с нуля по различным туториалам из сети, но во всех постоянно были какие то проблемы, т.к. они все написаны от 2 до 10 лет назад, на быстрый старт они не сработали.

Так же для автономной работы без зависимости от провайдеров нужен USB модем с поддержкой голосовых вызовов, есть списки нормально работающих модемов (предварительно разблокированных по инструкциям из 4ПДА), у меня работает Huawei E1550.

Для безопасной работы в сети использую Mikrotik RB951G, теоретически можно любой, OS у них одна и та же (основ настройки роутера здесь не будет, подразумевается, что у вас интернет через него уже работает). Так же нужен интернет провайдер с возможностью предоставить статический или динамический IP адрес, что бы можно было подключатся к АТС из любого места сети интернет. Через приватные адреса у меня не получилось работать (через мобильные сети тоже, они все предоставляют адрес, к которому нет подключения снаружи, да же через DDNS сервисы).

Установка и настройка FreePBX

Сохраняем себе в закладки сайт http://www.raspberry-asterisk.org/ , там скачиваем образ системы raspbx-10-10-2020.zip. Распаковываем архив, если для записи используется программа Win32DiskImager, можно без распаковки и использовать для записи, например, BalenaItcher. Записываем на компьютер скачанный образ на карту microSd, записанную карту вставляем в raspberry, подключаем кабели (сеть к роутеру, питание), включаем и ждем загрузки, монитор не нужен. В роутере в разделе ip-dhcp server-leases смотрим назначенный адрес нашей АТС, это нужно будет для подключения по ssh.

В браузере набираем http://raspbx/, проходим первоначальную регистрацию, назначение имени и пароля администратора FreePBX, желательно сложный защищенный, если нет желания все снова настраивать восстанавливать. В конечном итоге после входа должно получится так:

Так же подключаемся через Putty к asterisk, логин и пароль пока стандартные root/raspberry. Меняем пароль по умолчанию:

passwd

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

Так как система основана на Debian, то здесь работают стандартные команды. Обновляем систему, настраиваем свою временную зону, устанавливаем модуль для работы с USB модемом, файловый навигатор MC для удобства:

raspbx-upgrade configure-timezone install-dongle apt install mc

При установке модуля dongle указываем реальный номер, который будет использоваться в модеме (у оператора сотовой связи выбираем тариф с пакетом минут на звонки по России).

Так как у меня не получилось запустить систему на современном драйвере pjsip (в телефонах тишина), то все настройки будут на legacy sip, работает на всех абонентских устройствах.

В браузере переходим по порядку основные настройки:

Пояснение: 3-4 для безопасности, 5 - определение адреса внешнего IP, 6 - настройки вашей локальной сети, 7 - сужаем диапазон портов, так как сотрудников мало, чуть ниже выбираем стандартные кодеки ulaw alaw gsm, 9 - по завершению нажимаем на Apply config, ждем обновления конфигурации.
Пояснение: 3-4 для безопасности, 5 — определение адреса внешнего IP, 6 — настройки вашей локальной сети, 7 — сужаем диапазон портов, так как сотрудников мало, чуть ниже выбираем стандартные кодеки ulaw alaw gsm, 9 — по завершению нажимаем на Apply config, ждем обновления конфигурации.

Переходим на закладку SIP legacy setting:

1,2 -меняем стандартные значения портов на свои, 3 - пусть будет, пригодится, 4 - для безопасности  при подборах паролей.
1,2 -меняем стандартные значения портов на свои, 3 — пусть будет, пригодится, 4 — для безопасности при подборах паролей.

Так же меняем стандартное значение порта на вкладке PJSIP, все сохраняем и применяем ( submit & apply config).

Настраиваем extension (это номера для подключения абонентов):

настроили абонентов, Submit & Apply config.

Настройка trunk для модема:

6 -  максимальное число каналов - ставим 1
6 — максимальное число каналов — ставим 1

Маршрут для входящих звонков:

Маршрут для исходящих звонков:

Шаблоны для набранных номеров, здесь можно ограничить направление звонков, местные, межгород, международные. Звонок будет работать, если совпадет с набранным шаблоном.
Шаблоны для набранных номеров, здесь можно ограничить направление звонков, местные, межгород, международные. Звонок будет работать, если совпадет с набранным шаблоном.

С графической частью закончили. Главное не забывать после каждых действий Submit & Apply Config, что бы внесенные изменения сохранялись.

Подключение GSM модема

Здесь собранная копипаста из разных источников:

Тестированные модемы:
 Предварительно на компьютере перевести GSM-модем в режим работы «только модем» ( AT^U2DIAG=0 ) и в режим только 2G (AT^SYSCFG=13,1,3fffffff,0,0 ) с помощь Putty или любым другим способом, можно и через raspberry, но и так здесь большой объем.

  • E171 — ОК

  • E1550 — ОК

  • E150 — Голос только в одну сторону

  • E3131 — Работают не стабильно, при исходящих голос только в одну сторону

  • E352 — Нет голосовых функций 

    Подключаем GSM-модем HUAWEI E1550, проверяем появились ли устройства ttyUSB*:

ls -al /dev | grep ttyUSB
полученный ответ команды

crw-rw—- 1 root dialout 188, 0 фев 27 11:34 ttyUSB0

crw-rw—- 1 root dialout 188, 1 фев 27 11:33 ttyUSB1

crw-rw—- 1 root dialout 188, 2 фев 27 12:37 ttyUSB2

Чтобы при подключении GSM-модема, Asterisk имел доступ к нему, необходимо устройству назначить владельца asterisk и группу dialout. Создаем файл (nano /etc/udev/rules.d/92-dongle.rules) со следующим содержимым:

KERNEL==»ttyUSB*», MODE=»0666″, OWNER=»asterisk», GROUP=»dialout»

Перезагружаем raspberry командой reboot и переподключаемся к атс с помощью Putty.

Настройка файла dongle.conf ( nano /etc/asterisk/dongle.conf ) — проверяем параметр exten и прописываем imei модема, остальное можно не трогать:

initstate=start                 ; specified initial state of device, must be one of 'stop' 'start' 'remote'                                 ;   'remove' same as 'disable=yes'  exten=+79234567890   ; Проверяем наш номер сим карты, он связан с ранее настроенными  dtmf=relax                      ; control of incoming DTMF detection, possible values:                                 ;   off    - off DTMF tones detection, voice data passed to asterisk unalte$                                 ;              use this value for gateways or if not use DTMF for AVR or in$                                 ;   inband - do DTMF tones detection                                 ;   relax  - like inband but with relaxdtmf option                                 ;  default is 'relax' by compatibility reason  ; dongle required settings [dongle0] audio=/dev/ttyUSB1              ; tty port for audio connection; no default value data=/dev/ttyUSB2               ; tty port for AT commands; no default value  imei=351234567898991  ; ПРОПИСЫВАЕМ IMEI модема ;imsi=123456789012345 

В консоли asterisk, перечитываем конфигурацию chan_dongle и проверяем состояние устройства. Если все было сделано правильно, то подключение к GSM-модему будет осуществлено и устройство будет отображаться в консоли asterisk:

root@raspbx:/# asterisk -rv raspbx*CLI> dongle show devices  ID           Group State      RSSI Mode Submode Provider Name  Model      Firmware          IMEI             IMSI             Number dongle0      0     Free       26   3    3       MegaFon        E1550      11.608.14.15.311  35*******  2**************3  Unknown

Настройка файла конфигурации для звонков и смс (настраивал только входящие смс с переадресацией на настроенный extension) :

nano /etc/asterisk/extensions_custom.conf  [from-trunk-dongle] ; можно раскомментировать, тогда смс будут записываться в файл sms.txt, смотреть потом в логах ;exten => sms,1,Verbose(Incoming SMS from ${CALLERID(num)} ${BASE64_DECODE(${SMS_BASE64})}) ;exten => sms,n,Set(FILE(/var/log/asterisk/sms.txt,,,a)=${STRFTIME(${EPOCH},,%Y-%m-%d %H:%M:%S)} - ${DONGLE$ ;exten => sms,n,System(echo >> /var/log/asterisk/sms.txt) ;exten => sms,n,Hangup()  exten => _.,1,Set(CALLERID(name)=${CALLERID(num)}) exten => _.,n,Goto(from-trunk,${EXTEN},1)  ; закомментировать, если выше было раскомментировано exten => sms,1,Set(MESSAGE(body)=${BASE64_DECODE(${SMS_BASE64})}) exten => sms,n,System(echo '${STRFTIME(${EPOCH},,%Y-%m-%d %H:%M:%S)} - ${DONGLENAME} - ${CALLERID(num)}: ${$ exten => sms,n,Set(MESSAGE(from)="${CALLERID(num)}" <${CALLERID(num)}>) exten => sms,n,Set(CALLERID(name)=${CALLERID(num)}) exten => sms,n,Verbose(1,${MESSAGE(from)}) exten => sms,n,MessageSend(sip:250,${MESSAGE(from)}) ; Прописываем куда пересылать входящие сообщения - на номер 250 exten => sms,n,Hangup()   exten => ussd,1,Verbose(Incoming USSD: ${BASE64_DECODE(${USSD_BASE64})}) exten => ussd,n,System(echo '${STRFTIME(${EPOCH},,%Y-%m-%d %H:%M:%S)} - ${DONGLENAME}: ${BASE64_DECODE(${US$ exten => ussd,n,Hangup() 

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

Настраиваем защиту asterisk freepbx с помощью fail2ban (By @UKVoIPForums )

Полноценных русскоязычных гайдов для начинающих не нашел, есть на английском форуме:

install-fail2ban 

Создаем тюрьму:

sudo nano /etc/fail2ban/jail.local
Копируем содержимое в файл jail.local
[DEFAULT] # "ignoreip" can be an IP address, a CIDR mask or a DNS host. Fail2ban will not                           # ban a host which matches an address in this list. Several addresses can be                              # defined using space separator.                                                                           ignoreip = 127.0.0.1/8 ::1  [asterisk] enabled   = true filter    = asterisk action    = iptables-asterisk[name=asterisk] logpath   = /var/log/asterisk/security_log bantime   = 31536000 findtime  = 86400 maxretry  = 3  [sshd] enabled   = true port      = ssh filter    = sshd logpath   = /var/log/auth.log banaction = iptables-allports bantime   = 31536000 findtime  = 86400 maxretry  = 3  [freepbx] enabled   = true port      = http,https filter    = freepbx logpath   = /var/log/asterisk/freepbx_security.log bantime   = 31536000 findtime  = 86400 maxretry  = 3

Еще 6 файлов конфигурации нужно создать/изменить, поехали:

sudo nano /etc/fail2ban/filter.d/freepbx.conf
1. Копируем содержимое в файл freepbx.conf
[INCLUDES] before = common.conf  [Definition] datepattern = ^\[%%Y-%%b-%%d %%H:%%M:%%S\]  failregex = \[freepbx_security\.NOTICE\]: Authentication failure for .* from <HOST>
sudo nano /etc/fail2ban/filter.d/asterisk.conf
2. Копируем содержимое в файл asterisk.conf, на всякий случай скопируйте существующее содержимое оригинального файла
# Fail2Ban configuration file # # # $Revision: 251 $ #  [INCLUDES]  # Read common prefixes. If any customizations available -- read them from # common.local before = common.conf  [Definition]  #_daemon = asterisk  # Option:  failregex # Notes.:  regex to match the password failures messages in the logfile. The #          host must be matched by a group named "host". The tag "<HOST>" can #          be used for standard IP/hostname matching and is only an alias for #          (?:::f{4,6}:)?(?P<host>\S+) # Values:  TEXT # # Asterisk 1.8 uses Host:Port format which is reflected here  failregex = NOTICE.* .*: Registration from '.*' failed for '<HOST>:.*' - Wrong password         NOTICE.* .*: Registration from '.*' failed for '<HOST>:.*' - No matching peer found         NOTICE.* .*: Registration from '.*' failed for '<HOST>:.*' - Username/auth name mismatch         NOTICE.* .*: Registration from '.*' failed for '<HOST>:.*' - Device does not match ACL         NOTICE.* .*: Registration from '.*' failed for '<HOST>:.*' - Peer is not supposed to register         NOTICE.* .*: Registration from '.*' failed for '<HOST>:.*' - ACL error (permit/deny)         NOTICE.* .*: Registration from '.*' failed for '<HOST>:.*' - Device does not match ACL         NOTICE.* .*: Registration from '\".*\".*' failed for '<HOST>:.*' - No matching peer found         NOTICE.* .*: Registration from '\".*\".*' failed for '<HOST>:.*' - Wrong password         NOTICE.* <HOST> failed to authenticate as '.*'$         NOTICE.* .*: No registration for peer '.*' \(from <HOST>\)         NOTICE.* .*: Host <HOST> failed MD5 authentication for '.*' (.*)         NOTICE.* .*: Failed to authenticate user .*@<HOST>.*         NOTICE.* .*: <HOST> failed to authenticate as '.*'         NOTICE.* .*: <HOST> tried  to authenticate with nonexistent user '.*'         SECURITY.* .*: SecurityEvent="ChallengeSent",.*,.*,Service="(PJ)?SIP",.*,AccountID="<unknown>",.*,.*,RemoteAddress=".*/.*/<HOST>/.*",Challenge=""         SECURITY.* .*: SecurityEvent="InvalidAccountID",.*,Severity="Error",Service="(PJ)?SIP",.*,.*,.*,.*,RemoteAddress=".*/.*/<HOST>/.*"         SECURITY.* .*: SecurityEvent="ChallengeResponseFailed",.*,Severity="Error",Service="(PJ)?SIP",.*,.*,.*,.*,RemoteAddress=".*/.*/<HOST>/.*",.*         SECURITY.* .*: SecurityEvent="InvalidPassword",.*,Severity="Error",Service="(PJ)?SIP",.*,.*,.*,.*,RemoteAddress=".*/.*/<HOST>/.*",.*  # Option:  ignoreregex # Notes.:  regex to ignore. If this regex matches, the line is ignored. # Values:  TEXT #
sudo nano /etc/fail2ban/action.d/iptables-asterisk.conf
3. Копируем содержимое в файл iptables-asterisk.conf (в файле по аналогии добавляем наши кастомные порты, которые мы прописывали в настройках SIP)
# Fail2Ban configuration file # # Author: Razvan Turtureanu # # $Revision$ #  [Definition]  # Option:  actionstart # Notes.:  command executed once at the start of Fail2Ban. # Values:  CMD # actionstart = iptables -N fail2ban-<name>           iptables -A fail2ban-<name> -j RETURN           iptables -I <chain> -p tcp --dport 5061 -j fail2ban-<name>           iptables -I <chain> -p udp --dport 5060 -j fail2ban-<name>           iptables -I <chain> -p tcp --dport 5060 -j fail2ban-<name>  # Option:  actionstop # Notes.:  command executed once at the end of Fail2Ban # Values:  CMD # actionstop = iptables -D <chain> -p tcp --dport 5061 -j fail2ban-<name>          iptables -D <chain> -p udp --dport 5060 -j fail2ban-<name>          iptables -D <chain> -p tcp --dport 5060 -j fail2ban-<name>          iptables -F fail2ban-<name>          iptables -X fail2ban-<name>  # Option:  actioncheck # Notes.:  command executed once before each actionban command # Values:  CMD # actioncheck = iptables -n -L <chain> | grep -q fail2ban-<name>  # Option:  actionban # Notes.:  command executed when banning an IP. Take care that the #          command is executed with Fail2Ban user rights. # Tags:    <ip>  IP address #          <failures>  number of failures #          <time>  unix timestamp of the ban time # Values:  CMD # actionban = iptables -I fail2ban-<name> 1 -s <ip> -j DROP  # Option:  actionunban # Notes.:  command executed when unbanning an IP. Take care that the #          command is executed with Fail2Ban user rights. # Tags:    <ip>  IP address #          <failures>  number of failures #          <time>  unix timestamp of the ban time # Values:  CMD # actionunban = iptables -D fail2ban-<name> -s <ip> -j DROP  [Init]  # Defaut name of the chain # name = default  # Option:  chain # Notes    specifies the iptables chain to which the fail2ban rules should be #          added # Values:  STRING  Default: INPUT chain = INPUT
sudo nano /etc/asterisk/logger_logfiles_custom.conf
4. Копируем содержимое в файл logger_logfiles_custom.conf
security_log => SECURITY,NOTICE
sudo nano /etc/logrotate.d/asterisk-security
5. Копируем содержимое в файл asterisk-security
/var/log/asterisk/security_log {         weekly         missingok         rotate 4         size 2000k         sharedscripts         create 0664 asterisk asterisk         su asterisk asterisk         postrotate                 /usr/sbin/invoke-rc.d asterisk logger-reload > /dev/null 2> /dev/null         endscript }
sudo nano /etc/logrotate.d/freepbx-security
6. Копируем содержимое в файл freepbx-security
/var/log/asterisk/freepbx_security.log {         weekly         missingok         rotate 4         size 2000k         sharedscripts         create 0664 asterisk asterisk         su asterisk asterisk         postrotate                 /usr/sbin/invoke-rc.d asterisk logger-reload > /dev/null 2> /dev/null         endscript }

Перезагружаемся — reboot

Памятка для работы с fail2ban:

File permissions and owner/group information:

/etc/fail2ban/jail.local = rw-r—r— root root
/etc/fail2ban/filter.d/freepbx.conf = rw-r—r— root root
/etc/fail2ban/filter.d/asterisk.conf = rw-r—r— root root
/etc/fail2ban/action.d/iptables-asterisk.conf = rw-r—r— root root
/etc/asterisk/logger_logfiles_custom.conf = rw-rw-r— asterisk asterisk
/etc/logrotate.d/asterisk_security = rw-r—r— root root

Basic Fail2ban commands:
Start Fail2ban = sudo service fail2ban start
Stop Fail2ban = sudo service fail2ban stop
Restart Fail2ban = sudo service fail2ban restart

Get the current status of an individual jail:
FreePBX status = sudo fail2ban-client status freepbx
Asterisk status = sudo fail2ban-client status asterisk
SSHD status = sudo fail2ban-client status sshd

Ban/Unban IP addresses:
Ban IP = sudo fail2ban-client set *YOURJAILNAMEHERE banip IPADDRESSHERE
Unban IP = sudo fail2ban-client set *YOURJAILNAMEHERE unbanip IPADDRESSHERE

*Replace YOURJAILNAMEHERE with freepbxasterisk or sshd.
*Replace IPADDRESSHERE with the IP address that you want to ban/unban.

Настройка Mikrotik

Нужно настроить проброс портов и защиту.

IP-Firewall-жмем на плюсик:

Создаем ловушки на стандартных портах и рядом стоящих для сканировщиков и отправляем в бан. Правило копируем и делаем для tcp, так же можно сделать для других стандартных портов 22,3389,8291
Делаем проброс портов во вкладке NAT (номера, которые прописывали в SIP настройках FreePBX), копируем и пишем диапазон RTP по аналогии
Проброс портов для работы абонентов в локальной сети

Так же можно/желательно делать перезагрузку системы в автоматическом режиме по расписанию, для сброса зависшего модема, у меня завис через 5 дней работы, а рядом никого, пришлось ехать и в ручную перегружать.

crontab -e # пишем в конце файла (перезагрузка каждый день в 5 утра) 0 5 * * * /sbin/reboot

Желательно настроить VPN доступ к микротику из интернета, для разруливания внештатных ситуаций по случайно забаненым адресам абонентов.

Долго собирал из разных источников эту работающую инструкцию. Может кому то и поможет.

ссылка на оригинал статьи https://habr.com/ru/post/550734/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *