Installer son serveur XMPP 100% conforme aux XEP

déc. 14, 2020

Oui, vous avez bien lus, XMPP. Le nom raccourci de "Extensible Messaging and Presence Protocol" qui rassemble plein de protocoles pour la messagerie instantanée décentralisé. XMPP a été créé en 1999, plus jeune que IRC qui date de 1998 (Pour ce dernier, je vous invite à lire l'article de Von à ce sujet) il a quelques différences notable. Tout d'abord, XMPP nécessite un couple login / mot de passe pour se connecter. Il est également fédéré, c'est à dire que vous pouvez créer votre serveur à vous et me contacter sur le miens. Le plus gros avantage de XMPP est son extensibilité au travers de XEP ( "XMPP Extension Protocols" ). C'est d'ailleurs sont plus grand inconvénient, du fait de sa constante évolution, les clients et les serveurs ne suivent pas forcément et donc chacun a une expérience utilisateur différente.

Et pour vous qui me lisez, sachez que XMPP n'est pas mort et que c'est pas encore un protocole oĂč seul quelque barbus tente de le faire vivre, des XEP sont encore proposĂ© : https://xmpp.org/extensions/ les protocoles continues Ă  vivre.
Je vais pas vous mentir cependant, l'inconvénient majeur de XMPP est qu'il n'y a au final qu'extrémement peu de client user-friendly et tous n'intÚgre pas toutes les XEP.


Je vais faire une petite aparté sur le pourquoi de cet article. Tout d'abord, bon nombre d'entre vous ont pensés à me dire en commentaire "Hé dude ! Tu connais pas Matrix ?". TrÚs franchement, si, je connais cette norme (c'est pas un protocole car c'est simplement des json conçu et envoyé via HTTP/1.1) et actuellement seul le serveur Synapse existe et est complet (car développé par les concepteurs de Matrix).
J'administre un serveur Matrix, 50 utilisateurs en simultanĂ©s, 800 salons et une conservation des donnĂ©es sur 1 mois (sur un systĂšme de chat il n'y a pas d'intĂȘret de conserver ça plus longtemps)... Ca consomme 8Go de RAM, 50Go de stockage cĂŽtĂ© synapse et cĂŽtĂ© PostgreSQL 15Go de base de donnĂ©e et 4Go de RAM. Ajoutons Ă  cela que les websockets c'est pas ça avec Matrix et que les clients sont obligĂ©s de faire des requĂȘtes rĂ©guliĂšres au lieu de laisser un socket ouvert. De plus chaque requĂȘte fait appel Ă  la base de donnĂ©e et gĂ©nĂšre une requĂȘte qui retourne plusieurs miliers de ligne (1,2 millions par 10 secondes Ă  l'heure oĂč j'Ă©cris ces lignes). Et je ne parle mĂȘme pas de l'administration de cette application, entre les mises Ă  jour qui tente de modifier le fichier de configuration jamais modifiĂ© (j'utilise conf.d), le tweak du systĂšme pour que cela fonctionne correctement, le tweak de la base de donnĂ©e aussi...

Very heavy

Autant vous dire que pour envoyer et recevoir des messages texte cela fait beaucoup de ressources gaspillés. Je vous entend dire "Oui, mais t'as pas testé autant de personne sur XMPP". Imaginez en 1999 un logiciel qui consomme 8Go de RAM pour 50 personnes dessus. Déjà une machine qui avait 1Go de RAM ça coutait extrémement cher, donc un logiciel qui consomme autant n'aurait jamais fonctionné.

Le choix de XMPP pour un systÚme de chat libre est fédéré s'impose comme la seule solution potable selon moi


AprÚs avoir déjà testé Prosody à l'époque, j'ai voulu tester un autre serveur : Ejabberd (Erlang Jabber Daemon). Créé en 2002 Alexey Shchepin puis aidé par Mickaël Rémond, le logiciel sous licence Libre GNU GPL est rédigé en Erlang. La documentation explicite et les quelques tutoriels sur le site de l'entreprise des deux fondateurs m'ont conquis.

Let's go
Bien sur, installer l'application c'est simple, la configurer pas trop compliqué... Atteindre les 100% de conformité sur compliance.conversations.im est une autre tùche. Et cette tùche, nous allons la réussir ensemble !

Nous n'allons rien compiler par flemme et par volonté de ne pas vouloir complexifier la maintenance. Nous allons utiliser le paquet officiel avec comme base de donnée PostgreSQL. Vous pouvez utiliser sqlite ou MySQL sans soucis (mais moi et mon amour pour PostgreSQL...).
Vous allez donc avoir besoin de gpg, wget, PostgreSQL, Nginx (la conversion avec apache est pas compliqué) et Certbot de Let's Encrypt. Il vous faudra également un nom de domaine et donc avoir moyen de modifier votre zone DNS.

Configuration DNS premiĂšre du nom

Pour générer les certificats et accéder à votre serveur XMPP, vous allez devoir créer quelques sous domaines :

  • xmpp.domain.tld
  • upload.xmpp.domain.tld
  • conference.xmpp.domain.tld
  • proxy.xmpp.domain.tld
  • pubsub.xmpp.domain.tld

et les faires pointer vers votre serveur XMPP.
Vous pouvez faire comme moi et vous offrir un domaine en .im pour le faire pointer intégralement vers votre serveur XMPP.
Pour moi ça ressemble à ça :

  • dryusdan.im
  • upload.dryusdan.im
  • conference.dryusdan.im
  • proxy.dryusdan.im
  • pubsub.dryusdan.im

Installation

Pour ça rien de compliqué, il faut installer les paquets suivants :

apt update
apt install nginx-full postgresql postgresql-client certbot redis-server

Une fois ces paquets installés, nous récupérons Ejabberd avec les commandes ci dessous aprÚs avoir récupéré la version de ce dernier sur la page de téléchargement officiel.
Une fois les paquets suivants installé, nous allons créer un utilisateur et une base de donnée pour PostgreSQL, créer

Tout d'abord on récupÚre la clé GPG de process-one (l'entreprise de Ejabberd) :

wget -qO - https://www.process-one.net/downloads/KEYS | gpg --import

Ensuite nous téléchargeons le paquet, la signature et le checksum :

cd /tmp
wget  -O ejabberd_20.07-0_amd64.deb "https://www.process-one.net/downloads/downloads-action.php?file=/20.07/ejabberd_20.07-0_amd64.deb"
wget -O ejabberd_20.07-0_amd64.deb.sum "https://www.process-one.net/downloads/downloads-action.php?file=/20.07/ejabberd_20.07-0_amd64.deb.sum" 
wget -O ejabberd_20.07-0_amd64.deb.asc "https://www.process-one.net/downloads/downloads-action.php?file=/20.07/ejabberd_20.07-0_amd64.deb.asc"

Suite à cela, nous vérifions si le paquet est bon avant de l'installer :

$ sha256sum -c ejabberd_20.07-0_amd64.deb.sum
ejabberd_20.07-0_amd64.deb: RĂ©ussi

$ gpg --verify ejabberd_20.07-0_amd64.deb.asc 
gpg: les donnĂ©es signĂ©es sont supposĂ©es ĂȘtre dans « ejabberd_20.07-0_amd64.deb »
gpg: Signature faite le jeu. 30 juil. 2020 17:41:07 CEST
gpg:                avec la clef DSA 31468D18DF9841242B90D7328ECA469419C09311
gpg: Bonne signature de « Process-one  » [inconnu]
gpg: Attention : cette clef n'est pas certifiée avec une signature de confiance.
gpg:             Rien n'indique que la signature appartient à son propriétaire.
Empreinte de clef principale : 3146 8D18 DF98 4124 2B90  D732 8ECA 4694 19C0 9311

Puis on installe ejabberd :

dpkg -i ejabberd_20.07-0_amd64.deb 

Ejabberd sera installé dans /opt/ejabberd-20.07 et la configuration sera dans /opt/ejabberd. Le logiciel ne sera pas lancé à la fin de l'installation.
Nous allons devoir créer une base de donnée et un utilisateur sur PostgreSQL ainsi qu'un vhost Nginx et des certificats Let's Encrypt.

J'ai personnellement triché et utilisé deux playbooks Ansible :

Mais ici on va le faire sans tricher. Tout d'abord connectez vous avec le compte postgres sur PostgreSQL.

sudo -i -u postgres
psql
CREATE DATABASE xmpp;
CREATE USER xmpp WITH PASSWORD 'xmpp';
GRANT ALL PRIVILEGES ON DATABASE xmpp TO xmpp;

Ensuite nous allons créer un dossier dans /var/www/letsencrypt et un autre dans /var/www/xmpp. Puis configurer un vhost nginx pour générer les certificats avant de mettre en place un autre vhost avec une configuration pour la XEP-0156 de XMPP.

Tout d'abord créez le vhost dans /etc/nginx/sites-available/xmpp.conf


server {
    listen 80 ;
    server_name xmpp.domain.tld upload.xmpp.domain.tld conference.xmpp.domain.tld proxy.xmpp.domain.tld pubsub.xmpp.domain.tld ;


    client_max_body_size 2M;

    access_log /dev/null;
    error_log /dev/null;

    location /.well-known/acme-challenge {
        root /var/www/letsencrypt/;
        allow all;
    }

    location = /favicon.ico {
        log_not_found off;
        access_log /dev/null;
    }
    location = /robots.txt {
        allow all;
        log_not_found off;
        access_log /dev/null;
    }


    location / {
        return 301 https://$host$request_uri;
    }
}

Une fois cela fait, nous allons activer ce vhost, recharger nginx, puis lancez la commande certbot pour générer les certificats

ln -s /etc/nginx/sites-available/xmpp.conf /etc/nginx/sites-enabled/
nginx -t
systemctl reload nginx
certbot certonly --non-interactive  --webroot --email your@email.tld --agree-tos --webroot-path=/var/www/letsencrypt xmpp.domain.tld upload.xmpp.domain.tld conference.xmpp.domain.tld proxy.xmpp.domain.tld pubsub.xmpp.domain.tld --expand --rsa-key-size 4096;

DĂšs que c'est bon, nous mettons en place le vhost Nginx en HTTPS


server {
    listen 443 ssl http2 ;
    listen [::]:443 ssl http2 ;
    server_name mpp.domain.tld upload.xmpp.domain.tld conference.xmpp.domain.tld proxy.xmpp.domain.tld pubsub.xmpp.domain.tld ;


    client_max_body_size 2M;


    root /var/www/ejabberd;
    index index.html index.htm;

    access_log /var/log/nginx/dryusdan.im.access.log;
    error_log /var/log/nginx/dryusdan.im.error.log;


    ssl_certificate /etc/letsencrypt/live/xmpp.domain.tld/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/xmpp.domain.tld/privkey.pem;


    ssl_protocols TLSv1.1 TLSv1.2 TLSv1.3;
    ssl_ecdh_curve X25519:P-521:P-384:P-256;
    ssl_ciphers "EECDH+CHACHA20:EECDH+AESGCM";
    ssl_prefer_server_ciphers on;
    ssl_session_cache shared:SSL:20m;
    ssl_session_timeout 15m;
    ssl_session_tickets off;

    location /.well-known/acme-challenge {
        root /var/www/letsencrypt/;
        allow all;
    }
    location = /favicon.ico {
        log_not_found off;
        access_log /dev/null;
    }
    location = /robots.txt {
        allow all;
        log_not_found off;
        access_log /dev/null;
    }

    location /.well-known/host-meta {
        default_type 'application/xrd+xml';
        add_header Access-Control-Allow-Origin '*' always;
    }
    location /.well-known/host-meta.json {
        default_type 'application/jrd+json';
        add_header Access-Control-Allow-Origin '*' always;
    }


}

En effet, je n'ai pas fait générer de clé dhparam ni récupéré les clés de Let's Encrypt pour faire de l'OCSP. Ce n'est pas le but de cet article.
Les informations dans les fichiers non créé de host-meta et host-meta.json vous seront indiqué plus tard ;)

Bon, maintenant que les fondations ont été misent en place, rentrons dans le vif du sujet : Ejabberd !tenor-2

Ejabberd la vengance de la configuration

Bon, en réalité c'est trÚÚÚÚs simple, déjà parce que la doc est assez explicite mais en plus car les maintenairs d'Ejabberd ont d'excellent tutoriel sur leurs blogs.

Mais d'abord, il va nous falloir deux choses : une clĂ© dhparam est un certificat avec clĂ© privĂ©e et chaine dans un seul et mĂȘme fichier.

Commençons avec le dhparam, en effet c'est partie lĂ  peut ĂȘtre plus ou moins longue en fonction de votre serveur (globalement le miens ça a durĂ© 5 minutes mais sur d'autre machine gĂ©nĂ©rer cette clĂ© dure 30-45 minutes (j'ai mĂȘme atteint 2h). Pour ce faire, vous allez vous connectez avec l'utilisateur ejabberd, crĂ©er un dossier ssl, y mettre vos fichiers dedans...

su - ejabberd -s /bin/bash
mkdir ~/ssl
openssl dhparam -out ssl/dh4096.pem 4096

Je vous conseil de lancer ça via un screen ou un tmux comme ça en cas de coupure réseau, vous ne perdez pas la console et donc la génération de la clé.
Pendant ce temps, nous allons réaliser une tache cron qui va toute les semaines assembler les certificats en un gros fichier et relancer ejabberd.

Pour cela vous allez faire un fichier dans /etc/cron.weekly/ejabberd-cert et inserrer ces commandes :

#!/bin/bash
/bin/cat /etc/letsencrypt/live/xmpp.domain.tld/fullchain.pem /etc/letsencrypt/live/xmpp.domain.tld/privkey.pem > /opt/ejabberd/ssl/xmpp.domain.tld
/bin/chown ejabberd:ejabberd /opt/ejabberd/ssl/xmpp.domain.tld
/bin/systemctl reload ejabberd.service

(Oui, le script est trĂšs laid mais il fait ce qu'on lui demande).
Vous le rendez executable avec un petit chmod +x /etc/cron.weekly/ejabberd-cert. Puis vous le lancez : /etc/cron.weekly/ejabberd-cert .
Cela va vous retourner une erreur "ejabberd.service not found". Mais ça c'est pas important tout de suite. Maintenant : la configuration !


## Ici nous définissons un ou plusieurs hosts
## Ces différents hosts seront des "vhosts" 
## Cela permet, nottament, d'avoir plusieurs compte
## Et plusieurs jid sur un serveur
## (par exemple dryusdan.im et xmpp.drycat.fr)
hosts:
  - "xmpp.domain.tld"

## La configuration au serveur PostgreSQL pour xmpp.domain.tld
## Vous pouvez avoir une BDD par host et mĂȘme diffĂ©rent format
## (mysql, postgresql, sqlite...)
## ( cf https://docs.ejabberd.im/admin/configuration/database-ldap/ ) 
host_config:
  xmpp.domain.tld:
    sql_type: pgsql
    sql_server: 127.0.0.1
    sql_database: xmpp
    sql_username: xmpp
    sql_password: 'xmpp'
    auth_method: [sql]

## Utilisez le nouveau, mieux que l'ancien
new_sql_schema: true

## Ici nous définissons la DB Redis.
## Ce n'est pas obligatoire, cela permet
## de réduire les temps de latence lors d'une connexion
## (c'est pour stocker les sessions) 
## (cf https://docs.ejabberd.im/admin/configuration/database-ldap/#redis )
redis_server: 127.0.0.1
redis_db: 1

loglevel: 4
log_rotate_size: 10485760
log_rotate_date: ""
log_rotate_count: 1
log_rate_limit: 100

## Ici on va définir les ports écoutés ainsi que leurs configuration
## (STARTTLS, TLS ainsi que leurs cipher.
## Je me suis basé sur ceci https://www.process-one.net/blog/securing-ejabberd-with-tls-encryption/
## Le plain est intégralement désactivé sur cette configuration
## En premier lieu on a le Client To Server en STARTTLS
## Ensuite le Client To Server en full TLS
## Puis le Server To Server en STARTTLS
## AprÚs le serveur HTTPS pour gérer les méthodes de communication alternative
## Avec tout ça un listener pour le MQTT (que je ne détaillerai pas ici)
## Pour finir un listener TURN/STUN pour la XEP-0215 
## via l'article https://www.process-one.net/blog/how-to-set-up-ejabberd-video-voice-calling/
listen:
  -
    port: 5222
    ip: "::"
    module: ejabberd_c2s
    max_stanza_size: 262144
    shaper: c2s_shaper
    access: c2s
    ## Ici c'est soit plaintext (false) soit starttls (true)
    ## Le fonctionnement est comme pour les mails, ça chiffre en utilisant le port plain text
    starttls_required: true
    tls_compression: false
    ## On blinde ici les suites cryptographique en retirant tout ce qui est faible ou troué
    ## https://fr.wikipedia.org/wiki/Suite_cryptographique
    ciphers: "ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256"
    ## On désactive tout ce qui est inférieur à TLS 1.2
    protocol_options:
      - "no_sslv2"
      - "no_sslv3"
      - "no_tlsv1"
      - "no_tlsv1_1"
    ## Mettez ici le chemin vers votre certificat
    certfile: "/opt/ejabberd/ssl/xmpp.domain.tld"
    ## Et ici le DHparam
    dhfile: "/opt/ejabberd/ssl/dh4096.pem"
  -
    port: 5223
    ip: "::"
    module: ejabberd_c2s
    ## Ici on force le TLS
    ## Tout le reste ensuite reste identique
    tls: true
    shaper: c2s_shaper
    access: c2s
    tls_compression: false
    ciphers: "ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256"
    protocol_options:
      - "no_sslv2"
      - "no_sslv3"
      - "no_tlsv1"
      - "no_tlsv1_1"
    certfile: "/opt/ejabberd/ssl/dryusdan.im"
    dhfile: "/opt/ejabberd/ssl/dh4096.pem"
  ## Pour le s2s, la différence avec le c2s est que
  ## les certificats et le dhfile sont défini plus bas
  ## Sinon c'est la mĂȘme chose
  -
    port: 5269
    ip: "::"
    module: ejabberd_s2s_in
    max_stanza_size: 524288
    protocol_options:
      - "no_sslv2"
      - "no_sslv3"
      - "no_tlsv1"
      - "no_tlsv1_1"
    dhfile: "/opt/ejabberd/ssl/dh4096.pem"
  -
    port: 5270
    ip: "::"
    module: ejabberd_s2s_in
    tls: true
    max_stanza_size: 524288
    protocol_options:
      - "no_sslv2"
      - "no_sslv3"
      - "no_tlsv1"
      - "no_tlsv1_1"
    dhfile: "/opt/ejabberd/ssl/dh4096.pem"
  -
    port: 5443
    ip: "::"
    module: ejabberd_http
    ## Le module HTTP avec TLS, les bons cipher...
    tls: true
    tls_compression: false
    ciphers: "ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256"
    protocol_options:
      - "no_sslv2"
      - "no_sslv3"
      - "no_tlsv1"
      - "no_tlsv1_1"
    dhfile: "/opt/ejabberd/ssl/dh4096.pem"
    request_handlers:
      "/admin": ejabberd_web_admin
      "/api": mod_http_api
      "/bosh": mod_bosh
      "/captcha": ejabberd_captcha
      "/upload": mod_http_upload
      "/ws": ejabberd_http_ws
      "/oauth": ejabberd_oauth
  -
    port: 1883
    ip: "::"
    module: mod_mqtt
    backlog: 1000
  -
    port: 3478
    ## Definition des ports STUN et TUN
    ## cf https://www.process-one.net/blog/how-to-set-up-ejabberd-video-voice-calling/
    transport: udp
    module: ejabberd_stun
    use_turn: true
    turn_min_port: 49152
    turn_max_port: 65535
    ## définition IPv4 / IPv6
    turn_ipv4_address: 0.0.0.0
    turn_ipv6_address: "::"
  -
    port: 5349
    transport: tcp
    module: ejabberd_stun
    use_turn: true
    tls: true
    turn_min_port: 49152
    turn_max_port: 65535
    ip: "::"
    turn_ipv4_address: 0.0.0.0
    turn_ipv6_address: "::"


## Maintenant la configuration de la sécurité de s2s
## Pourquoi maintenant ? J'en sais rien
s2s_use_starttls: required
s2s_certfile: /opt/ejabberd/ssl/xmpp.tld
s2s_dhfile: "/opt/ejabberd/ssl/dh4096.pem"
s2s_ciphers: "ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256"

## Utilisons IPv4 et IPv6
outgoing_s2s_families:
    - ipv4
    - ipv6
outgoing_s2s_timeout: 10000
trusted_proxies: [127.0.0.1]

acl:
  local:
    user_regexp: ""
  ## Indiquons que les IPs de loopback sont celles ci
  loopback:
    ip:
      - 127.0.0.0/8
      - ::1/128
      - ::FFFF:127.0.0.1/128
  ## définir l'admin
  admin:
    user:
      - "admin@xmpp.domain.tld"
  ## C'est pour MQTT
  ## cf https://www.process-one.net/blog/starting-with-mqtt-protocol-and-ejabberd-mqtt-broker/
  publisher:
    user:
      - "broker@xmpp.domain.tld"
  subscriber:
    user:
      - "broker@xmpp.domain.tld"

## J'ai laissé les configurations par défaut car je suis seul sur l'instance
## La doc sur les ACL restes explicite
## https://docs.ejabberd.im/admin/configuration/basic/#access-rules
## À l'avenir peut-ĂȘtre j'en ferai un tutoriel

access_rules:
  local:
    allow: local
  c2s:
    deny: blocked
    allow: all
  announce:
    allow: admin
  configure:
    allow: admin
  muc_create:
    allow: local
  pubsub_createnode:
    allow: local
  ## DĂ©finir le rĂ©seau de confiance comme Ă©tant la machine elle mĂȘme
  trusted_network:
    allow: loopback

## J'ai laissé les configurations par défaut car je suis seul sur l'instance
## La doc sur les console restes explicite
## https://docs.ejabberd.im/developer/ejabberd-api/permissions/
## À l'avenir peut-ĂȘtre j'en ferai un tutoriel
api_permissions:
  "console commands":
    from:
      - ejabberd_ctl
    who: all
    what: "*"
  "admin access":
    who:
      access:
        allow:
          acl: loopback
          acl: admin
      oauth:
        scope: "ejabberd:admin"
        access:
          allow:
            acl: loopback
            acl: admin
    what:
      - "*"
      - "!stop"
      - "!start"
  "public commands":
    who:
      ip: 127.0.0.1/8
    what:
      - status
      - connected_users_number

shaper:
  normal: 1000
  fast: 50000

shaper_rules:
  max_user_sessions: 10
  max_user_offline_messages:
    5000: admin
    100: all
  c2s_shaper:
    none: admin
    normal: all
  s2s_shaper: fast

max_fsm_queue: 10000

## On désactive le acme, car cela est géré par certbot
acme:
   contact: "mailto:ssl@dryusdan.fr"
   ca_url: "https://acme-v02.api.letsencrypt.org"
   auto: false

modules:
  mod_adhoc: {}
  mod_admin_extra: {}
  mod_announce:
    ## Mettre la BDD dans postgresql
    access: announce
    db_type: sql
  mod_avatar: {}
  mod_blocking: {}
  mod_bosh:
    ## Utilisons la RAM pour de meilleur perf
    queue_type: ram
    ram_db_type: redis
  mod_caps: 
    ## Mettre la BDD dans postgresql
    db_type: sql
  mod_carboncopy: {}
  mod_client_state: {}
  mod_configure: {}
  mod_stun_disco:
    credentials_lifetime: 12h
    ## Configuration du STUN / TUN
    ## Pour faire de la visio via XMPP
    services:
      -
        host: stun.domain.tld
        port: 3478
        type: stun
        transport: udp
        restricted: false
      -
        host: turn.domain.tld
        port: 3478
        type: turn
        transport: udp
        restricted: true
      -
        host: domain.tld
        port: 5349
        type: stuns
        transport: tcp
        restricted: false
      -
        host: domain.tld
        port: 5349
        type: turns
        transport: tcp
        restricted: true
  mod_disco: 
    ## Mettre une adresse d'abus
    ## XEP-0157
    server_info:
    - 
      modules: all
      name: "abuse-addresses"
      urls: ["mailto:abuse@domain.tlkd"]
  mod_fail2ban: {}
  mod_http_api: {}
  mod_http_upload:
    # Permettre l'upload de ressource
    # pour la XEP-0363
    put_url: https://@HOST@:5443/upload
    docroot: /var/www/ejabberd/upload
    custom_headers:
      "Access-Control-Allow-Origin": "https://@HOST@"
      "Access-Control-Allow-Methods": "GET,HEAD,PUT,OPTIONS"
      "Access-Control-Allow-Headers": "Content-Type"
  mod_last:
    ## Mettre la BDD dans postgresql
    db_type: sql
  mod_mam:
    ## Mettre la BDD dans postgresql
    ## Conservons les conversations en BDD
    db_type: sql
    assume_mam_usage: true
    default: always
    clear_archive_on_room_destroy: true

  mod_mqtt:
    access_publish:
      "#":
        - allow: publisher
        - deny
    access_subscribe:
      "#":
        - allow: subscriber
        - deny
  mod_muc:
    ## Conservons les conversation
    ## Configurons par défaut les salons
    access:
      - allow
    access_admin:
      - allow: admin
    access_create: muc_create
    access_persistent: muc_create
    access_mam:
      - allow
    default_room_options:
      allow_subscription: true  # enable MucSub
      mam: true
      persistent: true
      allow_user_invites: true
  mod_muc_admin: {}
  mod_offline:
    access_max_user_messages: max_user_offline_messages
  mod_ping: {}
  mod_privacy: {}
  mod_private: {}
  mod_proxy65:
    access: local
    max_connections: 5
  mod_pubsub:
    access_createnode: pubsub_createnode
    plugins:
      - flat
      - pep
    force_node_config:
      ## Avoid buggy clients to make their bookmarks public
      storage:bookmarks:
        access_model: whitelist
  mod_push: {}
  mod_push_keepalive: {}
  mod_register:
    ## N'acceptez que les demandes d'enregistrement 
    ## provenant du réseau "de confiance" 
    ## (voir "access_rules" ci-dessus).
    ip_access: trusted_network
  mod_roster:
    versioning: true
    db_type: sql
    store_current_id: true
  mod_s2s_dialback: {}
  mod_shared_roster: {}
  mod_stream_mgmt:
    resend_on_timeout: if_offline
  mod_vcard: {}
  mod_vcard_xupdate: {}
  mod_version:
    ## Cacher la version du logiciel
    show_os: false

Tout les mods ne sont pas configurés pour avoir le serveur XMPP parfait. Il nous reste 3 choses à faire pour que tout cela fonctionne : Copier le fichier présent dans /opt/ejabberd-20.07/bin/ejabberd.service pour le caler dans /etc/systemd/system/ejabberd.service. Tapez ensuite systemctl daemon-reload. Ouvrez un autre terminal et tapez tail -f /opt/ejabberd/logs/* puis revenez sur l'ancien et lancer la commande systemctl start ejabberd.

Cela devrait normalement fonctionner. (Sauf lĂ©gĂšre erreur de copie, syntaxe etc... Enfin les logs sont EXTRÉMEMENT CLAIR pour le coup).
Il manque maintenant deux choses : la XEP-0368 (enregistrement DNS) et la XEP-0156 (les fichiers accessibles via Nginx).

Pour la XEP-0368, elle permet de signaler que le serveur XMPP est accessible sur tel port non sécurisé ou tel port sécurisé (bon, ici c'est soit TLS soit STARTTLS... Donc sécurisé coute que coute).
La XEP-0368 se base notamment sur la RFC 2782.
Vous allez devoir ajouter ces enregistrements ci dans votre zone DNS.

_xmpp-client._tcp IN xmpp.domain.tld 5 0 5222 xmpp.domain.tld 3600
_xmpp-server._tcp IN xmpp.domain.tld 5 0 5269 xmpp.domain.tld 3600
_xmpps-client._tcp IN xmpp.domain.tld 5 0 5223 xmpp.domain.tld 3600
_xmpps-server._tcp IN xmpp.domain.tld 5 0 5270 xmpp.domain.tld 3600

Et pour finir, nous allons gérer la XEP-0156. Cette XEP permet de spécifier quel méthodes alternatives existent pour communiquer avec ce serveur XMPP.
Il en existe deux :

  • Via BOSH (XEP-0124)
  • Via websocket (implĂ©mentĂ© avec BOSH)

Pour ce faire il vous faut deux fichiers.
Le fichier /var/www/ejabberd/.well-known/host-meta contenant :

<?xml version='1.0' encoding='utf-8'?>
<XRD xmlns='http://docs.oasis-open.org/ns/xri/xrd-1.0'>
  <Link rel="urn:xmpp:alt-connections:xbosh"
        href="https://xmpp.domain.tld:5443/bosh" />
  <Link rel="urn:xmpp:alt-connections:websocket"
        href="wss://xmpp.domain.tld:5443/ws" />
</XRD>

(ouais, j'ai pas pu le mettre sous une belle présentation car le XML est considéré comme de l'html par mon blog :( )

Et le fichier /var/www/ejabberd/.well-known/host-meta.json contenant

{
  "links": [
    {
      "rel": "urn:xmpp:alt-connections:xbosh",
      "href": "https://xmpp.domain.tld:5443/bosh"
    },
    {
      "rel": "urn:xmpp:alt-connections:websocket",
      "href": "wss://xmpp.domain.tld:5443/ws"
    }
  ]
}

Et voilĂ , c'est tout good.

Vous allez devoir créer deux utilisateurs avec la commande ci dessous.
Assurez vous que l'utilisateur que vous souhaitez voir administrateur soit défini dans la configuration de Ejabberd (acl > admin > user).
Le second sera utilisé par XMPP Compliance Tester pour tester votre conformité.

/opt/ejabberd-20.07/bin/ejabberdctl register admin xmpp.domain.tlkd MyStr0g3rP4$$W0rD
/opt/ejabberd-20.07/bin/ejabberdctl register compliance xmpp.domain.tlkd MyStr0g3rP4$$W0rD

Suite Ă  cela, rendez vous sur compliance.conversations.im et tapez votre nom de domaine. Vous devriez tomber sur une jolie page avec un beau 100% tout en haut.

100% conforme pour dryusdan.im

Pour Android je vous conseil le client Conversations sur Android. Payant sur Google Play, Gratuit sur F-Droid (je vous invite Ă  faire un don ;)).
Sur les autres plateformes je ne sais que conseiller. Cette page wikipedia en liste plein.

Suite a cela vous ĂȘtres prĂȘt pour revenir sur XMPP :D.

D'ailleurs pour me contacter c'est dryusdan@dryusdan.im :D

Sur ce, portez-vous bien.

Photo by Volodymyr Hryshchenko

Source

How to set up ejabberd video & voice calling | ProcessOne
Turn Your Ideas from Concept to Production in Record Time
How to configure ejabberd to get 100% in XMPP compliance test
Turn Your Ideas from Concept to Production in Record Time
Check ejabberd XMPP server useful configuration steps | ProcessOne
Turn Your Ideas from Concept to Production in Record Time
Configuring ejabberd | ejabberd Docs
ejabberd — WikipĂ©dia
Suite cryptographique — WikipĂ©dia
GĂ©rer ses utilisateurs... | DryWIki

Dryusdan

Chasseur de bug et régleur de problÚme (alias DevOps).

Super ! Vous vous ĂȘtes inscrit avec succĂšs.
Super ! Effectuez le paiement pour obtenir l'accĂšs complet.
Bon retour parmi nous ! Vous vous ĂȘtes connectĂ© avec succĂšs.
Parfait ! Votre compte est entiÚrement activé, vous avez désormais accÚs à tout le contenu.