Installer son serveur XMPP avec Prosody

Publié le 21/02/2021, dans informatique, xmpp
Article mis à jour le 18/06/2023 pour Prosody 0.12.3
Aujourd'hui, un article pour mettre en place son serveur de discussions instantanées pour parler avec ses ami·e·s de manière sécurisée, libre et décentralisée.
Il existe de nombreuses solutions pour faire de la discussion instantanée, mais les avoir sur ses propres serveurs permet de regagner un peu le contrôle de nos conversations. Pour cela XMPP est un ensemble de protocoles standardisés par l'IETF utilisé depuis de nombreuses années au sein de plusieurs technologies. On le retrouvait par exemple derrière Google Talk, le tchat de Facebook ou encore de nos jours derrière le tchat de League of Legend et Nintendo Switch. XMPP a l'avantage d'être extensible et permet de faire de la communication de manière décentralisée, contrairement à d'autres logiciels comme Signal (qui pour une raison qui j'ignore est adoré par plein de libristes alors qu'il souffre de nombreux problèmes que ces derniers rejetent habituellement).
Avec XMPP comme avec de nombreux autres systèmes décentralisés l'identifiant d'un compte est sous la forme nom@domaine et tous les comptes peuvent communiquer entre eux qu'ils soient sur la même instance XMPP ou non.
Pour commencer
XMPP étant extensible, il permet de nombreuses choses. Je vais donc préciser un peu l'étendue de cet article. Ici, le but sera de mettre en place un serveur permettant uniquement les fonctionnalités que je considère comme étant « de base » de la messagerie instantanée en 2021, à savoir : pouvoir avoir une liste de contacts, envoyer/recevoir des messages, faire des discussions de groupe, envoyer/recevoir des fichiers, et éventuellement passer/recevoir des appels audio/vidéo.
Je vais pour cela utiliser le logiciel Prosody. Il en existe bien d'autres, comme ejabberd qui est bien quand on a beaucoup d'utilisateurices, mais le but ici sera de mettre en place un petit serveur pour les membres d'une famille ou un groupe d'ami·e·s par exemple. Prosody est parfait pour ça et consomme peu de ressources.
Je vais également utiliser Coturn qui permettra de gérer le NAT pour faire de l'audio et de la vidéo.
Dans cet article je vais mettre en place un serveur Prosody ~~0.11.2 sur une Debian 10.8~~ 0.12.3 sur une Debian 11.6. Je pars du principe que l'on a un nom de domaine example.com.
On aura besoin de 4 noms de domaine au total :
- example.com : le nom de notre domaine de base
- conf.example.com : le nom pour les discussions de groupe
- proxy.xmpp.example.com : le nom pour le proxy sock5 (qui permet de simplifier les choses pour les gens derrière un NAT)
- xmpp.example.com : le nom pour le proxy HTTP pour l'envoi de fichiers
Dans cet article, tous ces noms pointent vers le même serveur Prosody.
Nous aurons aussi besoin d'une base de données : par défaut Prosody utilise une base sqlite3 mais ici je vais utiliser une base MySQL.
Installation, enregistrements DNS et pare-feu
On commence par ajouter le Dépôt Prosody pour Debian en suivant leur documentation.
Puis on installe Prosody, ses modules de base et le driver pour notre base de données (MySQL pour moi, mais vous pouvez utiliser sqlite3 ou postgresql) :
# apt install prosody prosody-modules lua-dbi-mysql
On crée une base de données nommée prosody et un utilisateur du même nom ayant les droits sur la base.
On va cloner le dépôt qui contient des modules supplémentaires, car on va en utiliser par la suite, ça se fait via Mercurial, donc on installe déjà :
# apt install mercurial
On clone alors le dépôt dans /usr/local/lib/prosody/modules :
# hg clone https://hg.prosody.im/prosody-modules/ /usr/local/lib/prosody/modules
On devra renseigner ce chemin de modules en plus de celui déjà présent dans la configuration de Prosody.
Enregistrements DNS
On crée ensuite dans notre zone DNS les deux enregistrements SRV suivants :
_xmpp-client._tcp IN SRV 0 5 5222 example.com.
_xmpps-client._tcp IN SRV 0 5 5223 example.com.
_xmpp-server._tcp IN SRV 0 5 5269 example.com.
_xmpps-server._tcp IN SRV 0 5 5270 example.com.
Le premier indique aux clients XMPP quels sont la priorité (0), le poids (5), le port (5222) et le nom (example.com) des serveurs XMPP pour ce domaine (ici nous en n'avons qu'un seul).
Le second indique exactement la même chose mais pour les serveurs XMPP avec qui notre serveur échangera.
Pare-feu
On va devoir ouvrir 7 ports TCP sur notre serveur (documentation) :
- 5222 : Port sur lequel les clients parlent aux serveurs (aussi nommé c2s)
- 5223 : Port sur lequel les clients parlent aux serveurs en TLS direct (aussi nommé c2s)
- 5269 : Port sur lequel les serveurs parlent aux autres serveurs (aussi nommé s2s)
- 5270 : Port sur lequel les serveurs parlent aux autres serveurs en TLS direct (aussi nommé s2s)
- 5280 : Port du proxy HTTP BOSH
- 5281 : Port du proxy HTTP BOSH sur TLS
- 5000 : Port du proxy socks5 pour les transferts
Configuration générale
On peut modifier la configuration du serveur dans /etc/prosody/prosody.cfg.lua pour changer les valeurs par défaut pour notre serveur si on le souhaite.
On commence par indiquer qui sont les administrateurices et qui contacter en cas de soucis :
admins = { "moi@example.com" }
contact_info = {
abuse = { "mailto:abuse@example.com" };
admin = { "mailto:abuse@example.com" };
feedback = { "mailto:abuse@example.com" };
sales = { "mailto:abuse@example.com" };
security = { "mailto:abuse@example.com" };
support = { "mailto:abuse@example.com" };
};
On y modifie la variable plugin_path pour ajouter notre chemin de modules clonés plus tôt :
plugin_paths = { "/usr/local/lib/prosody/modules" }
On décommente la ligne pour utiliser libevent :
network_backend = "event"
On active les modules utiles :
modules_enabled = {
"admin_adhoc";
"announce";
"blocklist";
"bookmarks";
"bosh";
"carbons";
"cloud_notify";
"csi";
"dialback";
"disco";
"filter_chatstates";
"mam";
"offline";
"pep";
"ping";
"posix";
"private";
"proxy65";
"register";
"roster";
"saslauth";
"server_contact_info";
"smacks";
"throttle_presence";
"time";
"tls";
"turncredentials";
"uptime";
"vcard4";
"vcard_legacy";
"version";
"watchregistrations";
"welcome";
}
On indique ensuite les ports de connections TLS direct :
c2s_direct_tls_ports = { 5223 };
s2s_direct_tls_ports = { 5270 };
Ici on voit que j'ai désactivé l'inscription depuis l'extérieur, car je ne veux pas que n'importe qui puisse s'inscrire sur mon instance.
Comme on veut aussi faire de l'audio/vidéo, on ajoute les informations Turn, on verra par la suite comment installer Coturn :
turncredentials_host = "example.com"
turncredentials_secret = "un-super-secret"
turncredentials_port = 3478
On indique qu'on utilise du SQL et on ajoute les infos pour se connecter à la base :
storage = "sql"
sql = { driver = "MySQL", database = "prosody", username = "prosody", password = "prosody-password", host = "localhost" }
pep permet de publier des infos (la musique qu'on écoute, etc), on indique ici un maximum d'élements :
pep_max_items = 10000
On indique le certificat pour le proxy HTTP :
https_certificate = "/etc/prosody/certs/example.com.crt"
Concernant les certificats TLS, Prosody va automatiquement les chercher dans /etc/prosody/certs/, il y a une documentation pour ça que je vous recommande de lire selon votre cas d'usage (j'utilise "Automatic certificate import" pour récupérer mes certificats), il y en a même une spécifique à Let's Encrypt.
On peut également mettre les logs via syslog avec cette configuration :
log = {
-- Log files (change 'info' to 'debug' for debug logs):
info = "/var/log/prosody/prosody.log";
error = "/var/log/prosody/prosody.err";
-- Syslog:
{ levels = { "error" }; to = "syslog"; };
}
Configuration du virtualhost
On va à présent créer le fichier de configuration de notre domaine example.com : /etc/prosody/conf.avail/example.com.cfg.lua.
On fait un lien symbolique pour faire pointer /etc/prosody/conf.d/example.com.cfg.lua vers notre configuration dans conf.avail :
# ln -s /etc/prosody/conf.avail/example.com.cfg.lua /etc/prosody/conf.d/example.com.cfg.lua
Et on l'édite :
VirtualHost "example.com"
-- Assign this host a certificate for TLS, otherwise it would use the one
-- set in the global section (if any).
ssl = {
key = "/etc/prosody/certs/example.com.key";
certificate = "/etc/prosody/certs/example.com.crt";
ciphers = "EECDH+AES:+AES128:+AES256:+SHA256:+SHA512";
dhparam = "/etc/prosody/certs/dh-2048.pem";
options = {
"cipher_server_preference",
"no_sslv2",
"no_sslv3",
"no_ticket",
"single_dh_use",
"single_ecdh_use"
};
}
------ Components ------
---Set up a MUC (multi-user chat) room server on conference.example.com:
Component "conf.example.com" "muc"
modules_enabled = { "muc_mam", "vcard_muc" }
-- Set up a SOCKS5 bytestream proxy for server-proxied file transfers:
Component "proxy.xmpp.example.com" "proxy65"
proxy65_address = "example.com"
proxy65_acl = { "example.com" }
Component "xmpp.example.com" "http_upload"
On génère notre DH (documentation) :
# openssl dhparam -out /etc/prosody/certs/dh-2048.pem 2048
On vérifie notre configuration avec la commande :
# prosodyctl check config
On donne les droits à l'utilisateur prosody sur le dossier qui contiendra les fichiers envoyés par les utilisateurs :
# chown -R prosody:prosody /var/lib/prosody/http_upload
Si tout est ok on relance prosody :
# systemctl restart prosody
Et on vérifie dans les logs que tout se passe bien :
# tail -f /var/log/prosody/prosody.log
Voici typiquement les logs après le démarrage du serveur :
startup info Hello and welcome to Prosody version 0.12.3
startup info Prosody is using the libevent epoll backend for connection handling
portmanager info Activated service 'http' on [127.0.0.1]:5280, [::1]:5280
portmanager info Activated service 'https' on [*]:5281, [::]:5281
xmpp.example.com:http info Serving 'upload' at https://xmpp.example.com:5281/upload
xmpp.example.com:http_upload info URL: <https://xmpp.example.com:5281/upload> - Ensure this can be reached by users
xmpp.example.com:http_upload info Storage path: '/data/1/xmpp/prosody/http_upload'
portmanager info Activated service 's2s' on [*]:5269, [::]:5269
portmanager info Activated service 's2s_direct_tls' on [*]:5270, [::]:5270
xmpp.example.com:tls info Certificates loaded
portmanager info Activated service 'c2s' on [*]:5222, [::]:5222
portmanager info Activated service 'c2s_direct_tls' on [*]:5223, [::]:5223
portmanager info Activated service 'legacy_ssl' on no ports
mod_http info Serving 'websocket' at https://*:5281/xmpp-websocket
example.com:http info Serving 'websocket' at https://example.com:5281/xmpp-websocket
portmanager info Activated service 'proxy65' on [*]:5000, [::]:5000
example.com:tls info Certificates loaded
example.com:cloud_notify info Module loaded
portmanager info Activated service 'console' on [127.0.0.1]:5582, [::1]:5582
mod_http info Serving 'bosh' at https://*:5281/http-bind
example.com:http info Serving 'bosh' at https://example.com:5281/http-bind
conf.example.com:tls info Certificates loaded
localhost:http info Serving 'websocket' at https://localhost:5281/xmpp-websocket
localhost:tls info Certificates loaded
localhost:cloud_notify info Module loaded
localhost:http info Serving 'bosh' at https://localhost:5281/http-bind
proxy.xmpp.example.com:tls info Certificates loaded
Ajout des utilisateurices et tests
Comme ce serveur est uniquement pour un petit nombre je n'ai pas autorisé l'enregistrement depuis l'extérieur, il faut donc créer les comptes à la main (documentation) :
# prosodyctl adduser codimp@example.com
Ensuite on peut se connecter avec le client XMPP de son choix (j'utilise Gajim sur ordinateur et Conversations sur Android) et tester que tout fonctionne bien.
Si vous préferez les interfaces web il y a un module d'administration web.
Gérer l'audio et la vidéo
Si on souhaite aussi faire de l'audio et de la vidéo on va installer Coturn, la documentation explique bien comment faire.
Conclusion
On a maintenant notre petit serveur de messagerie instantanée et on peut donner notre adresse XMPP à nos ami·e·s pour qu'elleux aussi puissent bavarder avec nous.
Il faut aussi bien penser à surveiller, comme pour tout en informatique, notre serveur XMPP via un logiciel de supervision.
Cet article ne porte que sur l'installation d'un serveur, mais j'en ferai peut-être un autre sur le choix de clients XMPP pour ordinateur ou mobile.
Merci à Imriel pour sa relecture.
Vous pouvez commenter en envoyant un mail via ce bouton (votre adresse ne sera pas publié).
Commenter par mailIls sont 2 sur terre à utiliser encore ce protocole mort née.
Hé ben je suis l'un des deux restants.... Juste pour info Facebook messenger utilise le protocole XMPP.
Merci pour cette article. Si tu as des astuces pour optimiser et sécuriser ce type de serveur je suis preneur.
Bonne continuation
je suis le deuxieme, la boucle est bouclée
merci pour ton article ca fait plaisir :)
ehbahavecmoiçafaittroisofcourse
merci pour cet article ... j'utilise xmpp depuis très longtemps (donc ça fait 4 utilisateurs!)
Je vais de ce pas installer le serveur sur mon serveur perso à la maison
;)
Eric
ça y est, c'est installé .... je suis en pleine config des modules, mais j'arrive à 75% de "compliance" .. ça progresse doucement.
serveur : im.yojik.net
Eric