Коротко — проблема не в том, что FreePBX «плохо работает», а в том, что Asterisk не получает уникального признака входящего вызова от шлюза, по которому можно привязать его к нужному inbound‑route. Решение — либо заставить шлюз передавать разный DID/To/Request‑URI для каждой SIM, либо маршрутизировать внутри Asterisk по заголовкам/peer’у (через простой кастом‑диалплан). Ниже пошагово что сделать и примеры.
1) Сначала посмотреть, что реально приходит на Asterisk
- Определите, какой SIP‑стек вы используете (chan_sip или chan_pjsip).
- Включите лог SIP и примите входящий вызов:
- chan_sip: asterisk -rvv
sip set debug on
- pjsip: asterisk -rvv
pjsip set logger on
- В логах найдите INVITE и посмотрите: Request‑URI (To:), From:, P-Asserted‑Identity/Remote‑Party‑ID, а также имя peer/channel (пример: SIP/gw1-0000001 или PJSIP/gw1-0000001). Запомните, есть ли отличительный маркер для каждой SIM (например разный user в To:, разный From user, или разный peername).
2) Рекомендованный (и самый простой) метод — настроить шлюз так, чтобы он отправлял уникальный DID/Request‑URI для каждой SIM
- На шлюзе для каждой SIM укажите, что при пересылке на PBX в Request‑URI/To user будет положен номер SIM (или любой уникальный id: 1001,1002…).
- В FreePBX создайте 4 inbound routes: DID Number = тот самый user/номер, Destination = соответствующий внутренний номер.
Плюсы: простая и чистая реализация, работает с любым стандартным inbound routing в FreePBX.
3) Если шлюз может регистрировать 4 отдельных SIP‑аккаунта (по одному на SIM)
- Зарегистрируйте на шлюзе 4 разных SIP‑аккаунта (username1…username4) к FreePBX.
- В FreePBX создайте 4 соответствующих Trunks (каждый — с соответствующим username/peer).
- При входе Asterisk будет видеть, с какого peer пришёл вызов; обычно шлюз/peer имя видно в channel name. Если при этом Request‑URI либо To содержит номер — используйте inbound routes по DID, как в пункте 2.
4) Если изменить заголовки/Request‑URI на шлюзе невозможно — вариант B: роутинг по peer или SIP‑заголовку через кастомный диалплан
- Сначала определите в логах, по какому признаку различаются входящие (например имя канала SIP/gw1-..., SIP/gw2-... или заголовок P-Asserted-Identity).
- Добавьте кастомную обработку, которая поймает этот признак и перебросит на нужный внутренний экстеншн / в стандартный from-pstn flow.
Примеры (вставлять в /etc/asterisk/extensions_custom.conf). Обязательно сделать backup перед правками.
A) Для chan_sip (пример — маршрут по имени peer):
[from-pstn-custom]
exten => _X.,1,NoOp(Incoming from PSTN — routing by chan_sip peer)
same => n,Set(PEERNAME=${CUT(CUT(${CHANNEL},/,2),-,1)}) ; получаем имя peer, например gw1
same => n,NoOp(Detected peer: ${PEERNAME})
same => n,GotoIf($["${PEERNAME}" = "gw1"]?1001,1)
same => n,GotoIf($["${PEERNAME}" = "gw2"]?1002,1)
same => n,GotoIf($["${PEERNAME}" = "gw3"]?1003,1)
same => n,GotoIf($["${PEERNAME}" = "gw4"]?1004,1)
same => n,NoOp(No match, продолжить стандартную обработку)
same => n,Goto(from-pstn,${EXTEN},1)
B) Для PJSIP или если нужно читать SIP‑заголовки (пример — берём To: и используем как DID):
[from-pstn-custom]
exten => _.,1,NoOp(Incoming from PSTN — extract DID from To header)
same => n,Set(DID=${CUT(PJSIP_HEADER(read,To),@,1)}) ; для pjsip
same => n,NoOp(Extracted DID=${DID})
same => n,GotoIf($["${DID}" = "1001"]?1001,1)
same => n,GotoIf($["${DID}" = "1002"]?1002,1)
same => n,GotoIf($["${DID}" = "1003"]?1003,1)
same => n,GotoIf($["${DID}" = "1004"]?1004,1)
same => n,NoOp(No match, standard)
same => n,Goto(from-pstn,${EXTEN},1)
Пояснения:
- В goto-целях 1001,1 — это пример: вы можете Goto на нужный extension/приёмник, либо Goto(from-pstn,номер,1) для использования стандартной логики inbound route по DID.
- Если у вас chan_sip и хотите читать заголовки, используйте SIP_HEADER(read,Header‑Name) вместо PJSIP_HEADER.
5) Как «подкрутить» FreePBX правильно (без ломать генерацию конфигов)
- FreePBX использует контексты from-pstn и from-pstn-custom: добавляя [from-pstn-custom] в extensions_custom.conf вы не будете перезаписаны при перезагрузке FreePBX. Именно туда добавляют такие проверки.
- После изменений reload: asterisk -rx "dialplan reload"
6) Отладка и советы
- Смотрите live‑логи: asterisk -rvv и sip/pjsip debug — чтобы убедиться, что ваш текст в заголовках корректно парсится.
- Если шлюз может отправлять P-Asserted-Identity/Remote‑Party‑ID с номером SIM — это удобный метод: читать этот заголовок и делать route.
- Не используйте изменения в основных сгенерированных файлах FreePBX — используйте extensions_custom.conf.
- Всегда делайте бэкап и тестируйте на одном номере перед массовыми изменениями.
Если пришлёте примеры INVITE (скрывая личные номера/пароли) — я укажу точно, какую именно строку/заголовок лучше использовать и дам готовый блок для extensions_custom.conf, чтобы входящие с каждой SIM шли на нужный внутренний номер.