Aller au contenu

Mise en place de Prosody

Parmi les différents serveurs XMPP disponibles, Prosody a l'avantage d'être assez performant pour un nombre restreint d'utilisateurs et d'être simple à configurer par rapport à Ejabberd. Il est également capable de supporter la majorité des spécifications XMPP en vigueur, ce qui en fait un bon serveur pour commencer.
Dans notre exemple, nous allons installer Prosody sur un serveur sous Debian 10.

Installation des paquets requis

Prosody étant présent dans les dépôts officiels, son installation se résume à la commande suivante : sudo apt install prosody prosody-modules mercurial

Installation de modules communautaires

Bien que Debian fournit une grande liste de plugins pour Prosody, certains plugins nécessaires pour avoir un serveur respectant le plus de spécifications XMPP sont manquants et il est alors nécessaire de passer par des modules communautaires qui s'installent depuis les serveurs des développeurs de Prosody, par l'intermédiaire de Mercurial.

Avant tout, nous allons préparer le terrain en créant deux dossiers, un pour stocker les plugins téléchargés et un réservé à ceux qui seront réellement actifs. Il nous suffira ainsi de créer un lien symbolique pour activer un module si besoin.
Cela se fait ainsi : sudo mkdir /etc/prosody/{modules-available,modules-enabled}

On télécharge ensuite le repertoire des modules communautaires, comme recommandé dans la documentation oficielle, en utilisant l'outil fourni par le paquet mercurial :
sudo hg clone https://hg.prosody.im/prosody-modules/ /etc/prosody/modules-available

On active enfin un module utile pour que notre serveur soit en accord avec les dernières normes de XMPP, à savoir mod_bookmarks, en faisant des liens symboliques comme ceci :
sudo ln -s /etc/prosody/modules-available/mod_bookmarks /etc/prosody/modules-enabled/

Il nous suffira alors d'ajouter le dossier modules-enabled dans les options de Prosody (pour trouver les modules) et ensuite de les rajouter un par un dans le fichier de configuration (en ne mentionnant que bookmarks, et non mod_bookmarks).

Configuration de Prosody

L'ensemble de la configuration de Prosody se fait dans le fichier /etc/prosody/prosody.conf.lua.
Avant toute chose, nous allons déplacer le fichier d'origine et créer un nouveau fichier vierge pour y mettre notre configuration. Pour cela, lancez la commande suivante dans votre terminal :
sudo mv /etc/prosody/prosody.cfg.lua /etc/prosody/prosody.cfg.old && sudo touch /etc/prosody/prosody.cfg.lua

On ouvre ensuite notre éditeur favori pour ajouter notre configuration petit à petit : sudo nano /etc/prosody/prosody.cfg.lua

Définir les admins et les dossiers liés aux plugins

Au début de notre configuration, on indique quel compte XMPP servira de compte d'administration (lui seul pour envoyer des commandes directement au serveur, pour ajouter des utilisateurs ou en supprimer par exemple) et où trouver les plugins pour Prosody. Ici, nous allons ajouter ceux fournis par Debian et les quelques plugins communautaires que nous avons indiqué plus haut.

-- Configuration de Prosody

admins = { "admin@votredomaine.xyz" }

plugin_paths = { "/usr/local/lib/prosody/modules", "/etc/prosody/modules-enabled/" }

Choisir nos plugins

En deuxième partie, on ajoute les plugins que l'on veut activer sur notre serveur.
J'ai directement copié les lignes présentes dans le fichier par défaut et décommenté ceux qui nous intéressent (les -- correspondent à des commentaires dans le langage Lua, langage de programmation utilisé par Prosody). Vous noterez la présence de la section Installed with Mercurial qui indique les plugins communautaires rajoutés.

modules_enabled = {

    -- Generally required
        "roster"; -- Allow users to have a roster. Recommended ;)
        "saslauth"; -- Authentication for clients and servers. Recommended if you want to log in.
        "tls"; -- Add support for secure TLS on c2s/s2s connections
        "dialback"; -- s2s dialback support
        "disco"; -- Service discovery

    -- Not essential, but recommended
        "carbons"; -- Keep multiple clients in sync
        "pep"; -- Enables users to publish their avatar, mood, activity, playing music and more
        "private"; -- Private XML storage (for room bookmarks, etc.)
        "blocklist"; -- Allow users to block communications with other users
        "vcard4"; -- User profiles (stored in PEP)
        "vcard_legacy"; -- Conversion between legacy vCard and PEP Avatar, vcard

    -- Nice to have
        "version"; -- Replies to server version requests
        "uptime"; -- Report how long server has been running
        "time"; -- Let others know the time here on this server
        "ping"; -- Replies to XMPP pings with pongs
        "register"; -- Allow users to register on this server using a client and change passwords
        "mam"; -- Store messages in an archive and allow users to access it
        "csi_simple"; -- Simple Mobile optimizations
        "cloud_notify"; -- Notifications
        "smacks";

    -- Admin interfaces
        "admin_adhoc"; -- Allows administration via an XMPP client that supports ad-hoc commands
        --"admin_telnet"; -- Opens telnet console interface on localhost port 5582

    -- HTTP modules
        --"bosh"; -- Enable BOSH clients, aka "Jabber over HTTP"
        --"websocket"; -- XMPP over WebSockets
        --"http_files"; -- Serve static files from a directory over HTTP

    -- Other specific functionality
        "posix"; -- POSIX functionality, sends server to background, enables syslog, etc.
        --"limits"; -- Enable bandwidth limiting for XMPP connections
        "groups"; -- Shared roster support
        "server_contact_info"; -- Publish contact information for this service
        --"announce"; -- Send announcement to all online users
        --"welcome"; -- Welcome users who register accounts
        "watchregistrations"; -- Alert admins of registrations
        "motd"; -- Send a message to users when they log in
        --"legacyauth"; -- Legacy authentication. Only used by some old clients and bots.
        --"proxy65"; -- Enables a file transfer proxy service which clients behind NAT can use

    -- Installed with Mercurial
        "bookmarks";
}

Options diverses (connexions chiffrées, journalisation)

On ajoute ensuite quelques options pour indiquer notamment les adresses à contacter en cas de problème (par défaut, le compte administrateur et une adresse mail), pour désactiver les inscriptions, pour forcer le chiffrement sur toutes les connexions au serveur (entre les autres serveurs, entre les clients) et pour personnaliser la localisation des fichiers de journaux (logs) et le fonctionnement général sous Debian.

contact_info = {
  abuse = { "mailto:admin@votredomaine.xyz", "xmpp:admin@votredomaine.xyz" };
  admin = { "mailto:admin@votredomaine.xyz", "xmpp:admin@votredomaine.xyz" };
  support = { "https://www.votredomaine.xyz/doc/xmpp/", "xmpp:admin@votredomaine.xyz" };
}

-- Disable account creation by default, for security
-- For more information see https://prosody.im/doc/creating_accounts
allow_registration = false

-- Debian:
--   Do not send the server to background, either systemd or start-stop-daemon take care of that.
--
daemonize = false;

-- Debian:
--   Please, don't change this option since /run/prosody/
--   is one of the few directories Prosody is allowed to write to
--
pidfile = "/run/prosody/prosody.pid";

-- Force clients to use encrypted connections? This option will
-- prevent clients from authenticating unless they are using encryption.

c2s_require_encryption = true

-- Force servers to use encrypted connections? This option will
-- prevent servers from authenticating unless they are using encryption.

s2s_require_encryption = true

-- Force certificate authentication for server-to-server connections?

s2s_secure_auth = true

-- Select the authentication backend to use. The 'internal' providers
-- use Prosody's configured data storage to store the authentication data.

authentication = "internal_hashed"

-- Archiving configuration
-- If mod_mam is enabled, Prosody will store a copy of every message. This
-- is used to synchronize conversations between multiple clients, even if
-- they are offline. This setting controls how long Prosody will keep
-- messages in the archive before removing them.

archive_expires_after = "1w" -- Remove archived messages after 1 week

-- You can also configure messages to be stored in-memory only. For more
-- archiving options, see https://prosody.im/doc/modules/mod_mam

-- Logging configuration
-- For advanced logging see https://prosody.im/doc/logging
--
-- Debian:
--  Logs info and higher to /var/log
--  Logs errors to syslog also
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";  };
}

Définir les ports utilisés par Prosody

Pour certains ports, notamment ceux pour le serveur HTTPS intégré, Prosody a du mal à attribuer le bon certificat SSL et ouvre par défaut les connexions au monde extérieur. Cela n'est pas forcément la configuration la plus sécurisée, donc nous allons changer quelques options pour définir le bon certificat et interdire les connexions extérieures sur les ports 5280 et 5281, utilisés notamment pour l'envoi de fichiers.
Pour rédiriger les requêtes sur ces deux ports, nous allons utiliser Nginx pour filtrer le tout et gérer les connexions en amont de Prosody.

legacy_ssl_ports = { 5223 }
legacy_ssl_ssl = {      certificate = "/etc/prosody/certs/fullchain.pem";
                        key = "/etc/prosody/certs/privkey.pem"; }

http_ports = { 5280 }
http_interfaces = { "127.0.0.1", "::1" }
https_ports = { 5281 }
https_interfaces = { "127.0.0.1", "::1" }
https_ssl = {   certificate = "/etc/prosody/certs/fullchain.pem";
                key = "/etc/prosody/certs/privkey.pem"; }

proxy65_interfaces = { "*", "::" }
proxy65_ports = { 5000 }

Définir les composants et le certificat SSL

La dernière partie nous sert, enfin, à indiquer les différents composants de notre serveur XMPP (c'est-à-dire les différents sous-domaines rattachés pour envoyer des fichiers sur le serveur, créer des discussions de groupe et tout autre fonctionnalité potentielle comme des passerelles vers un serveur de visioconférence) et l'endroit où trouver le certificat SSL nécessaire aux connexions chiffrées.

-- Location of directory to find certificates in (relative to main config file):
certificates = "certs"

-- Virtual hosts
VirtualHost "votredomaine.xyz"
    ssl = {
        key = "/etc/prosody/certs/privkey.pem";
        certificate = "/etc/prosody/certs/fullchain.pem";
    }
    disco_items = {
                { "upload.votredomaine.xyz" },
    }

Component "upload.votredomaine.xyz" "http_upload"
    http_host = "upload.automario.eu"
    http_external_url = "https://upload.automario.eu/"
    http_upload_file_size_limit = 1024 * 1024 * 10 -- 10MB upload limit

Component "groups.votredomaine.xyz" "muc"
    modules_enabled = { "muc_mam", "vcard_muc" }
    restrict_room_creation = "local"

Component "proxy.votredomaine.xyz" "proxy65"

Ajouter le certificat dans le dossier de Prosody

Pour des raisons de permissions au niveau des certificats produits par Certbot, Prosody n'est pas capable de lire un certificat installé dans le dossier par défaut sans modifier les permissions. Pour éviter ce problème, il existe plusieurs solutions, mais la plus simple consiste à copier le certificat généré dans le dossier de prosody et de changer le propriétaire du fichier :

$ sudo cp /etc/letsencrypt/live/votredomaine.xyz/fullchain.pem /etc/prosody/certs/fullchain.pem
$ sudo cp /etc/letsencrypt/live/votredomaine.xyz/privkey.pem /ets/prosody/certs/privkey.pem
$ sudo chown prosody:prosody /etc/prosody/certs/*.pem

Important : il est important de noter qu'il faudra copier le certificat à chaque renouvellement, mais cela peut être automatisé par un script.

Activer et lancer Prosody

Une fois la configuration terminée, on lance Prosody et on active son démarrage automatique : sudo systemctl enable prosody && sudo systemctl start prosody

Une fois que tout est bon et que le serveur est démarré, il convient alors de créer le compte administrateur que nous avons mentionné dans notre configuration. Pour cela, il suffit de faire sudo prosodyctl add admin@votredomaine.xyz SuperMotdePasse et il est alors possible de se connecter avec lui.

Pour créer d'autres comptes, il vous suffit de répéter l'opération, sauf si vous avez autorisé les inscriptions dans la configuration de Prosody.

Configurer l'envoi de fichiers

Pour envoyer des images ou autres types de fichiers via notre serveur Prosody, nous allons faire appel à Nginx pour s'occuper de gérer les connexions. Comme notre certificat contient le bon sous-domaine, on peut l'utiliser sans soucis avec Nginx.
On ajoute donc un fichier de configuration contenant le contenu suivant :

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

        server_name upload.votredomaine.xyz;

        ssl_certificate /etc/letsencrypt/live/groups.automario.eu/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/groups.automario.eu/privkey.pem;

        ssl_buffer_size 4k; # 16k, for throughput, video applications

        # intermediate config on ssl-config.mozilla.org
        ssl_ciphers TLS-CHACHA20-POLY1305-SHA256:TLS-AES-256-GCM-SHA384:TLS-AES-128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;

        ssl_ecdh_curve X25519:P-521:P-384:P-256;

        ssl_prefer_server_ciphers on;
        ssl_protocols TLSv1.3 TLSv1.2;

        ssl_session_cache shared:SSL:10m;
        ssl_session_tickets off;
        ssl_session_timeout 1h;

        ssl_stapling on;
        ssl_stapling_verify on;

        client_max_body_size 10m;

        location /upload/ {
                proxy_buffering off;
                proxy_set_header Host $host;
                if ($request_method = PUT) {
                        proxy_pass http://127.0.0.1:5280;
                }
                alias /var/lib/prosody/http_upload/;
        }

        # Logs
        access_log /var/log/nginx/upload-access.log;
        error_log /var/log/nginx/upload-error.log;
}
server {
        listen 80;
        listen [::]:80;

        # Nom de domaine
        server_name upload.votredomaine.xyz;

        # Redirection vers le HTTPS
        return 301 https://$server_name$request_uri;
}

On relance ensuite Nginx avec la commande sudo systemctl reload nginx et normalement, Prosody devrait accepter les envois de fichiers et renvoyer les bons liens vers les destinataires.