使用 Asterisk 与 Synway SMG4004-4LC 搭建多 SIM SIP 网关

0. 背景

由于工作和生活需求,需要将不同的电话隔离到不同的号码上,所以渐渐积累了不少 SIM 卡。但是目前的手机通常最多只能同时使用两张 SIM 卡,如果每两张卡都准备一台手机,不仅管理麻烦,也没有太大必要。因此我开始考虑,能否把这些 SIM 卡放在一个固定的设备中,然后通过「网络电话」的方式远程使用它们。

最终希望实现:

  • 手机不需要实际插入 SIM 卡
  • SIM 卡来电可以转发到手机
  • 手机可以通过指定 SIM 卡主动拨号
  • 可以远程接收和发送短信
  • 多张 SIM 卡分别对应不同的 SIP 用户
  • 即使 SIP 客户端没有运行,也能够收到短信通知

最终选择了 Asterisk + Synway SMG4004-4LC + Acrobits Softphone + Bark 的方案。

1. 解决方案思路

1.1 各组件功能

Asterisk 作为中心节点,负责连接手机端 SIP 客户端和 Synway 蜂窝网关

Synway 负责与实体 SIM 卡及移动运营商网络通信

Acrobits Softphone 作为手机端的 SIP 客户端,用于接打电话,他的优势在于一次买断($6.99),可以使用 Push Server 接收来电通知,在 IOS 上激活 CallKit

Bark 同样也是 IOS 上好用的通知类软件,可以通过 APNs 给 IOS 设备发送通知,这里面用于接收短信推送

1.2 简要流程

语音呼入时,电话首先到达 Synway 中对应的 SIM 卡。Synway 将蜂窝呼叫转换为 SIP 呼叫并发送给 Asterisk,再由 Asterisk 根据配置将来电转发到对应用户的 Acrobits Softphone。

主动拨号时流程相反。用户在 Acrobits Softphone 中拨号,请求首先发送到 Asterisk,Asterisk 根据拨号规则将呼叫转发到对应的 Synway SIP 账号,再由 Synway 选择相应的 SIM 卡向移动运营商网络发起呼叫。

短信的处理方式稍有不同。Synway 收到 SMS 后,会将短信转换成 SIP MESSAGE 发送给 Asterisk。Asterisk 根据短信来源的 SIM 端口进行解析和分流,再通过 Bark 将短信内容推送到对应用户的手机。

发送短信是通过 SIP MESSAGE 将消息发送给 Asterisk,再由 Asterisk 转发给 Synway,最后由 Synway 选择相应的 SIM 卡发送 SMS。

2. 部署流程

2.1 准备环境

本次使用的主要环境:

1
2
3
4
5
6
7
8
Asterisk: 22.10.1
部署方式: Docker

蜂窝网关:
Synway SMG4004-4LC

手机 SIP 客户端:
Acrobits Softphone

2.2 配置 Asterisk

TLS Transport

因为手机可能会连接一些不安全的网络,因此我希望手机连接 Asterisk 的时候是安全的,这里配置连接 Asterisk 时使用 TLS。

pjsip.conf 中添加:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[transport-tls]
type=transport
protocol=tls
bind=0.0.0.0:5061

cert_file=/cert/fullchain.pem
priv_key_file=/cert/key.pem

method=tlsv1_2

external_signaling_address=example.com
external_signaling_port=5061
external_media_address=<PUBLIC_IP>

local_net=<SERVER_PRIVATE_NETWORK>

手机 endpoint 主要设置:

1
2
3
4
5
6
rtp_symmetric=yes
force_rport=yes
rewrite_contact=yes

direct_media=no
media_encryption=sdes

Synway Endpoint

以 SIM3 对应的 8003 为例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
[8003]
type=endpoint

transport=transport-smg-udp

auth=8003-auth
aors=8003

identify_by=auth_username

context=from-smg-8003

disallow=all
allow=alaw,ulaw

rtp_symmetric=yes
force_rport=yes
rewrite_contact=yes

direct_media=no
media_encryption=no
ice_support=no

这里还有一个比较特殊的问题:

多个 Synway SIP 账号实际上都来自同一个公网 IP。

如果 Asterisk 优先按照 IP 判断 endpoint,就可能无法正确区分来自不同 Synway 账号的呼叫。

因此设置了:

1
2
3
[global]
type=global
endpoint_identifier_order=auth_username,username,ip

优先使用 SIP authentication username 判断来自哪个 Synway 账号。

蜂窝来电

例如 SIM3 对应某个 SIP 用户:

1
2
3
4
5
6
7
8
9
[from-smg-8003]

exten => _X.,1,NoOp(===== Incoming cellular call: SIM3 =====)

same => n,NoOp(CallerID: ${CALLERID(all)})

same => n,Dial(${PJSIP_PDIAL_CONTACTS(USER_C)},60)

same => n,Hangup()

这里使用了PJSIP_DIAL_CONTACTS(),而不是直接PJSIP/USER_C

因为一个 SIP 用户可能同时存在多个 Contact,例如iPhone、Acrobits Push Server 或者其他 SIP 客户端

这样来电时可以呼叫该用户所有可用 Contact。

主动拨号

主动拨号大致为:

1
Dial(PJSIP/${EXTEN}@8003,60)

2.3 配置 Synway SMG4004-4LC

Synway 这一侧主要需要完成蜂窝端口、SIP Server、SIP Account、Tel → IP、IP → Tel 以及 SMS 相关配置。每个蜂窝端口对应一张 SIM 卡,同时绑定一个独立的 SIP 账号,例如 Port 1 对应 8001,Port 2 对应 8002,Port 3 对应 8003。Asterisk 则作为 Synway 的 SIP Server。

当 SIM 卡收到来电时,Synway 会根据 Tel → IP 规则将呼叫转发到 Asterisk;而当 Asterisk 主动发起呼叫时,Synway 则根据 IP → Tel 规则选择实际使用的蜂窝端口和 SIM 卡。

这里有一个比较容易误解的地方:Asterisk 中的 PJSIP endpoint 与 Synway 的蜂窝端口并不是一一对应的关系。

我最开始认为,在 Asterisk 中使用 Dial(PJSIP/${EXTEN}@8003,60) 就意味着强制通过 SIM3 呼出。实际上,8003 只是 Asterisk 内部用于选择 PJSIP endpoint 的名称。多个 endpoint 最终都可能指向同一个 Synway SIP 地址,因此 Synway 并不会知道 Asterisk 内部选择的 endpoint 名称。

真正到达 Synway 后,最终使用哪个蜂窝端口,仍然由 Synway 自身的 IP → Tel 路由规则决定。在我的配置中,Caller ID 也会参与路由判断。

2.4 配置手机 SIP 客户端

手机端我最终使用 Acrobits Softphone,按照前面配置文件的内容修改了 SIP 账号、SIP Server、端口、TLS 等信息。

2.5 配置 SMS 发送与接收

Synway 支持把蜂窝网络收到的 SMS 转换成 SIP MESSAGE。由于 Synway 不支持直接通过 Port 绑定的 SIP 发送 MESSAGE,因此单独配置 Asterisk UDP 5162 端口用于接收 Synway 的 SMS MESSAGE,并在 Asterisk 中进行解析和分流。

Common 模式下,MESSAGE body 大致为:

1
2
3
4
5
6
7
8
{
"identity": "xxxxx",
"port": "3(X)",
"callerNO": "xxxxxxxx",
"calledNO": "",
"time": "2026-10-08 10:26:14",
"smsinfo": "短信内容"
}

Asterisk 可以直接解析:

1
2
3
4
5
6
7
8
9
10
[from-smg-sms]

exten => sms,1,NoOp(===== Incoming SMS from SMG =====)

same => n,Set(SMS_JSON=${MESSAGE(body)})

same => n,Set(SMS_PORT=${JSON_DECODE(SMS_JSON,port)})
same => n,Set(SMS_CALLER=${JSON_DECODE(SMS_JSON,callerNO)})
same => n,Set(SMS_TEXT=${JSON_DECODE(SMS_JSON,smsinfo)})
same => n,Set(SMS_TIME=${JSON_DECODE(SMS_JSON,time)})

其中:

1
port = 3(X)

表示短信来自 SIM3。因此可以根据 port 将不同 SIM 的短信分别发送给不同用户。

例如:

1
2
3
same => n,GotoIf($["${SMS_PORT:0:1}"="1"]?sim1)
same => n,GotoIf($["${SMS_PORT:0:1}"="2"]?sim2)
same => n,GotoIf($["${SMS_PORT:0:1}"="3"]?sim3)

随后通过 Bark 推送到手机上

发送短信则不太相同,通过 Arcobits Softphone 的 SIP MESSAGE 将消息通过 Asterisk 发送给 Synway,再由指定蜂窝端口发送 SMS。

3. 过程中踩坑

3.1 NAT 穿透问题

最开始我在手机端启用了 STUN / ICE,在普通 Wi-Fi 和移动网络下都可以正常使用。但是当手机同时运行部分代理软件的 Configuration 模式时,STUN / ICE 有时会获取代理出口地址,并将其作为 Candidate 写入 SDP,导致 RTP 被发送到错误的地址。

此时表现为 SIP 注册正常、电话可以正常振铃和接通,但是双方没有声音。

经过排查,最终选择关闭手机端的 NAT Traversal / ICE,将 RTP 的 NAT 处理主要交给 Asterisk。Asterisk Endpoint 配置如下:

1
2
3
4
rtp_symmetric=yes
force_rport=yes
rewrite_contact=yes
direct_media=no

修改后,在目前使用的网络环境中工作更加稳定。

3.2 中国电信 VoLTE

搭建过程中还遇到了一个和 SIP 完全没有关系的问题。

其中一个 EC20 模块可以正常识别 SIM,注册 LTE,获取信号。Synway 中甚至可以看到 FDD LTE,China Telecom。但实际上却不能拨出电话,别人打入提示关机。检查 SIP 信令后发现 INVITE 已经正常到达 Synway。于是打开 Synway 的 AT Debug。发现是模块拨打电话出现 ERROR。

经过查证,发现这个 EC20 模块的固件版本不支持中国电信的 VoLTE。模块的版本为EC20CEFDGR06A08M4G,MBN 为OpenMkt-Commercial-CT。如果想要升级固件,需要厂商校准,官方给出的建议是重新采购。

因此这套系统不支持中国电信的 VoLTE SIM 卡,成为了一个遗憾。


使用 Asterisk 与 Synway SMG4004-4LC 搭建多 SIM SIP 网关
https://nacldragon.top/2026/asterisk-phone/
作者
NaCl
发布于
2026年10月9日
许可协议