Обзор протокола SIP‑TLS: настройка сертификатов и проверка совместимости клиентов

Если вы разворачиваете IP-телефонию и хотите, чтобы звонки не прослушивались в сети, вам рано или поздно придётся разобраться с SIP over TLS. Суть простая: вместо того чтобы передавать сигнализацию открытым текстом (UDP/TCP порт 5060), вы заворачиваете её в TLS-туннель (TCP порт 5061). Это шифрует не только разговор, но и служебные сообщения — кто кому звонит, какие кодеки предлагает, какие кнопки нажимаются.

Но на практике «включить TLS» — это полдела. Основная головная боль начинается, когда вы подключаете первый же телефон и обнаруживаете, что он не звонит. В этой статье я разберу, как правильно подготовить сертификаты, что на самом деле влияет на совместимость клиентов, и как не потратить день на отладку там, где можно было за десять минут всё поправить.

Что именно шифруется и зачем это нужно

SIP — это сигнальный протокол. Он не несёт голос, но договаривается о том, как голос передавать. Если SIP идёт открытым текстом, любой, кто видит трафик (Wi-Fi сниффер, коммутатор с зеркалом порта, скомпрометированный роутер), видит:

  • номера вызывающего и вызываемого;
  • список поддерживаемых кодеков;
  • учётные данные при регистрации (Digest Auth передаёт хеш, который при слабом пароле можно обработать оффлайн);
  • маршрутизацию вызовов — кто куда звонит и через какие транки.

TLS закрывает всё это. Плюс он подтверждает личность сервера (а при взаимной TLS — и клиента), что убирает классические атаки типа «человек посередине». Для корпоративной телефонии это не роскошь, а базовая гигиена.

Порты и транспорт: что нужно помнить

По умолчанию SIP использует 5060 порт для UDP и TCP. Для SIP over TLS стандартный порт — 5061 (TCP). Это важно, потому что многие телефоны и софт-клиенты по умолчанию всё ещё шлют на 5060, даже если вы настроили сервер на TLS.

На стороне сервера (Asterisk, FreeSWITCH, 3CX, Kamailio) вы определяете, какие транспорты слушать. Например, в Asterisk в файле pjsip.conf это выглядит так:

[transport-tls]
type=transport
protocol=tls
bind=0.0.0.0:5061
cert_file=/etc/asterisk/keys/asterisk.pem
priv_key_file=/etc/asterisk/keys/asterisk.key

Если вы не указали cert_file, Asterisk не запустит TLS-транспорт. Тихая ошибка, которую легко пропустить.

Сертификаты: что нужно и без чего можно обойтись

Минимальный набор

Для TLS-сервера SIP вам нужны:

  1. Сертификат сервера — содержит публичный ключ и привязанные к нему имена (CN или SAN).
  2. Приватный ключ — соответствует сертификату, хранится в секрете.
  3. Цепочка промежуточных центров сертификации (CA bundle) — если сертификат выдан не корневым ЦС напрямую.

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

Какой тип сертификата выбрать

Вот реальная картина того, что работает с разными клиентами:

Тип сертификата Совместимость с софт-телефонами Совместимость с IP-телефонами Сложность настройки Когда использовать
Самоподписанный Низкая (нужна ручная установка CA) Средняя (зависит от модели) Просто сгенерировать Тестовая среда, закрытый контур
Let’s Encrypt Высокая (общее доверие) Высокая (если устройство доверяет ISRG Root X1) Средняя (нужен автообновление) Малый и средний бизнес, основной сценарий
Коммерческий OV/EV Высокая Высокая Просто (купил и установил) Корпоративная среда с жёсткими требованиями
Корпоративный ЦС (внутренний PKI) Средняя (нужно развернуть корневой CA на все устройства) Низкая-средняя (многие телефоны не умеют работать с корпоративным PKI) Сложно Крупные компании с существующей PKI-инфраструктурой

Практический совет: если у вас нет выделенной команды, которая занимается PKI, берите Let’s Encrypt. Он бесплатный, обновляется автоматически и поддерживается практически всеми современными клиентами.

Где взять сертификат и как его подготовить

Для Let’s Encrypt самый простой путь — утилита Certbot:

sudo certbot certonly --standalone -d pb.example.com

После этого у вас будут файлы:

  • /etc/letsencrypt/live/pb.example.com/fullchain.pem — сертификат + цепочка
  • /etc/letsencrypt/live/pb.example.com/privkey.pem — приватный ключ

Для Asterisk нужно склеить их в один PEM-файл (некоторые версии принимают и раздельно, но надёжнее объединить):

cat /etc/letsencrypt/live/pb.example.com/fullchain.pem \
    /etc/letsencrypt/live/pb.example.com/privkey.pem \
    > /etc/asterisk/keys/asterisk.pem

И не забудьте настроить автообновление с перезагрузкой Asterisk:

sudo systemctl restart asterisk

Это добавляется в /etc/letsencrypt/renewal-hooks/deploy/ в виде скрипта.

Имена в сертификате: здесь чаще всего ломается

Критический момент — это SAN (Subject Alternative Name). Если в сертификате указан только pb.example.com, а клиенты подключаются по IP-адресу или по другому имени, они отвергнут соединение.

Что нужно включить в SAN:

  • FQDN сервера (например, pb.example.com);
  • IP-адрес сервера (если клиенты подключаются по IP — добавьте IP в SAN как IP-адрес, а не как DNS);
  • все имена, по которым клиенты могут обращаться к серверу.

Для Let’s Encrypt IP-адреса в SAN не поддерживаются (только доменные имена). Если у вас чистая IP-адресация, придётся использовать самоподписанный сертификат или коммерческий, который поддерживает IP SAN.

Взаимная TLS (mTLS): когда сервер проверяет клиента

Обычный TLS — это односторонняя проверка: клиент проверяет сервер. При mTLS сервер тоже требует от клиента сертификат. Это даёт дополнительный уровень безопасности вместо (или вместе с) Digest Auth.

Настройка в Asterisk:

[transport-tls]
type=transport
protocol=tls
bind=0.0.0.0:5061
cert_file=/etc/asterisk/keys/asterisk.pem
priv_key_file=/etc/asterisk/keys/asterisk.key
verify_client=yes
ca_file=/etc/asterisk/keys/ca.pem

Здесь verify_client=yes заставляет сервер требовать сертификат клиента, а ca_file — это корневой сертификат, которым подписаны клиентские сертификаты.

На практике mTLS в SIP-телефонии встречается редко. Причина простая: управление клиентскими сертификатами — это отдельная боль. Нужно генерировать сертификат на каждый телефон, доставлять его на устройство, обновлять при истечении. Для больших парков устройств это неоправданно сложно. Гораздо чаще используют обычный TLS + надёжную аутентификацию.

Совместимость клиентов: что реально работает

Вот я привожу то, что подтверждено на практике в реальных установках.

Софт-телефоны

  • Linphone — отлично работает с TLS, поддерживает mTLS, умеет проверять сертификат и позволяет отключить проверку (для тестов). Корректно обрабатывает SAN.
  • MicroSIP (Windows) — поддерживает TLS, но старые версии могут игнорировать SAN и проверять только CN. Используйте актуальную версию.
  • Zoiper — работает с TLS, но на мобильных платформах иногда ведёт себя непредсказуемо с самоподписанными сертификатами. Десктопная версия стабильнее.
  • Jitsi — поддерживает TLS, но настройки спрятаны глубоко. Новичкам сложно.
  • Telegram/WhatsApp и прочие — не являются SIP-клиентами в классическом смысле, не рассматриваем.

IP-телефоны

  • Yealink — поддерживает TLS из коробки. В прошивках последних лет умеет работать с Let’s Encrypt без дополнительных телодвижений. Важно: в настройках аккаунта нужно явно выбрать транспорт TLS и порт 5061.
  • Grandstream — поддерживает TLS, но в некоторых моделях требуется загрузить CA-сертификат в раздел «Trusted CA Certificates». Без этого — тихий отказ.
  • Cisco (Linksys SPA, 8800-серии) — старые модели (SPA504G и подобные) имеют ограниченную поддержку TLS, могут не работать с современными cipher suite. Новые 8800-серии работают нормально.
  • Fanvil — аналогично Yealink, хорошая поддержка TLS в свежих прошивках.
  • Panasonic — бюджетные модели могут не поддерживать TLS вообще. Проверяйте спецификацию конкретной модели.

Что реально ломает совместимость

На основе реального опыта, вот основные причины, по которым TLS не работает:

  1. Клиент не поддерживает TLS вообще. Дешёвые SIP-шлюзы (ATA) и старые IP-телефоны могут работать только по UDP 5060. Проверяйте спецификацию.
  2. Несовпадение имён. Клиент подключается к 192.168.1.10, а в сертификате только pb.example.com. Решение — либо добавить IP в SAN, либо использовать DNS-имя везде.
  3. Истёкший сертификат. Особенно актуально для Let’s Encrypt — если обновление не сработало, клиенты молча отказываются подключаться.
  4. Неполная цепочка. Сертификат загружен без промежуточных CA. Клиент не может построить цепочку доверия и отвергает соединение.
  5. Старые cipher suite. Некоторые клиенты поддерживают только TLS 1.0 или слабые шифры. Современные серверы по умолчанию их отключают. Приходится идти на компромисс между безопасностью и совместимостью.
  6. Брандмауэр. Порт 5061 не открыт. Звучит банально, но это одна из самых частых причин «не работает».

Проверка совместимости: пошаговый алгоритм

Когда вы настроили TLS и подключили первый клиент, а он не регистрируется, делайте так:

  1. Проверьте, слушает ли сервер порт 5061:
sudo ss -tlnp | grep 5061
  1. Проверьте сертификат с клиентской стороны:
openssl s_client -connect pb.example.com:5061 -servername pb.example.com

Посмотрите, выдалась ли цепочка, какие имена в SAN, какой протокол согласован.

  1. Включите отладку SIP на сервере (Asterisk):
asterisk -r
pjsip set logger on

Или в консоли FreeSWITCH: sofia global siptrace on.

  1. Смотрите, на каком этапе обрыв: TCP-соединение устанавливается? TLS-рукопожатие проходит? Дошло ли до SIP-регистрации?
  2. Проверьте логи клиента. Большинство IP-телефонов имеют встроенный лог (доступен через веб-интерфейс). Софт-телефоны — в настройках диагностики.

Частые ошибки и как их избежать

  • Загрузили сертификат, но забыли приватный ключ. Сервер не запустит TLS-транспорт. Проверяйте права доступа — Asterisk должен иметь возможность читать ключ.
  • Использовали сертификат для другого домена. Клиент проверяет имя, видит несовпадение — отказ. Перевыпустите сертификат с правильным именем.
  • Настроили TLS, но оставили UDP 5060 открытым. Клиенты продолжают регистрироваться по открытому каналу. Если ваша цель — полное шифрование, отключайте незащищённые транспорты или принудительно направляйте клиентов на TLS.
  • Не настроили обновление Let’s Encrypt. Через 90 дней сертификат протухает, и все клиенты одновременно перестают работать. Классический сценарий — забыли, а потом бегают перевыпускают в панике.
  • Пытаются использовать mTLS с самоподписанными клиентскими сертификатами без развёртывания корневого CA на устройствах. Это работает только если вы вручную загружаете CA в каждый клиент. Для больше чем 5-10 устройств — неоправданно.
  • Не проверяют поддержку TLS на конкретной модели телефона. Прочитали «SIP over TLS supported» в спецификации и успокоились. А на деле — только TLS 1.0, который сервер уже отключил. Проверяйте конкретную версию прошивки.

Что выбрать в зависимости от ситуации

У вас офис на 10-20 человек, 3CX или Asterisk, Yealink/Grandstream.
Берите Let’s Encrypt, настраивайте TLS на сервере, в настройках телефонов выбирайте транспорт TLS. Не заморачивайтесь с mTLS. Это покрывает 95% потребностей.

У вас корпоративная среда с жёсткими требованиями безопасности.
Коммерческий сертификат с расширенной проверкой (EV), возможно — mTLS для критичных рабочих мест. Интеграция с корпоративным PKI, если он уже есть.

У вас смешанный парк устройств, есть старые телефоны без поддержки TLS.
Настройте сервер на приём и TLS, и TCP/UDP. Для старых устройств оставьте открытый канал, но изолируйте их в отдельный VLAN. Постепенно заменяйте.

У вас бюджетная установка, один-два телефона, нет домена.
Самоподписанный сертификат с IP в SAN. Загрузите корневой CA на клиенты. Это не идеально с точки зрения управления, но работает и шифрует трафик.

Как проверить, что всё действительно зашифровано

Самый простой способ — перехватить трафик между клиентом и сервером:

sudo tcpdump -i eth0 -w sip.pcap port 5061

Откройте в Wireshark. Если всё настроено правильно, вы увидите TLS-рукопожатие, а дальше — нечитаемый шифрованный трафик. Если видите SIP-сообщения открытым текстом (INVITE, REGISTER и т.д.) — значит, TLS не работает, и клиент подключается по другому порту или протоколу.

В Wireshark фильтр для SIP over TLS: tcp.port == 5061. Для обычного SIP: udp.port == 5060 || tcp.port == 5060. Сравните — убедитесь, что весь сигнальный трафик идёт через 5061.

Итог

SIP over TLS — это не сложно, если понимать, на что смотреть. Главные моменты:

  • Используйте сертификат, которому клиенты доверяют. Let’s Encrypt — оптимальный выбор для большинства случаев.
  • Проверяйте имена в сертификате. Клиент должен подключаться по тому же имени, которое указано в SAN.
  • Не забывайте про порт 5061 и явное указание транспорта TLS на стороне клиента.
  • Настройте автообновление сертификата и мониторинг его срока действия.
  • Проверяйте совместимость конкретных моделей телефонов с вашим сервером до закупки партии оборудования.

Если после настройки TLS что-то не работает — начинайте с проверки порта, затем смотрите сертификат, затем логи. В 80% случаев проблема решается за пятнадцать минут, если знать, где искать.

Virtual-Sim.ru