Matrix synapse
EN CHANTIER
Article en cours d'écriture et/ou de test. Certains éléments peuvent être incomplets et mener à un résultat non fonctionnel.Merci de ne pas rager.
Synapse est une implémentation serveur libre (licence Apache 2.0) du protocole Matrix écrit en Python. Le projet, initié en 2014, est maintenu par la fondation Matrix.org et passe en version stable (1.0.0) en 2019. Il est disponible dans les dépôts Bullseye-Backports et Testing de Debian.
Il permet la communication électronique textuelle, orale et vidéo entre plusieurs interlocuteurs au travers de réseaux IP. Il propose en outre la possibilité d'envoyer des fichiers et de partager les écrans des correspondants. Une attention toute particulière est porté sur la sécurité des échanges avec un système de chiffrement de bout en bout obligatoire, tant entre clients (pair à pair) que lors de transactions avec le serveur (client/serveur).
Il est nécessaire de permettre la communication vers les ports suivants :
- Fédération Synapse : 8448 TCP
- TURN : 3478 TCP/UDP
Service Synapse
Installation
Ajout des dépôts Backports pour Debian 11
echo "deb http://ftp2.fr.debian.org/debian bullseye-backports main" >> /etc/apt/sources.list
apt update
apt install --no-install-recommends -t bullseye-backports matrix-synapse
La réponse aux questions n'a pas d'importance car les fichiers de configuration seront re-générés plus loin.
Configuration
Le domaine utilisé pour l'exemple est le suivant
export DNS_SYNAPSE=synapse.exemple.fr
Génération des fichiers configuration et de la clé de signature
synapse_generate_config --server-name ${DNS_SYNAPSE} --config-dir /etc/matrix-synapse --data-dir /etc/matrix-synapse/ --report-stats no --generate-secrets -o /etc/matrix-synapse/homeserver.yaml
synapse_generate_log_config -o /etc/matrix-synapse/${DNS_SYNAPSE}.log.config
synapse_generate_signing_key -o /etc/matrix-synapse/${DNS_SYNAPSE}.signing.key
echo 'report_stats: false' > /etc/matrix-synapse/conf.d/report_stats.yaml
echo "server_name: \"${DNS_SYNAPSE}\"" > /etc/matrix-synapse/conf.d/server_name.yaml
Écouter les requêtes clientes sur toutes les adresses IP du serveur
sed -i "s/bind_addresses: \[.*\]/bind_addresses: ['0.0.0.0']/g" /etc/matrix-synapse/homeserver.yaml
Redémarrer le service
systemctl restart matrix-synapse.service
Vous devriez voir un port 8008 TCP en écoute avec un ss -ltn
. Celui-ci permet aux outils d'administrations d'utiliser les API de Synapse pour interagir avec lui.
Gestion des utilisateurs
Actuellement, seule la création d'un utilisateur est possible avec les outils fournis. Leur suppression ou modification (ou même leur listage) n'est pas supporté (oui c'est aberrant). Ce sujet est traité dans ce ticket.
La syntaxe d'un utilisateurs dans les différents clients Matrix est @michel:synapse.exemple.fr
. Ceci est utile pour en ajouter comme contact depuis un logiciel client (pourquoi faire simple ?).
Création d'un utilisateur
synapse_register_new_matrix_user http://127.0.0.1:8008 -c /etc/matrix-synapse/homeserver.yaml
Source de la section
Service TURN
Dans la mesure où le vrai monde est peuplé de NAT à profusion et qu'aucun protocole de communication en temps réel ne sais gérer cette situation correctement (la raison m'échappe toujours...), il est indispensable d'employer un service mitigeant cette contrainte. Ceci est le rôle des protocoles TURN/STUN implémenté dans le logiciel Coturn.
Installation
Le paquet est disponible dans les dépôts Sable
apt install --no-install-recommends coturn
Configuration
Les informations spécifiques à l'instance de cette documentations seront les suivantes
export DNS_COTURN=turn.exemple.fr
export SECRET_COTURN=$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 64 | head -n 1)
export IP_EXTERNE=$(wget -qO - ifconfig.co)
export IP_INTERNE=192.168.0.100
Le fichier de configuration du service se composera comme suit
cat << _EOF_ > /etc/turnserver.conf
use-auth-secret
static-auth-secret=${SECRET_COTURN}
realm=${DNS_COTURN}
# Le trafic VoIP est entièrement UDP. Il n'y a aucune raison de laisser les utilisateurs se connecter à des points d'extrémité TCP arbitraires via le relais
no-tcp-relay
# Ne laissez pas le relais essayer de se connecter à des plages d'adresses IP privées au sein de votre réseau (s'il y en a)
# Étant donné que le serveur tournant est probablement derrière votre pare-feu, n'oubliez pas d'inclure également toutes les adresses IP publiques privilégiées
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
# À recommandé, blocage de pairs locaux supplémentaires, afin de limiter l'accès externe aux services internes
# 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
# Cas particulier : le serveur TURN lui-même pour que les flux client->TURN->TURN->client fonctionnent
# Il doit s'agir de l'une des adresses IP d'écoute du serveur TURN
allowed-peer-ip=${IP_INTERNE}
# Examinez si vous souhaitez limiter le quota de flux relayés par utilisateur (ou total) pour éviter les risques de DoS
user-quota=12 # 4 flux par appel vidéo, donc 12 flux = 3 appels relayés simultanés par utilisateur
total-quota=1200
# Certificats TLS, y compris les certificats intermédiaires
# Pour les certificats Let's Encrypt, utilisez 'fullchain.pem' ici
cert=/srv/tls/corturn.pem
# Fichier TLS de clé privée
pkey=/srv/tls/corturn.key
# Assurez-vous que les lignes de configuration qui désactivent TLS/DTLS sont commentées ou supprimées.
#no-tls
#no-dtls
external-ip=${IP_EXTERNE}
listening-ip=${IP_INTERNE}
_EOF_
Support du TLS
Créer le répertoire d'accueil des éléments de chiffrement
mkdir /srv/tls
Ces éléments peuvent être issus d'une autorité de certification publique comme Letsencrypt (mettre la clé et le certificat chaînés) ou privée, via OpenSSL par exemple.
chown -R root:root /srv/tls
chmod 500 /srv/tls
chmod 400 /srv/tls/*
Redémarrer le service
systemctl restart coturn.service
Le service écoute sur le port 3478 TCP/UDP.
Il est à présent possible de configurer Synapse afin qu'il informe les clients d'utiliser notre service TURN lors de l'établissement des communications pair à pair entre eux.
cat << _EOF_ >> /etc/matrix-synapse/homeserver.yaml
turn_uris: [ "turn:${DNS_COTURN}?transport=udp", "turn:${DNS_COTURN}?transport=tcp" ]
turn_shared_secret: "${SECRET_COTURN}"
turn_user_lifetime: 86400000
turn_allow_guests: True
_EOF_
systemctl restart matrix-synapse.service
Enregistrement DNS
Cette section est totalement facultative et n'apporte rien. Il existe peut-être une configuration de Synapse permettant de trouver automatiquement le serveur TURN via DNS...
Enregistrements DNS SRV (à ajouter dans la configuration de votre zone)
_stun._udp 10800 IN SRV 0 5 3478 exemple.fr.
_turn._udp 10800 IN SRV 0 5 3478 exemple.fr.
Il est possible de requêter le serveur de noms sur ces champs précis via les commandes suivantes
dig +short _stun._udp._tcp 10800 IN SRV 0 5 3478 exemple.fr.
dig +short _turn._udp._tcp 10800 IN SRV 0 5 3478 exemple.fr.
Test de fonctionnement
Voici une méthode permettant de tester le fonctionnement du service en ligne de commande. Elle peut aider à deceler des problèmes simplement.
turnutils_uclient -p 3478 -W <CLÉ_SERVEUR_TURN> -v -y turn.exemple.fr
Source de la section
Client WEB Element
Element est un client WEB pour Matrix. Anciennement connu sous le nom de Riot, il existe aussi sous forme d'application IOS et Android.
Installation
N'étant pas dans les dépôts Debian, nous utiliserons la version Git
apt install --no-install-recommends apache2
wget https://github.com/vector-im/element-web/releases/download/v1.10.14/element-v1.10.14.tar.gz -P /tmp
tar xf /tmp/element-v1.10.14.tar.gz -C /var/www/
ln -s /var/www/element-v1.10.14/ /var/www/element
chown -R www-data: /var/www/element*
Configuration
L'hôte virtuel d'Apache doit pointer vers le programme
cat << '_EOF_' > /etc/apache2/sites-available/element.conf
<VirtualHost *:80>
ServerAdmin webmaster@localhost
DocumentRoot /var/www/element
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>
_EOF_
Désactivation de l'hôte virtuel par défaut et activation du nouveau
a2dissite 000-default.conf
a2ensite element.conf
Le domaine utilisé sera le suivant
export DNS_ELEMENT=element.exemple.fr
La configuration de notre instance sera celle-ci
cat << _EOF_ > /var/www/element/config.json
{
"default_server_config": {
"m.homeserver": {
"base_url": "https://${DNS_SYNAPSE}",
"server_name": "${DNS_SYNAPSE}"
},
"m.identity_server": {
"base_url": "https://vector.im"
}
},
"disable_custom_urls": false,
"disable_guests": false,
"disable_login_language_selector": false,
"disable_3pid_login": false,
"brand": "Element",
"bug_report_endpoint_url": "https://element.io/bugreports/submit",
"uisi_autorageshake_app": "element-auto-uisi",
"default_country_code": "FR",
"show_labs_settings": false,
"features": { },
"default_federate": false,
"default_theme": "light",
"enable_presence_by_hs_url": {
"https://matrix.org": false,
"https://matrix-client.matrix.org": false
},
"setting_defaults": {
"breadcrumbs": true
},
"features": {
"feature_you_want_to_turn_on": true,
"feature_you_want_to_keep_off": false
}
}
_EOF_
Redémarrer Apache
systemctl restart apache2.service
Source
Fédération
Un des atouts de cette solution est la décentralisation. En effet, il est possible d'interconnecter plusieurs serveurs afin de permettre la communication d'utilisateurs enregistrés sur des instances différentes. Ces interconnexions doivent êtres explicitement spécifiées dans la configuration de Synapse.
Le domaine du serveur distant sera le suivant
export DNS_SRV_DISTANT_SYNAPSE=synapse.toto.fr
Ajout de celui-ci dans la configuration de Synapse (ceci doit être fait des deux côtés)
sed -i "s/^trusted_key_servers:/trusted_key_servers:\n - server_name: \"${DNS_SRV_DISTANT_SYNAPSE}\"/g" /etc/matrix-synapse/homeserver.yaml
sed -i "s/^#federation_domain_whitelist:/federation_domain_whitelist:\n - ${DNS_SRV_DISTANT_SYNAPSE}/g" /etc/matrix-synapse/homeserver.yaml
systemctl restart matrix-synapse.service
Cas d'une connexion mandaté
Dans la mesure où il est courant qu'un serveur ne soit jamais relié directement à Internet (comprendre par la qu'il ne dispose pas d'IP publique), le cas d'un mandataire inverse officiant entre les clients du WAN et le serveur Element du LAN est le plus probable. Ce point complique la transparence des échanges entre les machines et doit être géré au niveau de cet intermédiaire. Deux services ont étés testés en production avec succès. Leur configuration est donnée ci-après.
Traefik
Ajout d'un point d'entrer dans Traefik pour le port 8448
cat << _EOF_ >> /etc/traefik/config/vhosts/matrix.toml
[http]
[http.routers]
[http.routers.synapse]
entryPoints = ["websecure"]
rule = "Host(\`${DNS_SYNAPSE}\`)"
service = "synapse"
[http.routers.synapse.tls]
certResolver = "myresolver"
[http.routers.element]
entryPoints = ["websecure"]
rule = "Host(\`${DNS_ELEMENT}\`)"
service = "element"
[http.routers.element.tls]
certResolver = "myresolver"
[http.routers.synapsefed]
entryPoints = ["synapsefed"]
rule = "Host(\`${DNS_SYNAPSE}\`)"
service = "synapse"
[http.routers.synapsefed.tls]
certResolver = "myresolver"
[http.services]
[http.services.synapse.loadBalancer]
[[http.services.synapse.loadBalancer.servers]]
url = "http://${IP_INTERNE}:8008"
[http.services.element.loadBalancer]
[[http.services.element.loadBalancer.servers]]
url = "http://${IP_INTERNE}:80"
_EOF_
HAProxy
cat << _EOF_ >> /etc/haproxy/haproxy.cfg
frontend matrix-federation
bind *:8448,[::]:8448 ssl crt /etc/haproxy/tls/ alpn h2,http/1.1
http-request set-header X-Forwarded-Proto https if { ssl_fc }
http-request set-header X-Forwarded-Proto http if !{ ssl_fc }
http-request set-header X-Forwarded-For %[src]
default_backend synapse
frontend https
http-response add-header X-Frame-Options SAMEORIGIN
bind :443 ssl crt /etc/haproxy/tls/ alpn h2,http/1.1
acl host_synapse hdr(host) -i synapse.exemple.fr
use_backend synapse if host_synapse
<backend synapse
option forwardfor except 127.0.0.1
option http-server-close
server synapse 192.168.170.178:8008 check maxconn 32
_EOF_
Débogage
La configuration de Synapse est quelque peu imbuvable et les problèmes, difficiles à corriger. Il est possible de s'appuyer sur les journaux du service afin de cibler l'origine des disfonctionnements.
tail -f /var/log/matrix-synapse/homeserver.log
Un outil permettant de determiner les caractéristiques du serveur est disponible à l'adresse https://federationtester.matrix.org/. Il peut s'avérer d'une aide précisieuse (surtout le rapport Json).