Matrix 下一代聊天协议 Synapse 服务器搭建

liueic 发布于 17 天前 0 次阅读


目前很多博客只简单讲述了如何搭建 Synapse 服务器,但实际搭建完,用户使用后会出现大量问题,本文旨在详细讲述 Synapse 服务器以及其他的配套服务搭建

Synapse 现状

Synapse 原本是由 Matrix基金会实现和维护的,是一个基于 Python 的 Matrix 协议实现服务,当然除此之外也有其他的服务端推荐,但是 Synapse 是其中最稳定,也是官方最为推荐的,在官网他们给出了其他的服务端

在2024年的八月份,Matrix基金会已经无力再维护 Synapse,而是将其转交给了 Element 维护

你或许会问了,Element 是什么?和 Matrix 又是什么关系?

坦率地讲,我觉得 Element 有点像一个商业公司,他们为一些客户提供了 Matrix 服务器的托管服务,同时将一些客户端和服务端开源,Matrix 让 Element 来接手 Synapse 的维护其中应该也有 Matrix 作为一个非盈利基金会资源不够用的窘境

对于我们普通用户来说,不管是 Matrix 还是 Element,他们所提供的 Synapse 都是开源的,因此对于我们来说没有影响,只管好好用就可以了

但是在一些细微的配置中,Element 为了更好的适配直接的客户端,我们需要做一些细微的调整,这些在后面的章节中会详细讲述

安装 Synapse

一个完整的 Synapse 包括以下部分:

如果英文能力可以的话我极力推荐阅读官方的文档,目前最新的文档是由 Element 所维护:Welcome and Overview - Synapse

搭建基础服务

关于如何搭建 Synapse 基础服务器,我建议可以去看一看这位博主的文章,我第一次搭建就是跟着这个的:超详细 Matrix Synapse 部署教程:搭建去中心化加密聊天服务器 - 白鱼小栈

但是这个博主使用的是默认的 SQLlite 数据库,虽然简单但是性能十分拉垮,所以我们可以安装官方给出的文档将其切换成 Postgres

首先请按照我给的 docker-compose.yml 起好容器:

services:
  synapse:
    image: matrixdotorg/synapse:latest
    container_name: synapse
    restart: unless-stopped
    healthcheck:
       test: ["CMD-SHELL", "curl -s localhost:8008/health || exit 1"]
    ports:
      - "8008:8008"
    volumes:
      - ./data:/data
    environment:
      VIRTUAL_HOST: matrix.example.com
      VIRTUAL_PORT: 8008
      LETSENCRYPT_HOST: matrix.example.com
      SYNAPSE_SERVER_NAME: matrix.example.com
      SYNAPSE_REPORT_STATS: "no"
    networks:
      - matrix_network

  db:
    image: postgres13
    container_name: synapse_db
    restart: unless-stopped
    environment:
      POSTGRES_USER: synapse
      POSTGRES_PASSWORD: synapse
      POSTGRES_DB: synapse
      POSTGRES_INITDB_ARGS: "--locale=C --encoding=UTF8"
    volumes:
      - ./db_data:/var/lib/postgresql/data
    networks:
      - matrix_network

networks:
  matrix_network: {}

之后需要修改 homeserver.yaml,之后修改 database 字段为:

database:
  name: psycopg2
  args:
    user: synapse
    password: synapse
    database: synapse
    host: synapse_db
    port: 5432
    cp_min: 5 
    cp_max: 10

其他按照博主给的配置就可以了,之后打开 8008 端口,看看是否会出现欢迎界面

其返回的路径为:http://<ip>/_matrix/static/

配置反向代理

官方提供了 Nginx 和 Caddy 两种配置文件:Using a reverse proxy with Synapse

nginx

server {
    listen 443 ssl;
    listen [::]:443 ssl;

    # For the federation port
    listen 8448 ssl default_server;
    listen [::]:8448 ssl default_server;

    server_name matrix.example.com;

    location ~ ^(/_matrix|/_synapse/client) {
        # note: do not add a path (even a single /) after the port in `proxy_pass`,
        # otherwise nginx will canonicalise the URI and cause signature verification
        # errors.
        proxy_pass http://localhost:8008;
        proxy_set_header X-Forwarded-For $remote_addr;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header Host $host:$server_port;

        # Nginx by default only allows file uploads up to 1M in size
        # Increase client_max_body_size to match max_upload_size defined in homeserver.yaml
        client_max_body_size 50M;

    # Synapse responses may be chunked, which is an HTTP/1.1 feature.
    proxy_http_version 1.1;
    }
}

caddy,在这里我们不使用官方的配置文件,不大好用

matrix.example.com {
    reverse_proxy 127.0.0.1:8008
}

官方提供的配置文件是:

matrix.example.com {
  reverse_proxy /_matrix/* localhost:8008
  reverse_proxy /_synapse/client/* localhost:8008
}

example.com:8448 {
  reverse_proxy /_matrix/* localhost:8008
}

但在实际的使用中,路径并不会被正确路由,按照我自己使用的方法进行路由可能存在一些风险,还是建议用 Nginx 进行反代

在这里我们需要指定来自联邦(Federation)的流量

image

在这里我不打算使用 8448 端口,因此需要进行声明,要使用这种方法,需要配置 https://<server_name> 处的服务器为 https://<server_name>/.well-known/matrix/server 处的文件提供服务

homeserver.yaml 中,我们可以指定字段来提供服务

serve_server_wellknown: true

之后使用 curl 进行测试

$ curl -i https://<server_name>/.well-known/matrix/server
HTTP/2 200 
alt-svc: h3=":443"; ma=2592000
content-type: application/json
date: Wed, 05 Feb 2025 03:27:35 GMT
server: Caddy
server: Synapse/1.123.0
strict-transport-security: max-age=31536000; includeSubDomains; preload
content-length: 34

{"m.server":"<server_name>:443"}%  

配置 Sydent

Sydent 是 Matrix 协议中的身份服务器,它允许用户通过邮件和电话号码发现对方,尽管官方并不推荐用户自己搭建 Sydent 服务器,但是为了完整展示全过程,我还是在这里贴出参考步骤

直接使用 docker compose 进行部署

services:
  sydent:
    image: matrixdotorg/sydent:latest
    container_name: matrix_sydent
    environment:
    - SYDENT_SERVER_NAME=
    volumes:
    - ./sydent_data:/data
    ports:
    - "8090:8090"
    restart: unless-stopped

之后使用 Caddy 进行反代,在客户端中添加服务器

配置 Sliding Sync

在一些比较新的客户端,如 Element X 中,要求服务器必须支持 Sliding Sync,在这里我们还是使用 docker compose 来进行部署

services:
  postgres:
    image: postgres:13
    container_name: sliding_sync_db
    environment:
      POSTGRES_DB: syncv3
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: ${DATABASE_PASSWORD}
    volumes:
      - ./data_db:/var/lib/postgresql/data
  sliding_sync:
    image: ghcr.io/matrix-org/sliding-sync:latest
    container_name: sliding_sync
    depends_on:
      - postgres
    ports:
      - "8009:8009"
    environment:
      SYNCV3_SERVER: "https://matrix.example.com"
      SYNCV3_DB: "postgres://postgres:${DATABASE_PASSWORD}@postgres:5432/syncv3?sslmode=disable"
      SYNCV3_SECRET: ${SYNCV3_SECRET}
      SYNCV3_BINDADDR: ":8009"

需要创建一个 .env 文件,在里面填入DATABASE_PASSWORDSYNCV3_SECRET

DATABASE_PASSWORD=password
SYNCV3_SECRET=password

同样需要配置反代,除此之外,在 Synapse 服务器的 homeserver.yaml 中也要配置对于的字段,来让服务器在 https://matrix.example.com/.well-known/matrix/client 返回一个 JSON 数组,来声明服务器的 Sliding Sync 的服务

public_baseurl: "https://matrix.example.com"
extra_well_known_client_content : # 用来配置 /.well-known/matrix/client
  org.matrix.msc3575.proxy: https://sliding.example.com

重启服务,使用 curl 进行检查

$ curl -i https://matrix.example.com/.well-known/matrix/client
HTTP/2 200 
access-control-allow-headers: X-Requested-With, Content-Type, Authorization, Date
access-control-allow-methods: GET, HEAD, POST, PUT, DELETE, OPTIONS
access-control-allow-origin: *
access-control-expose-headers: Synapse-Trace-Id, Server
alt-svc: h3=":443"; ma=2592000
cache-control: no-cache, no-store, must-revalidate
content-type: application/json
date: Wed, 05 Feb 2025 03:45:24 GMT
server: Caddy
server: Synapse/1.123.0
strict-transport-security: max-age=31536000; includeSubDomains; preload

{"m.homeserver":{"base_url":"https://matrix.example.com/"},"org.matrix.msc3575.proxy":"https://sliding.example.com"}%   

至此,我们可以使用官方提供的工具来检查是否配置正常,能不能和 Matrix 联邦上的其他服务器进行通信:Matrix Federation Tester

TRUN 服务器

Matrix 是支持 VoIP 通话的,你可以尝试使用官方提供的 turn.matrix.org,但是这样有 IP 地址泄漏风险,而且该服务在大陆存在网络问题,因此我建议进行自建

官方文档也提供了相应的指导:Configuring a Turn Server - Synapse,在这里我使用 coturn 作为 TURN 服务器

coturn 提供了包管理、docker和本地编译三种方式,由于我使用的是 Debian,提供了包

sudo apt install coturn

配置文件在 /etc/turnserver.yaml,在正式修改之前需要进行备份

cp /etc/turnserver.conf /etc/turnserver.conf.bak

基础配置如下:

# 填写你的 TURN 服务域名
realm=turn.example.com

# 启用服务器
listening-port=3478
tls-listening-port=5349

# 随机密码
cli-password=password

# 指定外网IP(重要!替换为你的公网IP)
external-ip=<ip>

# UDP端口范围(建议保留默认)
min-port=49152
max-port=65535

# 测试用户,实际使用需要删除!!
user=username:password

# 动态密钥 使用 pwgen -s 64 1 生成
use-auth-secret
static-auth-secret=password

# TLS证书配置(必须)
cert=/etc/letsencrypt/live/turn.example.com/fullchain.pem
pkey=/etc/letsencrypt/live/turn.example.com/privkey.pem

# 日志配置
log-file=/var/log/turn.log
verbose

# VoIP traffic is all UDP. There is no reason to let users connect to arbitrary TCP endpoints via the relay.
no-tcp-relay

# don't let the relay ever try to connect to private IP address ranges within your network (if any)
# given the turn server is likely behind your firewall, remember to include any privileged public IPs too.
denied-peer-ip=10.0.0.0-10.255.255.255
denied-peer-ip=192.168.0.0-192.168.255.255
denied-peer-ip=172.16.0.0-172.31.255.255

# recommended additional local peers to block, to mitigate external access to internal services.
# https://www.rtcsec.com/article/slack-webrtc-turn-compromise-and-bug-bounty/#how-to-fix-an-open-turn-relay-to-address-this-vulnerability
no-multicast-peers
denied-peer-ip=0.0.0.0-0.255.255.255
denied-peer-ip=100.64.0.0-100.127.255.255
denied-peer-ip=127.0.0.0-127.255.255.255
denied-peer-ip=169.254.0.0-169.254.255.255
denied-peer-ip=192.0.0.0-192.0.0.255
denied-peer-ip=192.0.2.0-192.0.2.255
denied-peer-ip=192.88.99.0-192.88.99.255
denied-peer-ip=198.18.0.0-198.19.255.255
denied-peer-ip=198.51.100.0-198.51.100.255
denied-peer-ip=203.0.113.0-203.0.113.255
denied-peer-ip=240.0.0.0-255.255.255.255

# special case the turn server itself so that client->TURN->TURN->client flows work
# this should be one of the turn server's listening IPs
allowed-peer-ip=10.0.0.1

# consider whether you want to limit the quota of relayed streams per user (or total) to avoid risk of DoS.
user-quota=12 # 4 streams per video call, so 12 streams = 3 simultaneous relayed calls per user.
total-quota=1200

启动服务:

systemctl start coturn

设置开机启动:

systemctl enable coturn

虽然有很多教程提出可以使用 Trickle ICE 测试服务是否可用,但是我在实际使用过程中发现不太好用,因此使用 coturn 提供的测试工具 turnutils_uclient

turnutils_uclient -v -y -u username -w password <ip>

链接成功的关键点:

  1. 成功的分配响应:多次发送的“allocate response received: success”表明客户端成功地从TURN服务器获得了中继地址。
  2. 通道绑定成功:输出中显示“channel bind sent”和“cb response received: success”,这表明通道绑定请求也成功。
  3. 消息传输统计:在消息客户端(mclient)部分,显示了发送和接收的消息数量,以及没有丢包(Total lost packets 0),这表明数据传输正常。
  4. 延迟和抖动:输出中提供的平均往返延迟和抖动值(Average round trip delay 250.75 ms; Average jitter 1.35 ms)也在合理范围内,表明连接质量良好。

之后需要设置 TLS/DTLS,不要使用来自 Let's Encrypt 的证书,因为所有使用 Chromium's WebRTC 的 Matrix 客户端都无法使用

申请 ZeroSSL 即可,ZeroSSL 提供了自动化工具:GitHub - zerossl/zerossl-bot: The repository for the ZeroSSL certbot wrapper

apt install certbot

bash <(wget -q -O - https://github.com/zerossl/zerossl-bot/raw/master/get-zerosslbot.sh)

sudo zerossl-bot certonly --standalone -m youremail@example.com -d turn.example.com

申请成功后证书会下放到 /etc/letsencrypt/archive/turn.example.com

直接运行会出现问题,因为 coturn 进程没有权限去读取相应的证书文件,在cannot start TLS and DTLS listeners because private key file is not set properly · Issue #1139 · coturn/coturn中可以看到

解决方法有两种,将文件所有权设置为 644

或者以 root 用户运行 coturn

修改服务配置:

sudo nano /lib/systemd/system/coturn.service

修改配置为:

[Unit]
Description=coTURN STUN/TURN Server
Documentation=man:coturn(1) man:turnadmin(1) man:turnserver(1)
After=network.target

[Service]
User=root
Group=root
Type=notify
ExecStart=/usr/bin/turnserver -c /etc/turnserver.conf --pidfile=
Restart=on-failure
InaccessibleDirectories=/home
PrivateTmp=yes

[Install]
WantedBy=multi-user.target

重启服务:

sudo systemctl daemon-reload
sudo systemctl restart coturn

查看日志是否正常

sudo journalctl -u coturn -f

可以使用 openssl 测试 TLS 是否正常

openssl s_client -connect turn.example.com:5349

可以看到我这里的 CA 确实是 ZeroSSL

之后需要在 Synapse 中的 homeserver.yaml 配置

turn_uris: [ "turn:turn.example.com?transport=udp", "turn:turn.example.com?transport=tcp" ]
turn_shared_secret: "password"
turn_user_lifetime: 86400000
turn_allow_guests: true

官方文档可以参考:Configuring a Turn Server - Synapse

总结

Matrix 是一个很牛逼的东西,希望未来的发展越来越好,能加入和 tg 类似的贴纸包,各种功能能够更完善一下,管理集成是什么东西还是不知道

image

目前我这样配置还是不能支持 Element X 的创建用户,原因目前为止,还有待进一步解决

此作者没有提供个人介绍
最后更新于 2025-02-05