Иногда может оказаться полезным поставить дома в шлюз свою симку, а самому совершать и принимать звонки через 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, что у модема появились порты управления, голоса и данных
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
[ 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, стандартным путём устанавливаем астериск.
1 |
yaourt -S asterisk |
Также его можно установить из исходников.
chan_dongle
Как оказалось, рабочий вариант нужно поискать.
1 2 3 4 5 6 7 |
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:
1 |
usermod -G uucp asterisk |
Стартуем asterisk, подключаемся к консоли и загружаем модуль chan_dongle:
1 2 3 |
systemctl start asterisk asterisk -r alarmpi*CLI> module load chan_dongle.so |
Возможна ругань, но тем не менее следующая команда отрабатывает как ожидается:
1 2 3 |
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
Пропишем автозагрузку модуля:
1 |
echo "load => chan_dongle.so" >> /etc/asterisk/modules.conf |
Добавим пользователя с номером 100 в файл sip.conf:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
[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-объектов:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
[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:
1 |
pacman -S wvdial |
Вызов wvdialconf без параметров опросит порты и сгенерит конфиг, который нужно немного подправить:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
[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
1 2 3 4 5 6 7 8 9 10 |
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 (пути к ключам нужно подставить свои):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
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 |
Стартуем:
1 |
service openvpn start |
OpenVPN-клиент
Ставим OpenVPN и Easy-RSA:
1 |
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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
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:
1 |
systemctl start openvpn-client@client |
Проверим связь между сервером и малиной:
1 2 3 4 5 6 |
[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-клиент на работу с нашей системой.
Заключение
При подключении малины к Интернету проводным способом, система работает стабильно.
При подключении через модем, появляется задержка голоса и периодические лаги, но, откровенно говоря, я вообще не ожидал, что голос и данные хоть как-то будут работать вместе.