Asterisk + chan_dongle + USB-модем

By | 2018-03-07

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

В качестве платформы будет выступать Raspberry Pi 2, под управлением Arch Linux, в качестве модема разлоченный Huawei E173, ну а всем остальным будет заниматься Asterisk с модулем chan_dongle.

Если модем определяется как USB Storage Device, установим usb_modeswitch, который переводит модем в режим, собственно, модема.
Из вывода dmesg видим, по строкам usb 1-1.4: GSM modem (1-port) converter now attached to ttyUSB, что у модема появились порты управления, голоса и данных

[   13.072775] usb 1-1.4: New USB device found, idVendor=12d1, idProduct=1446
[   13.075290] usb 1-1.4: New USB device strings: Mfr=3, Product=2, SerialNumber=0
[   13.077709] usb 1-1.4: Product: HUAWEI Mobile
[   13.080106] usb 1-1.4: Manufacturer: HUAWEI Technology
[   13.085184] usb-storage 1-1.4:1.0: USB Mass Storage device detected
[   13.088621] scsi host0: usb-storage 1-1.4:1.0
[   13.092008] usb-storage 1-1.4:1.1: USB Mass Storage device detected
[   13.094898] scsi host1: usb-storage 1-1.4:1.1
[   13.261021] FAT-fs (mmcblk0p1): Volume was not properly unmounted. Some data may be corrupt. Please run fsck.
[   13.333088] smsc95xx 1-1.1:1.0 eth0: hardware isn't capable of remote wakeup
[   13.335580] IPv6: ADDRCONF(NETDEV_UP): eth0: link is not ready
[   14.172244] scsi 1:0:0:0: Direct-Access     HUAWEI   SD Storage       2.31 PQ: 0 ANSI: 2
[   14.175929] scsi 0:0:0:0: CD-ROM            HUAWEI   Mass Storage     2.31 PQ: 0 ANSI: 2
[   14.183222] sd 1:0:0:0: [sda] Attached SCSI removable disk
[   14.355084] sr 0:0:0:0: [sr0] scsi-1 drive
[   14.356410] cdrom: Uniform CD-ROM driver Revision: 3.20
[   14.358865] sr 0:0:0:0: Attached scsi CD-ROM sr0
[   14.934961] IPv6: ADDRCONF(NETDEV_CHANGE): eth0: link becomes ready
[   14.937681] smsc95xx 1-1.1:1.0 eth0: link up, 100Mbps, full-duplex, lpa 0x45E1
[   15.696569] usb 1-1.4: USB disconnect, device number 4
[   19.830019] usb 1-1.4: new high-speed USB device number 5 using dwc2
[   19.962660] usb 1-1.4: New USB device found, idVendor=12d1, idProduct=1436
[   19.962883] usb 1-1.4: New USB device strings: Mfr=4, Product=3, SerialNumber=0
[   19.963097] usb 1-1.4: Product: HUAWEI Mobile
[   19.963237] usb 1-1.4: Manufacturer: HUAWEI Technology
[   19.967457] usb-storage 1-1.4:1.0: USB Mass Storage device detected
[   20.000903] usb-storage 1-1.4:1.1: USB Mass Storage device detected
[   20.053279] cdc_ether 1-1.4:1.1 wwan0: register 'cdc_ether' at usb-3f980000.usb-1.4, Mobile Broadband Network Device, 02:50:f3:00:00:00
[   20.054674] usb-storage 1-1.4:1.3: USB Mass Storage device detected
[   20.110784] usb-storage 1-1.4:1.4: USB Mass Storage device detected
[   20.180780] usb-storage 1-1.4:1.5: USB Mass Storage device detected
[   20.181875] scsi host0: usb-storage 1-1.4:1.5
[   20.182949] usb-storage 1-1.4:1.6: USB Mass Storage device detected
[   20.183828] scsi host1: usb-storage 1-1.4:1.6
[   20.221361] usbcore: registered new interface driver usbserial
[   20.221646] usbcore: registered new interface driver usbserial_generic
[   20.221892] usbserial: USB Serial support registered for generic
[   20.247889] usbcore: registered new interface driver option
[   20.248145] usbserial: USB Serial support registered for GSM modem (1-port)
[   20.248559] option 1-1.4:1.0: GSM modem (1-port) converter detected
[   20.258315] usb 1-1.4: GSM modem (1-port) converter now attached to ttyUSB0
[   20.262963] option 1-1.4:1.3: GSM modem (1-port) converter detected
[   20.267487] usb 1-1.4: GSM modem (1-port) converter now attached to ttyUSB1
[   20.272813] option 1-1.4:1.4: GSM modem (1-port) converter detected
[   20.276995] usb 1-1.4: GSM modem (1-port) converter now attached to ttyUSB2
[   21.212690] scsi 1:0:0:0: Direct-Access     HUAWEI   SD Storage       2.31 PQ: 0 ANSI: 2
[   21.220266] scsi 0:0:0:0: CD-ROM            HUAWEI   Mass Storage     2.31 PQ: 0 ANSI: 2
[   21.232567] sr 0:0:0:0: [sr0] scsi-1 drive
[   21.237436] sd 1:0:0:0: [sda] Attached SCSI removable disk
[   21.246535] sr 0:0:0:0: Attached scsi CD-ROM sr0

Если портов нет, то ищем командную строку для usb_modeswitch и добиваемся своего.

Ставим Asterisk

При наличии yaourt, стандартным путём устанавливаем астериск.

yaourt -S asterisk

Также его можно установить из исходников.

chan_dongle

Как оказалось, рабочий вариант нужно поискать.

git clone https://github.com/wdoekes/asterisk-chan-dongle.git
cd asterisk-chan-dongle
./bootstrap
./configure --with-astversion=15.2.2 # Заменить версию на свою
make
sudo make install
sudo cp dongle.conf /etc/asterisk/

Добавим пользователя asterisk в группу uucp:

usermod -G uucp asterisk

Стартуем asterisk, подключаемся к консоли и загружаем модуль chan_dongle:

systemctl start asterisk
asterisk -r
alarmpi*CLI> module load chan_dongle.so

Возможна ругань, но тем не менее следующая команда отрабатывает как ожидается:

alarmpi*CLI> dongle show devices
ID           Group State      RSSI Mode Submode Provider Name  Model      Firmware          IMEI             IMSI             Number
dongle0      0     Free       15   0    0       Beeline        E173       11.126.85.00.209  XXXXXXXXXXXXXXX  25099XXXXXXXXXX  Unknown

Значения IMEI и IMSI прописываем в /etc/asterisk/dongle.conf.
Теперь на номер можно позвонить, Астериск возьмёт трубку и скажет, что экстеншен недоступен. Также доступен USSD и чтение/отправка SMS.

Настройка Asterisk

Пропишем автозагрузку модуля:

echo "load => chan_dongle.so" >> /etc/asterisk/modules.conf

Добавим пользователя с номером 100 в файл sip.conf:

[general]
language = en
bindport = 5060
callcounter = yes
limitonpeers = yes
dtmfmode = rfc2833
compensate = yes
defaultexpiry = 3600
disallow = all
allow = alaw
tcpenable=yes

[100]
type=friend
host=dynamic
username=100
secret=password
callerid=100
context=from-sip-phone
canreinvite=yes
dtmfmode=rfc2833
permit=0.0.0.0/0.0.0.0
qualify=yes
transport=udp
nat=force_rport,comedia

Отредактируем дайлплан в extensions.conf так, чтобы все входящие вызовы на модем направлялись на номер 100, исходящие — шли через модем, а SMS-сообщения записывались в файл в виде json-объектов:

[globals]
[general]
autofallthrough=yes

[from-sip-phone]
exten => _1XX,1,Dial(SIP/${EXTEN})
exten => _XXXXXX,1,Dial(Dongle/dongle0/${EXTEN})
exten => _+7[3489]XXXXXXXXX,1,Dial(Dongle/dongle0/${EXTEN})
exten => h,1,Hangup()

[from-gsm]
exten => s,1,Set(CALLERID(all)=${CALLERID(num)})
exten => s,n,Dial(SIP/100)
exten => sms,1,System(echo '{"time":"${EPOCH}","donglename":"${DONGLENAME}","dongleimei":"${DONGLEIMEI}","dongleimsi":"${DONGLEIMSI}","fromnum":"${CALLERID(num)}","text":"${BASE64_DECODE(${SMS_BASE64})}"}' >> /var/log/asterisk/sms.txt)
exten => sms,n,Hangup()
exten => h,1,Hangup()

Раз уж у нас всё-таки модем, то было бы странно не появиться идее организовать связь с внешнем миром через него.
Установим wvdial:

pacman -S wvdial

Вызов wvdialconf без параметров опросит порты и сгенерит конфиг, который нужно немного подправить:

[Dialer Defaults]
Init2 = ATQ0 V1 E1 S0=0 &C1 &D2 +FCLASS=0
Modem Type = Analog Modem
ISDN = 0
Init1 = ATZ
Modem = /dev/ttyUSB0
Baud = 9600
Phone = *99***1#
Stupid Mode = 1
New PPPD = 1

[Dialer pin]
Init3 = AT+CPIN=0000

[Dialer megafon]
Username = \n
Password = \n
Init2 = AT+CGDCONT=1,"IP","internet.ru"

[Dialer beeline]
Username = beeline
Password = beeline
Init2 = AT+CGDCONT=1,"IP","internet.beeline.ru"

[Dialer tele2]
Username = \n
Password = \n
Phone = *99#
Init2 = AT+CGDCONT=1,"IP","internet.tele2.ru"

теперь, вызовом wvdial beeline, подключаемся к Интернету.
Секция [Dialer pin], добавлена чтобы можно было ввести PIN-код SIM-карты командой wvdial pin, если это необходимо.

Логистические проблемы и их решение

Учитывая, что провайдеры физ. лицам статические, белые IP-адреса практически не дают, назревает вопрос: «А как и куда подключиться из Интернета?».
Т.к у меня есть арендованный VDS, проблема решена так: Raspberry Pi и устройство с SIP-фоном, подключаются по OpenVPN к VDS и связываются с друг другом через виртуальные адреса.

OpenVPN-сервер на FreeBSD

pkg install openvpn								#Ставим OpenVPN
pkg install  easy-rsa							#Ставим EasyRSA, можно на голом OpenSSL, но это сложнее
openvpn --genkey --secret /etc/openvpn/ta.key	#Генерируем TLS-ключ
mkdir -p /etc/openvpn/ccd						#Директория с кастомными конфигами клиентов
easyrsa init-pki								#Активируем УЦ
easyrsa build-ca								#Генерируем корневой сертификат этого центра:
easyrsa gen-dh								#Генерируем ключ Диффи-Хелмана
easyrsa build-server-full vpn.arogov.com nopass	#Генерируем ключ сервера
easyrsa build-client-full rpi2b nopass			#Генерируем ключ клиента
easyrsa gen-crl								#Генерируем список отозванных сертификатов

Правим конфиг /usr/local/etc/openvpn/openvpn.conf (пути к ключам нужно подставить свои):

local X.X.X.X #Внешний IP
port XXXX     #Порт, который слушать. По умолчанию 1194, но лучше поменять
proto udp
dev tun
ca /usr/local/share/easy-rsa/pki/ca.crt
cert /usr/local/share/easy-rsa/pki/issued/vpn.arogov.com.crt
key /usr/local/share/easy-rsa/pki/private/vpn.arogov.com.key # This file should be kept secret
dh /usr/local/share/easy-rsa/pki/dh.pem
server 172.16.1.0 255.255.255.0
ifconfig-pool-persist ipp.txt
push "route 172.16.1.0 255.255.255.0"
client-config-dir ccd
route 172.16.1.0 255.255.255.0
client-to-client
keepalive 10 60
tls-auth /usr/local/etc/openvpn/ta.key 0 # This file is secret
cipher AES-256-CBC
max-clients 5
persist-key
persist-tun
status /var/run/openvpn-status.log
log-append  /var/log/openvpn.log
verb 3
explicit-exit-notify 1

Стартуем:

service openvpn start

OpenVPN-клиент

Ставим OpenVPN и Easy-RSA:

pacman -S openvpn easy-rsa

Для работы потребуются следующие файлы:
/usr/local/share/easy-rsa/pki/ca.crt сертификат УЦ
/usr/local/share/easy-rsa/pki/private/rpi2b.key ключ клиента
/usr/local/share/easy-rsa/pki/issued/rpi2b.crt сертификат клиента
/usr/local/etc/openvpn/ta.key ключ TLS
Копируем их с сервера на Raspberry в папку /etc/openvpn/client/ доступными способами.

Отредактируем конфиг клиента в /etc/openvpn/client/client.conf:

client
port XXXX
dev tun
proto udp
remote arogov.com 1194
resolv-retry infinite
nobind
persist-key
persist-tun
ca ca.crt
cert rpi2b.crt
key rpi2b.key
remote-cert-tls server
tls-auth ta.key 1
cipher AES-256-CBC
verb 3

Запускаем OpenVPN:

systemctl start openvpn-client@client

Проверим связь между сервером и малиной:

[root@rpi2b]# ping 172.16.3.1
PING 172.16.1.1 (172.16.1.1) 56(84) bytes of data.
64 bytes from 172.16.1.1: icmp_seq=1 ttl=64 time=42.9 ms
64 bytes from 172.16.1.1: icmp_seq=2 ttl=64 time=42.2 ms
64 bytes from 172.16.1.1: icmp_seq=3 ttl=64 time=42.0 ms
64 bytes from 172.16.1.1: icmp_seq=4 ttl=64 time=42.2 ms

Видим, что связь есть. Если же нет, то смотрим логи OpenVPN на обоих концах и принимаем меры.

Ну и наконец настраиваем смартфон/компьютер к нашему VDS и настраиваем SIP-клиент на работу с нашей системой.

Заключение

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

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

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