Как настроить TLS для SMPP и защитить SMS-трафик

Как настроить TLS для SMPP и защитить SMS-трафик

TLS защищает соединение между вашим приложением и SMPP-шлюзом: данные передаются в зашифрованном виде, а приложение может проверить сертификат сервера. В статье разберём, что уточнить у провайдера, как проверить порт и сертификат, какие параметры задать в Python и как убедиться, что после включения шифрования не сломались bind, отправка и DLR. Примеры подойдут разработчику малого бизнеса, который подключает высокообъёмный SMS-трафик из Беларуси.

Что именно защищает TLS в SMPP?

SMPP передаёт команды между ESME, то есть вашим приложением, и SMS-центром или шлюзом. Через соединение проходят логин SMPP, служебные команды, текст сообщения, номер получателя и ответы сервера. Если соединение идёт без шифрования, содержимое сетевого обмена можно перехватить на одном из участков маршрута.

TLS создаёт защищённый транспортный слой поверх TCP. После установки соединения стороны договариваются о версии протокола и шифрах, затем приложение проверяет сертификат сервера. SMPP-команды при этом остаются теми же: bind_transmitter, bind_receiver или bind_transceiver, submit_sm, enquire_link и ответы на них.

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

До настройки запросите у провайдера пять параметров:

  • адрес SMPP-шлюза и порт TLS;
  • нужна ли проверка сертификата по имени хоста;
  • требуется ли сертификат клиента, то есть взаимная аутентификация;
  • допустимые версии TLS и наборы шифров;
  • ограничения по bind, DLR, кодировкам и тайм-аутам.

Для высокообъёмного трафика TLS не заменяет настройку самого SMPP-сеанса. После защищённого подключения всё равно нужно контролировать ответы submit_sm, delivery receipt и состояние bind. Отдельно проверьте heartbeat: настройка Enquire Link на SMPP-шлюзе помогает не держать в пуле соединение, которое сеть уже разорвала.

Как подготовить TLS-соединение на сервере?

Начните с окружения, где приложение будет работать постоянно. На сервере должны быть актуальные корневые сертификаты операционной системы и библиотека SMPP, которая умеет принимать готовый TLS-сокет либо включать TLS собственным параметром. Если библиотека поддерживает только обычный TCP, понадобится обёртка над сокетом или другой SMPP-клиент.

Сертификат сервера нужно проверять по цепочке доверия. Для рабочей системы не подходит режим, который принимает любой сертификат и отключает проверку имени хоста. Такой флаг иногда используют для локальной диагностики, но его нельзя переносить в конфигурацию продакшена: приложение тогда подтвердит шифрование, но не удостоверится, с каким сервером оно установило связь.

Ниже приведён общий пример на Python. Названия методов у SMPP-библиотек отличаются, поэтому функцию создания клиента и вызов bind нужно сверить с документацией выбранного пакета. Ключевая часть примера — контекст SSL, включённая проверка сертификата и подключение к TLS-порту.

import ssl
import smpp_client

context = ssl.create_default_context()
context.minimum_version = ssl.TLSVersion.TLSv1_2
context.check_hostname = True
context.verify_mode = ssl.CERT_REQUIRED

client = smpp_client.Client(
    host="smpp.example",
    port=TLS_PORT,
    ssl_context=context,
    system_id=SMPP_LOGIN,
    password=SMPP_PASSWORD
)

client.connect()
client.bind_transceiver()
client.submit_sm(destination_addr=PHONE, short_message=TEXT)

В этом фрагменте smpp.example, TLS_PORT, SMPP_LOGIN и другие значения обозначают параметры из договора или кабинета провайдера. Их нельзя копировать буквально. Если шлюз требует сертификат клиента, добавьте в SSL-контекст загрузку файла сертификата и закрытого ключа, которые вы получили от провайдера:

context.load_cert_chain(
    certfile="/etc/smpp/client.crt",
    keyfile="/etc/smpp/client.key"
)

Закрытый ключ храните вне репозитория и не передавайте в логах. Доступ к файлу ограничивают правами пользователя, от имени которого работает SMS-сервис. В конфигурации приложения оставляют путь к секрету или ссылку на хранилище секретов, а не сам ключ в открытом виде.

Как проверить сертификат и сам SMPP-сеанс?

Проверка состоит из двух частей. Сначала убедитесь, что TCP-соединение действительно устанавливается с нужным портом и TLS-сервер отдаёт сертификат. Затем выполните полноценный SMPP-сценарий: bind, тестовый submit_sm, получение ответа и проверку DLR, если шлюз его возвращает.

Для первичной диагностики администратор может использовать TLS-клиент командной строки из окружения сервера. Команда должна обращаться к имени хоста, которое указал провайдер, потому что проверка сертификата зависит от совпадения имени. Если подключаться по IP-адресу, сертификат часто не пройдёт проверку даже при исправной настройке.

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

  • время начала и завершения TLS-handshake;
  • результат проверки сертификата;
  • успешный bind и тип bind;
  • исходящий идентификатор сообщения;
  • код ответа submit_sm;
  • статус DLR и причина ошибки, если шлюз её передал;
  • разрыв соединения и повторное подключение.

Текст SMS и пароль SMPP в журнал не записывают. Для поиска проблемы достаточно идентификатора сообщения, времени, номера порта и кода ответа. Если сообщения не отправляются после включения TLS, сначала отделите транспортную ошибку от ошибки SMPP: при проблеме сертификата приложение обычно не доходит до bind, а при неверных учётных данных TLS завершается, но bind получает отказ.

DLR проверяйте отдельно для каждого тестового сообщения. Сам факт успешного submit_sm означает, что шлюз принял запрос приложения, но не подтверждает доставку абоненту. Для контроля этого участка пригодится мониторинг SMPP через DLR.

Как настроить кодировки, heartbeat и повторные подключения?

TLS шифрует канал, но не исправляет ошибки в формате SMS. Для кириллицы обычно используют UCS2, а для латинского алфавита GSM7, если текст укладывается в поддерживаемый набор символов. Такая рекомендация указана в требованиях к отправке SMS SMPP в документации Exolve. Перед запуском проверьте, как ваша библиотека формирует data_coding и short_message.

Сделайте отдельные тесты для латинского текста, кириллицы и сообщения, в котором встречается специальный символ. Проверяйте не только отображение у получателя, но и длину сообщения, разбиение длинного текста и значение esm_class для составных SMS. Эти параметры зависят от шлюза и библиотеки, поэтому их фиксируют в рабочей конфигурации после теста.

Поддерживайте соединение через enquire_link и отвечайте на enquire_link от шлюза. В документации Exolve для SMPP указано, что ESME должно отправлять PDU enquire_link каждые 15 минут независимо от наличия трафика. В конкретном подключении интервал может быть иным, если это установлено провайдером. Таймер должен работать независимо от очереди отправки.

После сетевого разрыва приложение закрывает старый сокет, создаёт новый TLS-контекст или повторно использует безопасный объект согласно документации библиотеки, затем выполняет bind заново. Нельзя без проверки повторно отправлять последний submit_sm: при разрыве ответа приложение не знает, принял ли шлюз сообщение. Нужны собственный message ID, идемпотентная логика и сверка DLR.

СитуацияЧто проверить первымЧто записать в журнал
Не проходит TLS-handshakeПорт, имя хоста, срок действия и цепочку сертификатаКод ошибки TLS и время подключения
TLS установлен, bind отклонёнsystem_id, пароль, тип bind и права учётной записиКод ответа bind без пароля
submit_sm принят, DLR нетПараметры DLR и маршрут статусов у провайдераИдентификатор сообщения и статус ответа
Соединение разрывается в простоеEnquire Link, тайм-ауты и сетевой firewallВремя последнего heartbeat
Кириллица отображается неправильноUCS2, data_coding и длину поля сообщенияТип кодировки и размер текста

Какие ошибки встречаются при включении TLS?

  • Проверку сертификата отключают навсегда. Так можно найти причину сбоя в тестовой среде, но рабочее подключение должно проверять цепочку доверия и имя сервера.
  • На TLS-порт отправляют обычный SMPP без TLS. Сервер ждёт начало TLS-сеанса и не понимает первые байты SMPP-пакета.
  • Имя сервера заменяют IP-адресом. При включённой проверке hostname сертификат может не совпасть с адресом подключения.
  • Сертификат клиента и сертификат сервера путают. Для взаимной аутентификации нужны отдельные файлы и требования провайдера.
  • После включения TLS не тестируют DLR. Принятый submit_sm показывает только ответ шлюза на запрос, поэтому доставку проверяют отдельным сценарием.
  • Heartbeat смешивают с очередью SMS. Enquire Link должен отправляться даже тогда, когда новых сообщений нет.

Перед переносом настройки в рабочую среду сохраните параметры TLS, тип bind, кодировки, интервал enquire_link и правила повторного подключения в одном техническом описании. Затем проведите небольшой тестовый прогон с кириллицей, проверкой ответа submit_sm и DLR. Если собственная SMPP-библиотека не умеет надёжно работать с TLS-сокетом, сначала выберите шлюз и клиентскую реализацию с такой поддержкой; сравнить варианты подключения помогает материал как выбрать SMPP-шлюз в 2026 году: SMPP или HTTP API.

3 шага, которые можно сделать сегодня:

  1. Запросить у провайдера TLS-порт, требования к сертификатам, имя хоста и интервал heartbeat.
  2. Собрать SSL-контекст с проверкой сертификата и прогнать bind в тестовой среде.
  3. Отправить тестовую SMS, проверить код submit_sm, DLR, кириллицу и поведение после разрыва соединения.