Одним из наиболее популярных приложений для голосового общения в сети является Skype. Для этого есть и объективные предпосылки - достаточно развитые возможности клиента и протокола, неплохая работа в условиях NAT (и даже возможность работы через прокси), интеграция (коммерческая) с телефонными сетями, мультиплатформенный клиент. Основной недостаток - закрытость протокола и клиента, сложность интеграции с другими chat/voice сервисами, замкнутость технологии на одной компании. Тем не менее - реалии таковы что на сегодняшний день это наиболее популярное средство для общения и, на мой взгляд, альтернатив, особенно открытых, немного. В этой заметке я решил описать создание гейта skype ↔ SIP с использованием IP АТС Asterisk. Данное решение позволит преобразовать skype трафик в стандартный и открытый SIP, с которым потом уже средствами Asterisk (и не только) можно делать все что угодно.
Редкий тролль не любит рассказов об ужасах, скрывающихся в BLOB`ах закрытых продуктов (особенно забавна история когда обнаружили чтение skype`ом /etc/passwd и стали трубить о том что скайп “ворует пароли”), которые чаще всего не подкреплены какими либо доказательствами. Тем не менее - в данной задаче, на мой взгляд, и в самом деле удобнее создать изолированное окружения, как по соображениям безопасности так и с точки зрения удобства поддержки. В качестве виртуальной машины я выбрал linux-kvm (также успешно протестирована работа в VirtualBox), в качестве гостевой среды - debian 5 (который как раз только что вышел). Выбор основан исключительно на личных предпочтениях, думаю что должно работать на любом другом дистрибутиве, и скорее всего, даже на BSD (в линуксяторе). В дальнейшем я планирую перенести гейт на XEN, так что в данном случае нормальная поддержка в debian работы в domU тоже плюс. Единственным найденным мной открытым решением для *nix стал Skypiax, так что тут и выбирать не пришлось.
Как уже упоминалось - скайп закрытое приложение, и его протокол достаточно неплохо защищен от сторонних разработчиков. Так что единственным доступным клиентом протокола в настоящий момент является сам skype. Но для интеграции своего ПО со сторонними разработчиками (как железа, так и ПО) skype клиент позволяет работать с ним используя документированное API. В linux версии для транспорта используется DBUS и X11. API достаточно обширно, но тем не менее о полноценном embed клиенте говорить не приходится, так что нам все равно потребуется X11 и запущенный клиент. Skypiax позволяет Asterisk общаться с запущенными skype клиентами и совершать или принимать skype звонки.
Для начала установим ОС. Для нашей задачи будет вполне достаточно диска на 2Gb (думаю, что хватило бы и сильно меньшего но это потребовало бы пересборки пакетов без ненужных зависимостей). Ставить дистрибутив x86_64 лишено смысла, так как клиент все равно i386, да и памяти меньше израсходуем.
~: qemu-img create ~/images/skype 2G ~: kvm -hda ~/images/skype -cdrom ~/dists/debian-500-i386-CD-1.iso
Выбираем вариант установки без десктоп окружения и прочего непотребства, все что нужно мы позже установим из пакетов. После того как установка завершена - перезагружаем гостя и устанавливаем нужные пакеты:
Asterisk, заголовки и куча преимущественно ненужных нам зависимостей
skype:~# apt-get install asterisk-dev
Skype client
skype:~# wget http://skype.com/go/getskype-linux-deb skype:~# dpkg -i skype-debian_2.0.0.71-1_i386.deb skype:~# apt-get -f install skype:~# dpkg -i skype-debian_2.0.0.71-1_i386.deb
Subversion (потребуется для скачивания исходников skypiax)
skype:~# apt-get install subversion
OpenSSH server (для управления в будущем и первоначальной настройки Skype)
skype:~# apt-get install openssh-server
Заголовки Xlib потребуются нам позже
skype:~# apt-get install libx11-dev
Теперь загрузим и скомпилируем skypiax:
skype:~# svn co http://www.celliax.org:8081/svn/celliax/trunk celliax skype:~# cd celliax/skypiax_stuff/build/ skype:~/celliax/skypiax_stuff/build# vi Makefile
Заменяем путь AST_INCLUDE_DIR=/home/user/devel/asterisk-1.4.23.1/include
на AST_INCLUDE_DIR=/usr/include
, компилируем и копируем результат в нужную нам папку.
skype:~/celliax/skypiax_stuff/build# make skype:~/celliax/skypiax_stuff/build# cp chan_skypiax.so /usr/lib/asterisk/modules/ && cp skypiax.conf /etc/asterisk/
На этом установка завершена, можно переходить к более увлекательному этапу настройки.
Для запуска skype я использован возможность X11 forwarding openssh сервера и клиента, присоединившись с десктоп машины на skype сервер с параметром -X:
ssh -X root@skypeserver.local
Для своей работы скайп захочет звуковую карту, для подобных целей в alsa предусмотрен драйвер snd-dummy
, загрузим его:
modprobe snd-dummy
После этого запускаем в терминале скайп, и если все работает правильно - он должен показать лицензионное соглашение и свой интерфейс на рабочем столе. Скайп позволяет использовать одно и тоже подключение из нескольких мест (чем, кстати, выгодно отличается от SIP), но тем не менее я рекомендую завести отдельную запись, как минимум для удобства тестирования. Запустив скайп соглашаемся с лицензией и вводим данные учетной записи. Если все настроено правильно - skype должен зарегистрироваться в сети. Перейдя в настройки отключаем уведомления (Notifications → Enable Event). Теперь самое важное - в пункте Sound Devices указываем устройство Dummy (hw:Dummy,0)
. В меню Advanced стоит отключить проверку обновлений, а в меню Video Devices - поддержку видео. После этого skype клиент должен без проблем совершать или принимать звонки, правда слышно ничего не будет, так как карта виртуальная. Не закрываем клиент (он нам скоро потребуется) и переходим к настройке Asterisk.
Desktop:~$ ssh -X root@skypeserver.local
skype:~# echo $DISPLAY
В моем случае это localhost:11.0
[skypeclient] language=en ; default context=default ; incoming context extension=600 ; forward calls to default asterisk echo test skype=yes ; legacy setting X11_display=localhost:11.0 ; value from $DISPLAY tcp_cli_port=11234 ; 2 random pots tcp_srv_port=11235 ; skype_user=skypet123 ; skype nickname playback_boost=0 ; volume boost for playback capture_boost=0 ; ... and recording
В данной конфигурации я указал X11_display из пункта 2, для того, чтобы asterisk смог соединиться с запущенным клиентом. Extension=600 обозночает что входящие звонки в будут перенаправлены в extension 600, который по умолчанию (см. extensions.conf) перенаправляется на эхо тест задержки. Это позволит нам убедиться что все работает правильно и заодно определить на слух задержу сигнала.
skype:~# /etc/init.d/asterisk stop; asterisk -c -vvv -ddd
. Если все настроено верно - скайп должен показать уведомление о том, что другая программа пытается к нему подключиться. Обязательно отмечаем галку “Remember this selection” и разрешаем подключение.
После этого пробуем позвонить на эту скайп запись. Если все настроено верно - вы должны слышать эхо-тест астериска. Кстати, распознавание DTMF прекрасно работает, что позволяет создавать IVR на базе данного решения.
Для того, чтобы skype работал в виртуальном X11 окружении установим xvfb - Virtual Framebuffer 'fake' X server.
skype:~# apt-get install xvfb
Данный сервер позволяет работать X11 приложением локально, не требуя видео карты и потребляя сравнительно немного ресурсов. Для запуска скайпа создадим скрипт skypestart.sh:
#!/bin/sh # loading sound driver /sbin/modprobe snd_dummy # setting DISPLAY export DISPLAY=:1 # starting virtual framebuffer X-Server nohup /usr/bin/Xvfb ${DISPLAY} -screen scrn 300x600x8 >/dev/null & echo <skypenick> <password>|/usr/bin/skype --pipelogin & # restarting asterisk sleep 5 /etc/init.d/asterisk restart
заменив <skypenick> <password> на данные skype записи. Этот скрипт загружает snd_dummy, запускает X-server и загружает скайп. Перезагрузка астериска требуется для того, чтобы он установил связь с клиентом.
Скрипт можно добавить в крон, например так:
@reboot /root/skypestart.sh
Или сделать на его основе полноценный init.d сценарий. Также возможна запуска более чем одной копии Skype. Для этого надо скопировать $HOME/.Skype/ в соответствующие поддиректории, и переопределив HOME и DISPLAY запустить для каждой из копий свой xvfb сервер и клиента, добавив соответствующие записи в конфигурацию asterisk.
Для тестирования работы skype c SIP телефоном я использовал ATA adapter Linksys (подойдет и любой sofpthone, например - Ekiga), подключив его к Asterisk. Для этого создадим запись в файле /etc/asterisk/sip.conf
; linksys ata adapter, skype testing [sipphone] context=default type=friend ; ATA login secret=f.ck ; ATA password host=dynamic ; allow to register
Перезапустим Asterisk и настроем АТА адаптер используя Asterisk в качестве сервера. Для проверки наберем на SIP телефоне 600#, вы должны услышать эхо тест.
Если все работаем - настроим перенаправление. Для этого в /etc/asterisk/skypiax.conf заменим строчку extension=600
на, например extensions=555
. В файле /etc/asterisk/extensions.conf (секция [default]) добавим
exten => 555,1,Dial(SIP/sipphone);
Перезапустим Asterisk и попробуем вызвать наш тествовый SkypeID - звонок должен быть перенаправлен на sipphone. Единственный неприятный момент - скайп берет трубку сразу после поступления вызова, так что корректную сигнализацию, вероятно, обеспечить не удастся.
Для того, чтобы с sipphone вызывать skype пользователей - добавим соответствующие записи в /etc/asterisk/extensions.conf (секция default), например
[default] exten => 555,1,Dial(SIP/sipphone); exten => 556,1,Dial(Skypiax/skypeclient/echo123); exten => 557,1,Dial(Skypiax/skypeclient/drugdiler); exten => 558,1,Dial(Skypiax/skypeclient/advokat);
и в консоли Asterisk наберем dialplan reload
. Теперь набрав на sipphone 556 asterisk соединет нас с Skype call testing service. Что и требовалось )
Для использования решения в production желательно сделать некоторые доработки, так я планирую сделать скрипты для пуска/остановки клиентов, создать rootless окружение для всего этого, интегрировать все это хозяйство с monit и перенести все в Xen domU. Тем не менее уже сейчас понятно что решение работоспособно и работает достаточно неплохо. Я буду рад дельным замечаниям и комментариям на эту тему.
Alex Samorukov