Mettre en place un serveur Jabber avec du TLS et du Forward Secrecy

Posté par (page perso) . Édité par ZeroHeure, palm123, Nÿco et NeoX. Modéré par ZeroHeure. Licence CC by-sa
55
27
jan.
2015
XMPP

J'ai publié il y a quelques mois un tuto pour mettre en place "facilement" un serveur XMPP/Jabber avec Prosody et du SSL/TLS plutôt bien configuré sous Debian, j'ai eu pas mal de retours positifs depuis et je pense qu'il pourrait intéresser d'autres personnes.

Sommaire

Installation

Pour installer Prosody sous Debian, il suffit de rajouter le dépôt dans son sources.list, on peut utiliser la ligne suivante pour le faire. Elle permet de simplifier énormement la manipulation (pour les détails, c'est ici) :

echo "deb http://packages.prosody.im/debian $(lsb_release -sc) main" | sudo tee -a /etc/apt/sources.list

Puis on ajoute la clé GPG du dépôt :

wget https://prosody.im/files/prosody-debian-packages.key -O- | sudo apt-key add -

On met à jour les dépôts, puis on installe Prosody :

aptitude update && aptitude install prosody

Le paquet lua-sec dans Debian est légèrement… ancien, si vous voulez les derniers algorithmes de chiffrement et que le Perfect Forward Secrecy soit pris en compte, il faut le mettre à jour.

Sur Debian Wheezy :

echo "deb http://ftp.debian.org/debian wheezy-backports main" >> /etc/apt/sources.list
aptitude update && aptitude -t wheezy-backports install lua-sec-prosody

Configuration

L'ensemble de la configuration se fait dans un seul fichier :

/etc/prosody/prosody.cfg.lua

La première partie est commune à l'ensemble des VirtualHosts que vous allez mettre en place. Ce qui sera écrit sous chaque VirtualHost "exemple.com" (en bas) sera propre à chaque VirtualHost.

Ce qui veut dire que si vous mettez votre configuration SSL dans la première partie, elle sera commune à tous les VirtualHosts. Faites attention aux répercussions que ça peut avoir ;-)

La première brique

Ouvrez le fichier avec votre éditeur préféré (pour moi ça sera vim)

vim /etc/prosody/prosody.cfg.lua

Il faut modifier/compléter les champs suivants (avec évidemment vos informations à la place de example.tld) :

Qui est administrateur du serveur (tout en haut du fichier) ?

admins = {"admin@exemple.tld"}

Voulez-vous autoriser les inscriptions sur votre serveur ? À moins de savoir ce que vous faites, je vous conseille grandement de le mettre sur false afin d'éviter de servir aux spammeurs et aux bots.

allow_registration = false;

Quel domaine voulez-vous utiliser (tout en bas du fichier) ? N'oubliez pas de changer example.tld pour votre domaine.

VirtualHost "example.tld"
enabled = true

Les logs

C'est très important (et déjà partiellement configuré). Ils permettent de trouver où est le problème quand ça ne marche pas (pour plus de détails sur la configuration : logging), la modification par rapport au fichier original consiste à mettre le prosody.log en warn et non plus en info et à faire la même manipulation pour le syslog :

log = {
        warn= "/var/log/prosody/prosody.log";
        error = "/var/log/prosody/prosody.err";
        { levels = { "error" }; to = "syslog";  };

Si vous avez un problème à régler, je vous conseille de rechanger le premier warn pour debug, puis de redémarrer prosody (via la commande prosodyctl restart), vous aurez alors toutes les informations qu'il vous faut dans /var/log/prosody/prosody.log et bien plus encore pour trouver d'où ça vient.

Un minimum de sécurité

De base, Prosody enregistre les mots de passe des comptes en clair sur le serveur, pour qu'ils soient hashés, il faut modifier la ligne authentication = "internal_plain" par la ligne suivante :

authentication = "internal_hashed"

prosodyctl

Prosody vient avec une commande qui aide à communiquer avec lui facilement : prosodyctl, et qui s'utilise sous la forme suivante :

prosodyctl COMMAND [OPTIONS]

COMMAND peut être :

  • adduser - exemple@exemple.tld - crée le compte utilisateur
  • passwd - exemple@exemple.tld - configure le password de l'utilisateur
  • deluser - exemple@exemple.tld - supprime l'utilisateur
  • start - démarre Prosody
  • stop - arrête Prosody
  • restart - redémarre Prosody
  • reload - recharge la configuration de Prosody
  • status - indique le status actuel de Prosody

Plutôt utile non ? :]

Nous allons ajouter un utilisateur (il vous demandera un mot de passe), puis nous rechargerons la configuration pour prendre en compte les changements (exemple.tld doit être le même que vous avez mis pour votre VirtualHost) :

prosodyctl adduser exemple@exemple.tld
    prosodyctl reload

Et là, c'est l'instant de plaisir, si vous essayez de vous connecter avec un client jabber (comme pidgin), ça devrait se connecter. Si ce n'est pas le cas (faire dans l'ordre) :

  • voir les logs de prosody,
  • voir les logs de votre client jabber,
  • changer les logs de prosody de info à debug,
  • boire un thé (ou une bière)
  • vérifier votre firewall,
  • rebrancher la box,
  • reprendre un thé,
  • changer de FAI.

Les modules

Comme vous pouvez le voir dans le fichier de configuration, il y a déjà un certain nombre de modules qui sont activés par défaut (roster, saslauth, tls, posix…). ils sont dans la partie modules_enabled = { }.

Si je vous parle de ça, vous vous doutez que ce n'est pas pour rien, il existe beaucoup de modules, dont un pour Tor :

Chiffrons tout pour tout le monde

   Manifesto - *[A public statement about ubiquitous encryption on the XMPP network.](https://github.com/stpeter/manifesto)*

Si vous ne connaissez pas (ou mal) le SSL/TLS, je ne peux que vous conseiller d'attaquer le sujet par la conférence de Benjamin Sonntag dans le cadre du cycle de conférence « Il était une fois Internet ».

Création du certificat

  Si votre certificat n'est pas reconnu « valide » par votre client jabber, par exemple en cas de certificat auto-signé, il demandera autorisation pour l'utiliser.
La méthode simple (et vraiment rapide)

La méthode « simple » consiste à la création d'un certificat auto-signé avec l'aide de prosodyctl :

# exemple.tld étant le domaine que vous avez mis dans prosody.cfg.lua
prosodyctl cert generate exemple.tld
  • vérifier l'emplacement des certificats une fois qu'ils sont générés
  • vous pouvez les bouger dans /etc/prosody/certs/ si vous avez envie (on part du principe que c'est le cas pour la suite)
  • N'oubliez pas les deux lignes suivantes :
chmod 600 /etc/prosody/certs/exemple.tld.key
chown prosody:prosody /etc/prosody/certs/exemple.tld.key
chown prosody:prosody /etc/prosody/certs/exemple.tld.crt

Pour aller plus loin :

La méthode un peu moins simple mais qui est vachement mieux

Nous allons créer ce dont nous avons besoin en faisant une requête à startssl.com :

openssl req -sha256 -out /etc/prosody/certs/exemple.csr -new -newkey rsa:2048 -nodes -keyout /etc/prosody/certs/exemple.key

Cette commande génère (openssl req -out) une CSR (-new) ainsi qu'une nouvelle clé RSA de 2048 bits (-newkey rsa:2048) qui ne sera pas chiffrée (-nodes). Si vous voulez encore plus de détails, c'est sur openssl.org.

Je vous laisse sur startssl.com réaliser les différentes étapes pour s'inscrire (bonne chance !), il faut choisir la première formule (celle qui est gratuite). Après la création de votre compte, la validation de votre nom de domaine, etc. etc. nous pouvons passer à la suite.

  • Après votre authentification sur le site, cherchez l'onglet « Certificates Wizard » qui se trouve normalement vers la gauche de votre écran,
  • il vous demande alors pourquoi vous voulez un certificat ("Select Certificate Purpose"), vous choisissez donc XMPP (jabber) SSL/TLS certificate,
  • le site vous demande de créer une clé privée ("Generate Private Key") : VOUS NE LE FAITES PAS !, vous appuyez au contraire sur skip (nous avons créé la clé privée quelques lignes au dessus),
  • vous arrivez maintenant sur la page de demande de certificat ("Submit Certificate Request (CSR)"), toujours dans un terminal, vous devez taper la commande suivante :
cat /etc/prosody/certs/exemple.csr

Cette commande vous donnera un résultat qui devrait ressembler à

-----BEGIN CERTIFICATE REQUEST-----
MIIChjCCAW4CAQAwQTELMAkGA1UEBhMCRlIxCzAJBgNVBAgMAkZSMQswCQYDVQQH
DAJGUjELMAkGA1UECgwCRlIxCzAJBgNVBAsMAkZSMIIBIjANBgkqhkiG9w0BAQEF
AAOCAQ8AMIIBCgKCAQEAsoJcj6/bwl9naKG9C9seKt4HjBicV5o96zqoO0YxtJAe
X9k2t4KTp0CrzQ85c9DfggY8oAMq/DX/xRFL0cPxamxSwwW5ttVoBQ04wBWDhjEo
a2ixpe5UMmfakuY3Q56HsIbhh7Vo4RZS1OtPOv7E2J0CfDVUhrNCpDjZbtM8akTE
9P86BkXdroJgU8tfwONMFDBF2K8ElhN6mqftb89KGIUpgm1fcDq8woRpnFER7A3H
OwfCfnlkLrtMWVca1smEWnlutBKw6cgk6uSMK9V9/Y44wMKZHoOrOQE0R26+MGrA
MLhprqPaANIvhamq+tSsSASYZDeajDS3R1JWX188awIDAQABoAAwDQYJKoZIhvcN
AQEFBQADggEBAHYSpBxHhRP87qmWNqp9Sf8dYz3oQfJLA2cLpQV2MOIfFW0mmOyz
JG6TVISKVmiEHZtHqgW4TL3BSKBAWENBM8mjAjmxXCmy2MBSWBVhDVaGz4w+x3hO
UMtNMubYxkkc/xgX5vwbuReH6y1sbkMUQm1UETb6Fnmm8dyDzwPI0zV+NdzUqqhI
ARjMM2RrwPH7QZ2lSAOiB/X+fXKhwMSg0qUExYiln20JKBi6f58GdyOu6Hp/Fi+m
r8xnIcnZ2ZIIyjh4B2bfAfybTOWHHRtOaI9yH8pTP3HnKqgbtxZJYqioTAAAQxjQ
hFmXThFFrfhTDnqJ0Fc+bjcoiLoy46FtLz8=
-----END CERTIFICATE REQUEST-----

Copiez-le dans la fenêtre en bas (de -----BEGIN CERTIFICATE REQUEST----- à -----END CERTIFICATE REQUEST----- !).
Vous aurez alors votre certificat peu de temps après, transférez-le sur votre serveur, dans /etc/prosody/certs/ avec comme nom « exemple.tld.crt ».

Création d'un certificat chaîné

Pour créer un certificat chaîné, faites la manipulation suivante (startssl.com vous donne les liens vers ces deux certificats juste au dessus du bouton finish »» de la page Save Certificate) :

  • télécharger le certificat intermédiaire de startssl :
wget https://www.startssl.com/certs/sub.class1.server.ca.pem
  • puis le certificat root :
wget https://www.startssl.com/certs/ca.pem
  • puis on forge le certificat chaîné (ne pas oublier les 2 >>) :
cat sub.class1.server.ca.pem >> /etc/prosody/certs/exemple.tld.crt
cat ca.pem >> /etc/prosody/certs/exemple.tld.crt

Génération du dhparam

Création du dhparam (prosody.im/dhparam) :

openssl dhparam -out /etc/prosody/certs/dh-2048.pem 2048

Java ne peut pas utiliser un dhparam supérieur à 1024 bits, ce qui empêche d'utiliser par exemple le logiciel Jitsi. Pour éviter cela (c'est tout de même un client grandement utilisé), on peut générer un dhparam de 1024 bits avec la commande suivante (ne pas oublier de modifier la configuration pour remplacer dh-2048.pem par dh-1024.pem) :

openssl dhparam -out /etc/prosody/certs/dh-1024.pem 1024

Configuration du SSL/TLS

On retourne dans /etc/prosody/prosody.cfg.lua :

    ssl = {
        key = "/var/lib/prosody/exemple.tld.key";
        certificate = "/var/lib/prosody/exemple.tld.cert";
        dhparam = "/etc/prosody/certs/dh-2048.pem";
        options = { "no_sslv2", "no_sslv3", "no_ticket", "no_compression",
        "cipher_server_preference", "single_dh_use",
        "single_ecdh_use" };
        ciphers = "EECDH+ECDSA+AESGCM EECDH+aRSA+AESGCM EECDH+ECDSA+SHA384 EECDH+ECDSA+SHA256 EECDH+aRSA+SHA384 EECDH+aRSA+SHA256 EECDH EDH+aRSA !RC4 !aNULL !eNULL !LOW !3DES !MD5 !EXP !PSK !SRP !DSS";
    }
  • c2s signifie « Client TO Server »,
  • s2s signifie « Server TO Server ».
c2s_ports = { 5222 }
s2s_ports = { 5269 }
c2s_require_encryption = true
s2s_require_encryption = true
s2s_secure_auth = false
allow_unencrypted_plain_auth = false;

s2s_secure_auth est sur false pour les raisons suivantes (TL;DR: possibilité de certificat auto-signé en face). Peut marcher avec s2s_auth_fingerprint mais c'est douloureux.

Les options s2s_secure_domains et s2s_insecure_domains peuvent aussi vous intéresser, surtout si vous voulez parler avec des personnes qui sont sur gmail (ce qui veut dire que ça ne sera pas chiffré).

Concernant la ciphersuite, le choix par défaut de Prosody est déjà pas mal :

ciphers = "HIGH+kEDH:HIGH+kEECDH:HIGH:!PSK:!SRP:!3DES:!aNULL";

Il faut tout de même enlever RC4 et eNULL, et tant qu'à faire, autant faire une liste de ciphers avec seulement du PFS (Perfect Forward Secrecy) (c'est à mettre dans le bloc ssl { }) :

ciphers = "EECDH+ECDSA+AESGCM EECDH+aRSA+AESGCM EECDH+ECDSA+SHA384 EECDH+ECDSA+SHA256 EECDH+aRSA+SHA384 EECDH+aRSA+SHA256 EECDH EDH+aRSA !RC4 !aNULL !eNULL !LOW !3DES !MD5 !EXP !PSK !SRP !DSS";

DNS

N'oubliez pas d'ajouter les enregistrements SRV dans vos DNS :

_xmpp-client._tcp.jabber        IN      SRV     0 5 5222 host.exemple.com.
_xmpp-server._tcp.jabber        IN      SRV     0 5 5269 host.exemple.com.

Firewall

En cas de firewall, il faut ouvrir les ports 5269 et 5222 (IN et OUT) en TCP. La configuration pour iptables donne ceci :

iptables -I INPUT -p tcp --dport 5269 -j ACCEPT
iptables -I OUTPUT -p tcp --sport 5269 -j ACCEPT
iptables -I INPUT -p tcp --dport 5222 -j ACCEPT
iptables -I OUTPUT -p tcp --sport 5222 -j ACCEPT

Test

Comme SSLLabs pour tester le SSL/TLS sur les serveurs webs, il existe xmpp.net pour les serveurs XMPP. Je vous conseille vivement de tester votre site !

Il faut toujours vérifier, même quand on pense pouvoir avoir confiance.

Si vous vous demandez comment améliorer votre note, c'est là : xmpp.net/about.

  • # Merci

    Posté par . Évalué à 2.

    Super intéressant, merci! Je ne connaissais pas le concept de confidentialité persistante, c'est toujours bon de se remettre à jour…

    • [^] # Re: Merci

      Posté par (page perso) . Évalué à 3. Dernière modification le 27/01/15 à 12:00.

      Très bon tuto, merci. Il y a un </pre> qui traine dans l'exemple iptable (c'est pour trouver le bonheur ?).

      edit: et aussi on ne devrait plus utiliser le terme Jabber, il faudrait remplacer par XMPP

      • [^] # Re: Merci

        Posté par (page perso) . Évalué à 2.

        Il y a un qui traine…

        corrigé, merci

        "La liberté est à l'homme ce que les ailes sont à l'oiseau" Jean-Pierre Rosnay

    • [^] # PFS

      Posté par (page perso) . Évalué à 1.

      Le forward secrecy est en fait une partie extrêmement importante pour le SSL/TLS, il faut le mettre par défaut, et idéalement ne mettre que ça :]

      Le problème vient alors des autres serveurs qui ne sont pas toujours à jour, il faut souvent leur donner un coup de main ou faire pointer l'adminsys vers un article pour l'aider (c'est une des raisons pour laquelle ce tuto existe)

  • # Questions

    Posté par . Évalué à 2.

    Pourquoi ajouter un dépôt Prosody ainsi que les debian backports ???
    Tout est déjà packagé en stable et ça marche plutôt bien.

    • [^] # Re: Questions

      Posté par (page perso) . Évalué à 1.

      Il me semble que la version dans stable est un peu ancienne et qu'elle ne permet pas, entre autres, de s'interfacer avec fail2ban.

    • [^] # Re: Questions

      Posté par . Évalué à 3.

      Euh non la version stable est toute pourrie il n'y a même pas de support d'IPv6 et elle gère pas le pfs.

      splash!

  • # mod_s2s: Forbidding insecure connection to/from jabber.org

    Posté par (page perso) . Évalué à 4.

    Si quelqu'un s'heurte au message «mod_s2s: Forbidding insecure connection to/from jabber.org» tout comme moi depuis des semaines, et bien en mettant à jour le paquet «lua-sec» comme indiqué ci-dessus, le problème est corrigé.

    Bref, merci beaucoup !

    alf.life

    • [^] # Commentaire supprimé

      Posté par . Évalué à -4. Dernière modification le 27/01/15 à 16:36.

      Ce commentaire a été supprimé par l'équipe de modération.

  • # Un peu trop tard

    Posté par . Évalué à 1.

    Dommage, j'en ai monté un ce weekend.

    Merci quand même, je vais pouvoir affiner quelques éléments de configurations ! :)

    • [^] # Commentaire supprimé

      Posté par . Évalué à -4. Dernière modification le 27/01/15 à 16:34.

      Ce commentaire a été supprimé par l'équipe de modération.

  • # Commentaire supprimé

    Posté par . Évalué à -4. Dernière modification le 27/01/15 à 16:35.

    Ce commentaire a été supprimé par l'équipe de modération.

  • # euh et sinon...

    Posté par (page perso) . Évalué à 5.

    bon… imaginons qu'on moule sur linuxfr et qu'on sache de très loin ce qu'est Jabber. Serait-il possible de savoir à quoi sert la mise en place d'un tel serveur ? j'ai vraiment du mal à voir à quoi ça va me servir chez moi…

    • [^] # Re: euh et sinon...

      Posté par . Évalué à 4.

      Ben à titre perso ça sert à auto-héberger son compte Jabber. Plutôt que de le créer sur un hébergeur tiers. A titre moins perso, ça peut servir à proposer un compte Jabber à d'autres gens (autant le faire tourner pour plusieurs personnes).

      Un boîte peut faire tourner son propre serveur XMPP. Pour communiquer en interne ou même vers l'extérieur avec des identifiants Jabber en @ma-multinationale.com.

    • [^] # Re: euh et sinon...

      Posté par (page perso) . Évalué à 3. Dernière modification le 28/01/15 à 21:39.

      Si tu es une moule, tu n'as pas envie d'un système de chat sans norloge.

      http://devnewton.bci.im

  • # Redirection de ports ?

    Posté par (page perso) . Évalué à 2.

    Hello,

    J'ai également installé un serveur XMPP dans mon réseau et il ne reste qu'un détail qui me turlupine, c'est à propos de la redirection de ports.

    Pour l'instant, ce que je fais, c'est que toutes les tentatives de connexions sur mon adresse IP publique pour les ports 5222 et 5269 sont redirigées vers mon serveur.

    J'ai un doute que ce soit la bonne manière, car je ne sais pas comment est établie la connexion client to client :

    • si j'établis moi la connexion depuis mon client vers l'extérieur, j'imagine que mon routeur sait faire les bonnes redirections (il est là pour ça :))
    • mais si quelqu'un essaie directement de se connecter à mon client sur le port 5222, il va se retrouver sur le serveur (j'imagine qu'il peut le faire en interrogeant d'abord le serveur sur les informations de mes clients puis en les utilisant lui-même)

    Est-ce que vous avez des conseils pour la redirection de ports ? Ou alors, est-ce que vous avez une documentation vulgarisée d'XMPP pour m'éviter de lire les RFCs ?

    Merci pour le journal, il est bien complet !

    • [^] # Re: Redirection de ports ?

      Posté par (page perso) . Évalué à 5.

      je ne sais pas comment est établie la connexion client to client

      Bah elle n'existe pas donc t'es assez tranquille.

      Bon je ne parle pas des aspects P2P du protocole (transferts de fichiers, VoIP…) mais du chat pur. Mais eux passent, il me semble, par un port aléatoire négocié de manière ad-hoc si les clients peuvent se voir, ou passent par le media proxy sur ton port 7777 (si t'as activé cette option sur ton serveur), ou passent par un proxy public, ou… ah bah non ça s'arrête là et c'est à ce point-ci que Skype devient l'unique solution de VoIP viable :)

  • # StartSSL est une fausse bonne idée

    Posté par (page perso) . Évalué à 4.

    Vécu il y a peu pour cause de cœur qui saigne : « Revocation Handling Fee - US$ 24.90 »

    Debian Consultant @ DEBAMAX

    • [^] # Re: StartSSL est une fausse bonne idée

      Posté par (page perso) . Évalué à 3.

      Propose mieux que $25 un fois tous les 10 ans, je suis preneur.
      Un en qui on peut avoir confiance, hein, pas un qui as la confiance que de quelques personnes dans leur coin (non, je ne pense pas du tout à l'alerte de sécurité SSL de LinuxFr sur tous les navigateurs et distros Linux majeures…) et qui du coup ne sert à rien en pratique à part croire qu'on fait une chaine de confiance sans la faire ou alors juste entre soit (autant mettre un auto-signé à ce niveau)

  • # Deux petites question

    Posté par . Évalué à 1.

    -> Est-ce qu'il y a un dépôt particulier pour Raspbian ?
    -> Peut-on migrer facilement les comptes depuis ejabberd ?
    L'inverse ne m'était pas possible j'ai du recréer les comptes à la main et le roasters étaient perdus. Et j'avais fait la migration parce qu'il manquait à prosody des fonctionnalités qui m'intéressaient.

  • # Et la voix ?

    Posté par . Évalué à 2.

    Bonjour,
    est-ce qu'avec un serveur xmpp ainsi monté on peut aisément chatter en vocal ?
    Avec des softs qui fonctionnent aussi sur Mac OS (oui je sais…)

    Je tombe sur cet article alors que je regardais du côté d'OpenFire :
    http://www.igniterealtime.org/downloads/index.jsp
    (licence Apache 2.0)

    Michel

  • # Echec

    Posté par . Évalué à 0.

    Salut à tous,

    J'ai un problème pour mettre à jour le paquet lua-sec, j'ai bien complété le sourcelist, fait l'update, et lorsque je lance la commande aptitude -t wheezy-backports install lua-sec-prosody :
    ```
    Les nouveaux paquets suivants vont être installés :
    lua-sec-prosody
    .., 1 nouvellement installés, …

    Il est nécessaire de télécharger 0 o/30, 2 ko d'archives….
    Dépquetage de lua-sec-prosody (à partir de …/lua-sec-prosody_0.5.1.2~wheeze_amd64.deb) …
    dpkg: erreur de traitement de /var/cache/apt/archives/lua-sec-prosody_0.5.1.2~wheezy_amd64.deb (--unpack) :
    tentative de remplacement de "/usr/share/lua/5.1/ssl.lua", qui appartient aussi au paquet lua-sec:amd64 0.4.1+git063e8a8-2~bpo70+1
    Des erreur on étés rencontrées pendant l'exécution:
    /var/cache/apt/archives/lua-sec-prosody_0.5.1.2~wheezy_amd64.deb
    E: Sub-process /usr/bin/dpkg returned an error code (1)
    Echec de l'installation d'un paquet. Tentative de réparation:
    ```Merci pour votre aide.

    • [^] # Re: Echec

      Posté par (page perso) . Évalué à 2.

      bin, enlève le paquet lua-sec au préalable et ré-essaie ?

      • [^] # Re: Echec

        Posté par . Évalué à 1.

        Quel noob, merci !

Suivre le flux des commentaires

Note : les commentaires appartiennent à ceux qui les ont postés. Nous n'en sommes pas responsables.