Дёрнул меня чОрт в очередной раз поковыряться с Asterisk-ом. Надо было сделать TLS+SRTP. А поскольку chan_sip вроде как устарел и вообще весь из себя deprecated, решил взять chan_pjsip.
Пилил себе и пилил потихонечку, до какого-то момента вроде всё работает. А потом "бац" и застрял после включения директив
protocol=tls
method=tlsv1
И ни в какую. SIP-клиент говорит лаконичное "Service Unavailable" и отказывается подключаться. В консоли и в логах сервера тишина, хотя какой-то трафик туда-сюда бегает. Но вот не выходит каменный цветок. Правильно, не фиг было его глотать.
В 13-м астериске (Debian 9) мне так и не удалось заставить всё это работать, от слова "совсем". В 16-м астериске (Debian 10) после долгих мучений таки зашевелилось. А вся засада оказалась в трудностях подобрать общий набор шифров, которые бы одновременно поддерживались OpenSSL, SIP-клиентом и грёбаным PJSIP-ом. Какие-то из них считает небезопасными OpenSSL, какие-то из них несовместимы с TLSv1 (но PJSIP про это не знает) и всё в этом духе.
В общем случае алгоритм таков.
На сервере спрашиваем
openssl ciphers -s -tls1
Он выдаст что-нибудь типа
ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES256-SHA:ECDHE-ECDSA-AES128-S HA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES128-S HA:AES256-SHA:AES128-SHA
Затем спрашиваем у самого PJSIP-а что он про это думает:
asterisk -rx 'pjsip list ciphers'
В ответ оно выплюнет огромную такую простыню, но нас из этого набора интересуют только те, которые упоминались в предыдущем выхлопе openssl. Таким образом, мы получаем некое пересечение двух множеств. Берём его и через запятую прописываем в настройках pjsip-транспорта в директиве "cipher". Например, вот так:
cipher=ECDHE-ECDSA-AES256-SHA,ECDHE-RSA-AES256-SHA,DHE-RSA-AES256-SHA,ECDHE-ECDSA-A ES128-SHA,ECDHE-RSA-AES128-SHA,DHE-RSA-A ES128-SHA,AES256-SHA,AES128-SHA
Дальше берем какого-нибудь клиента (хотя можно прям с самого сервера, большой разницы нет) и пытаемся подключиться к запущенному Asterisk-у по TCP/5061 с явным указанием протокола TLSv1.
openssl s_client -connect 11.22.33.44:5061 -tls1
И смотрим что ответит. Если скажет
---
no peer certificate available
---
No client certificate CA names sent
---
То поздравляю, Шарик, ты балбес. Значит он не смог подобрать устраивающие обе стороны шифры. Надо курить дальше. Возможно, обновлять / пересобирать Asterisk, OpenSSL, дистрибутив и совершать прочие пляски с бубном.
Если же он выплюнул имя сервера и его сертификат в PEM-виде, то дальше ищем тама вожделенные строчки типа
SSL-Session:
Protocol : TLSv1
Cipher : ECDHE-RSA-AES256-SHA
Вот этот самый шифр и будет тем самым, нашим любимым и всячески обласканным. И именно его-родимого мы и пропишем в конечном итоге в директиве "cipher" в конфиге pjsip.conf. То есть, вот так:
cipher=ECDHE-RSA-AES256-SHAДальше можно пробовать цепляться SIP-клиентом. Скорее всего, заработает. Я тестировал на CSIPSimple.
Почему-то этого нет ни в примерах, ни в мануалах, ни в вики, нигде. Пришлось добираться до этого тайного знания методом набивания собственных шишек.
И ещё. В настройках SIP-клиента надо явно указывать идентификатор аккаунта вида "sips:john@superserver.com". То есть не "sip", а "sips". Иначе Asterisk будет отбивать вызовы с такого устройства с мотивацией "PJSIP_EUNSUPTRANSPORT". Типа, раз решил работать бизапасна, то давай по всё строгости. Чтоб никакой фокус.
А вообще, смотрю я на то, что делают с этим Asterisk-ом в каждой последующей версии... Блин, чем дальше, тем страшней. Особенно порадовал последний комментарий топикстартера вот в этом обсуждении. Ещё один человек ушёл на тёмную сторону, понимаешь... гы.