Телефония и инфраструктура

Почему Asterisk не регистрировался в MCN, хотя софтфон работал

Настраивали SIP-транк MCN в Asterisk внутри Docker на Mac. Логин и пароль были верные — в софтфоне Telephone всё подключалось. А Asterisk показывал Unregistered. Оказалось, дело не в учётке, а в том, какой адрес контейнер отправлял провайдеру.

В двух словах

Telephone на Mac ходит в MCN напрямую. Asterisk в контейнере — через Docker Desktop и NAT. Для обычного HTTP это редко заметно, а SIP смотрит на заголовки Via и Contact: по ним провайдер понимает, куда слать ответ.

Сначала Asterisk писал в эти заголовки внутренний Docker-адрес 172.x.x.x. MCN такой REGISTER видел, но ответить на него снаружи не мог — это адрес внутри контейнера, не в интернете.

Asterisk в контейнере Docker Desktop Mac sip.mcn.ru

Заработало после трёх правок: указали публичный IP в EXTERNAL_IP, оставили порт MCN 5060 для исходящих запросов и вынесли локальный порт Asterisk на 50600.

Симптомы

Asterisk не регистрируется

В pjsip show registrations видно Unregistered, иногда после ответа провайдера статус меняется на Rejected.

Софтфон работает

Telephone на Mac с теми же SIP-логином, паролем и сервером sip.mcn.ru проходит регистрацию. Это отсекает проблему учётки и переносит фокус на REGISTER от Asterisk.

Если софтфон регистрируется, а Asterisk нет — сначала сравните SIP REGISTER в логе. Чаще всего проблема в адресе и порте в заголовках, а не в пароле.

Что показал лог

Включили PJSIP logger и отправили REGISTER вручную:

docker compose exec asterisk asterisk -rx "pjsip set logger on"
docker compose exec asterisk asterisk -rx "pjsip send register mcn-reg"
docker compose logs --tail 220 asterisk

До исправления

Asterisk объявлял себя через приватный Docker IP:

REGISTER sip:sip.mcn.ru SIP/2.0
Via: SIP/2.0/UDP 172.20.0.2:5160;rport;branch=...
Contact: <sip:<sip-login>@172.20.0.2:5160>

172.20.0.2 — адрес внутри Docker. MCN с интернета на него не достучится.

После EXTERNAL_IP

Когда задали публичный IP, в заголовках появился нормальный внешний адрес:

Via: SIP/2.0/UDP <public-ipv4>:5160;rport;branch=...
Contact: <sip:<sip-login>@<public-ipv4>:5160>

Но на портах 5060 и 5160 регистрация всё равно то появлялась, то пропадала. Стабильно заработало только с локальным портом 50600.

Что в итоге сработало

Тут два разных порта. На MCN Asterisk шлёт REGISTER на sip.mcn.ru:5060. А в Via и Contact пишет, что сам слушает на <public-ipv4>:50600.

MCN_SIP_LOGIN=<sip-login>
MCN_SIP_PASSWORD=<password-from-mcn>
MCN_SIP_SERVER=sip.mcn.ru
MCN_SIP_CONTEXT=incoming
MCN_SIP_LOCAL_PORT=50600
MCN_SIP_REMOTE_PORT=5060
EXTERNAL_IP=<public-ipv4>
INTERNAL_EXT=100

В docker-compose.yml пробросили UDP-порты, включая тот, что Asterisk указывает в заголовках:

ports:
  - "50600:50600/udp"
  - "5060:5060/udp"
  - "5160:5160/udp"
  - "10000-10100:10000-10100/udp"

Дальше всё штатно: MCN отвечает 401 Unauthorized, Asterisk повторяет REGISTER с Digest, приходит 200 OK. В pjsip show registrationsRegistered.

REGISTER sip:sip.mcn.ru SIP/2.0
Via: SIP/2.0/UDP <public-ipv4>:50600;rport;branch=...
Contact: <sip:<sip-login>@<public-ipv4>:50600>

SIP/2.0 401 Unauthorized

REGISTER sip:sip.mcn.ru SIP/2.0
Authorization: Digest username="<sip-login>", realm="mcn", nonce="...", uri="sip:sip.mcn.ru", response="...", algorithm=MD5

SIP/2.0 200 OK

Про запуск и проверку

docker compose up --wait ждёт, пока контейнер станет healthy — то есть Asterisk запустился и CLI отвечает. Регистрация в MCN идёт чуть позже, это отдельный шаг.

После старта подождите несколько секунд и проверьте статус:

docker compose up --build -d --force-recreate --wait asterisk
sleep 10
docker compose exec asterisk asterisk -rx "pjsip show registrations"

Без паузы можно поймать Unregistered (exp. 4s), хотя через пару секунд уже будет Registered.

Другие статьи