一、部署架构说明
本教程适用于以下场景:
- Matrix/Synapse 服务部署在德国服务器
- Element Web 部署在德国服务器或其他服务器
- coturn/TURN 中继部署在香港服务器
- 用户主要在中国大陆、香港、台湾、东南亚等地区使用语音/视频通话
推荐架构如下:
德国服务器:
mx.baidu.com → Matrix/Synapse
ele.baidu.com → Element Web
香港服务器:
turn.baidu.com → coturn/TURN 中继
Matrix/Synapse 主要负责:
登录
消息同步
房间管理
文件上传
语音/视频通话信令
coturn/TURN 主要负责:
当两端设备无法 P2P 直连时,中继语音和视频流量
如果两个人的网络可以 P2P 直连,音视频流量不会经过 TURN。
如果两个人无法直连,音视频流量会走香港 TURN:
用户 A → 香港 TURN → 用户 B
对于国内用户来说,TURN 放香港通常比放德国延迟更低,视频通话体验更好。
二、域名规划
本文使用以下域名作为示例:
mx.baidu.com Matrix/Synapse 服务端
ele.baidu.com Element Web 网页端
turn.baidu.com coturn/TURN 中继服务器
DNS 解析示例:
mx.baidu.com A记录 → 德国服务器公网 IP
ele.baidu.com A记录 → 德国服务器公网 IP
turn.baidu.com A记录 → 香港服务器公网 IP
如果服务器有 IPv6,也可以额外添加 AAAA 记录。
三、香港服务器部署 coturn
以下操作在 香港 VPS 上执行。
1. 创建目录
mkdir -p /opt/docker/coturn
cd /opt/docker/coturn
2. 生成 TURN 密钥
执行:
openssl rand -hex 32
会生成类似下面的密钥:
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
这个密钥非常重要,需要同时配置在:
香港 coturn:static-auth-secret
德国 Synapse:turn_shared_secret
两边必须完全一致。
3. 创建 coturn 的 docker-compose.yml
编辑文件:
nano /opt/docker/coturn/docker-compose.yml
写入以下内容:
services:
coturn:
image: coturn/coturn:latest
container_name: coturn
restart: unless-stopped
network_mode: host
command:
- -n
- --log-file=stdout
- --realm=turn.baidu.com
- --server-name=turn.baidu.com
- --listening-ip=香港服务器公网IP
- --relay-ip=香港服务器公网IP
- --listening-port=3478
- --min-port=49160
- --max-port=49200
- --fingerprint
- --use-auth-secret
- --static-auth-secret=你的TURN密钥
- --no-tls
- --no-dtls
需要修改三处:
--listening-ip=香港服务器公网IP
--relay-ip=香港服务器公网IP
--static-auth-secret=你的TURN密钥
例如香港服务器公网 IP 是:
1.2.3.4
那么应改成:
services:
coturn:
image: coturn/coturn:latest
container_name: coturn
restart: unless-stopped
network_mode: host
command:
- -n
- --log-file=stdout
- --realm=turn.baidu.com
- --server-name=turn.baidu.com
- --listening-ip=1.2.3.4
- --relay-ip=1.2.3.4
- --listening-port=3478
- --min-port=49160
- --max-port=49200
- --fingerprint
- --use-auth-secret
- --static-auth-secret=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
- --no-tls
- --no-dtls
说明:
3478:TURN/STUN 服务入口端口
49160-49200:音视频中继端口范围
network_mode: host:让 coturn 直接使用宿主机网络,避免 Docker NAT 影响
4. 启动 coturn
cd /opt/docker/coturn
docker compose up -d
查看容器状态:
docker ps -a | grep coturn
正常应看到:
coturn/coturn:latest Up ...
如果看到:
Restarting
说明配置有错误,需要查看日志。
5. 查看 coturn 日志
docker logs --tail=100 coturn
正常日志中应能看到类似:
Default realm: turn.baidu.com
Listener address to use: 香港服务器公网IP
Relay address to use: 香港服务器公网IP
Relay ports initialization done
如果出现大量帮助参数说明,通常是 docker-compose.yml 里某个参数写错。
6. 检查 3478 端口监听
ss -lunpt | grep 3478
正常应看到类似:
udp UNCONN 0 0 香港服务器公网IP:3478
tcp LISTEN 0 1024 香港服务器公网IP:3478
注意:
49160-49200 端口不一定会马上显示。
这些端口是实际语音/视频中继时动态使用的。
四、香港服务器开放防火墙和安全组
香港服务器必须放行以下端口:
3478/tcp
3478/udp
49160-49200/udp
如果使用 ufw:
ufw allow 3478/tcp
ufw allow 3478/udp
ufw allow 49160:49200/udp
ufw reload
如果服务器厂商有安全组,也需要在控制台放行:
TCP 3478
UDP 3478
UDP 49160-49200
如果没有放行 49160-49200/udp,可能出现:
可以响铃
可以接听
但接通后黑屏、无声音、连接失败
五、德国 Matrix/Synapse 配置 TURN
以下操作在 德国 Matrix/Synapse 服务器 上执行。
编辑 Synapse 配置文件:
nano /opt/docker/matrix/synapse/homeserver.yaml
在文件末尾添加:
turn_uris:
- "turn:turn.baidu.com:3478?transport=udp"
- "turn:turn.baidu.com:3478?transport=tcp"
turn_shared_secret: "你的TURN密钥"
turn_user_lifetime: "1h"
turn_allow_guests: false
注意:
turn_shared_secret 必须和香港 coturn 里的 static-auth-secret 完全一致。
例如:
turn_uris:
- "turn:turn.baidu.com:3478?transport=udp"
- "turn:turn.baidu.com:3478?transport=tcp"
turn_shared_secret: "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
turn_user_lifetime: "1h"
turn_allow_guests: false
六、重启德国 Synapse
cd /opt/docker/matrix
docker compose restart synapse
查看 Synapse 日志:
docker logs --tail=100 matrix-synapse
测试 Matrix API:
curl https://mx.baidu.com/_matrix/client/versions
正常会返回 JSON 数据。
七、Element Web 是否需要修改?
一般情况下,Element Web 不需要修改。
Element Web 仍然连接 Matrix/Synapse:
{
"default_server_config": {
"m.homeserver": {
"base_url": "https://mx.baidu.com",
"server_name": "mx.baidu.com"
}
},
"disable_custom_urls": true,
"disable_guests": true,
"brand": "Element"
}
TURN 信息是 Synapse 下发给 Element 客户端的,不需要写进 Element Web 的 config.json。
八、测试德国服务器到香港 TURN 是否连通
在德国服务器执行:
apt update
apt install -y netcat-openbsd
测试 TCP:
nc -vz turn.baidu.com 3478
正常输出:
Connection to turn.baidu.com 3478 port [tcp/*] succeeded!
测试 UDP:
nc -vzu turn.baidu.com 3478
正常输出:
Connection to turn.baidu.com 3478 port [udp/*] succeeded!
注意:
nc 的 UDP 测试只能说明 UDP 端口大概率可达,
不能完全证明 TURN 认证和中继一定正常。
最终仍需要用 Element 实测语音/视频通话。
九、测试 Synapse 是否下发 TURN 配置
需要先登录 Matrix 账号获取 access token。
执行:
curl -X POST "https://mx.baidu.com/_matrix/client/v3/login" \
-H "Content-Type: application/json" \
-d '{
"type": "m.login.password",
"identifier": {
"type": "m.id.user",
"user": "admin"
},
"password": "你的管理员密码"
}'
返回结果里找到:
"access_token": "xxxxx"
然后执行:
TOKEN='这里粘贴access_token'
curl "https://mx.baidu.com/_matrix/client/v3/voip/turnServer" \
-H "Authorization: Bearer $TOKEN"
正常应该返回类似:
{
"username": "xxx",
"password": "xxx",
"ttl": 3600,
"uris": [
"turn:turn.baidu.com:3478?transport=udp",
"turn:turn.baidu.com:3478?transport=tcp"
]
}
如果这里能看到 turn.baidu.com,说明 Synapse 已经成功把 TURN 信息下发给 Element 客户端。
十、Element 客户端实测
推荐测试方式:
手机:使用 4G/5G 网络
电脑:使用家庭宽带
两个不同 Matrix 账号互相发起语音/视频通话
如果 TURN 配置成功,之前一直显示“连接中”“无法接通”的问题通常会改善。
十一、常见问题排查
1. coturn 容器一直 Restarting
查看日志:
docker logs --tail=100 coturn
常见原因:
参数写错
docker-compose.yml 中 command 下有空参数
static-auth-secret 没填写
公网 IP 写错
端口被占用
查看 compose 文件行号:
cd /opt/docker/coturn
nl -ba docker-compose.yml
2. coturn 没有监听 3478
检查:
ss -lunpt | grep 3478
如果没有输出,说明 coturn 没有正常启动。
处理:
docker ps -a | grep coturn
docker logs --tail=100 coturn
3. 只看到 3478,没有看到 49160-49200
这是正常现象。
3478 是 TURN 入口端口,会一直监听。
49160-49200 是中继端口,只有实际通话分配 relay 时才会使用。
4. TCP 3478 通,UDP 3478 不通
检查:
香港 VPS 安全组
香港服务器防火墙
运营商是否限制 UDP
需要确保:
3478/udp 已放行
49160-49200/udp 已放行
5. 可以响铃,但接通后没声音或黑屏
大概率是中继端口范围没放行。
确认香港服务器安全组:
49160-49200/udp
必须放行。
6. TURN 密钥泄露怎么办?
重新生成:
openssl rand -hex 32
然后同时修改两处:
香港 coturn:
--static-auth-secret=新密钥
德国 Synapse:
turn_shared_secret: "新密钥"
重启:
# 香港服务器
cd /opt/docker/coturn
docker compose down
docker compose up -d
# 德国服务器
cd /opt/docker/matrix
docker compose restart synapse
十二、最终检查清单
香港 coturn 服务器:
docker ps -a | grep coturn
docker logs --tail=80 coturn
ss -lunpt | grep 3478
德国 Matrix 服务器:
grep -nE "turn_uris|turn_shared_secret|turn_user_lifetime|turn_allow_guests" /opt/docker/matrix/synapse/homeserver.yaml
curl https://mx.baidu.com/_matrix/client/versions
网络测试:
nc -vz turn.baidu.com 3478
nc -vzu turn.baidu.com 3478
Synapse 下发 TURN 测试:
curl "https://mx.baidu.com/_matrix/client/v3/voip/turnServer" \
-H "Authorization: Bearer $TOKEN"
Element 实测:
手机 5G + 电脑宽带
两个账号互打语音/视频
十三、推荐最终架构
用户 A
↓
Element App / Element Web
↓
德国 Synapse:mx.baidu.com
↓ 下发 TURN 信息
香港 coturn:turn.baidu.com
↓
用户 B
如果网络能 P2P 直连:
用户 A ←→ 用户 B
如果网络不能直连:
用户 A → 香港 TURN → 用户 B
这种架构的优点:
Matrix 数据仍然保存在德国服务器
香港 TURN 提高国内用户语音/视频成功率
Element Web 不需要额外修改
视频通话体验比 TURN 放德国更好
十四、总结
部署完成后,需要满足以下条件:
1. turn.baidu.com 正确解析到香港服务器
2. 香港 coturn 容器正常运行
3. 香港服务器监听 3478 TCP/UDP
4. 香港安全组放行 3478 TCP、3478 UDP、49160-49200 UDP
5. 德国 Synapse 配置 turn_uris 和 turn_shared_secret
6. Synapse 重启后可以通过 /voip/turnServer 下发 TURN 信息
7. Element 客户端重新登录或刷新后实测语音/视频通话
只要以上条件都满足,Matrix/Element 的语音和视频通话稳定性会明显提升。
评论区