侧边栏壁纸
  • 累计撰写 65 篇文章
  • 累计创建 80 个标签
  • 累计收到 1 条评论

目 录CONTENT

文章目录

Matrix/Synapse + Element Web 配置香港 coturn/TURN 中继完整教程

Seger
2026-06-29 / 0 评论 / 0 点赞 / 1 阅读 / 2,611 字

一、部署架构说明

本教程适用于以下场景:

  • 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 的语音和视频通话稳定性会明显提升。

0

评论区