Exploring the roots and future of Internet Relay Chat

TLS/SSL sur un serveur IRC avec Let's Encrypt

En 2008, j'ai configure TLS sur un serveur IRC pour la premiere fois. Le processus impliquait de generer un CSR, de l'envoyer a une autorite de certification par email, d'attendre 48 heures, de recevoir le certificat, de concatener les intermediaires dans le bon ordre, et de prier pour que le client IRC de tout le monde accepte la chaine. Aujourd'hui, Let's Encrypt delivre un certificat valide en 30 secondes. Il n'y a plus aucune excuse pour faire tourner un serveur IRC sans TLS.

Pourquoi TLS sur IRC

Sans TLS, le trafic IRC circule en clair. Tout ce qui passe entre le client et le serveur — messages, mots de passe NickServ, commandes OPER — est lisible par quiconque intercepte le trafic. Sur un reseau WiFi public, c'est trivial.

TLS chiffre la connexion entre le client et le serveur IRC. Un observateur ne voit que du trafic chiffre — il sait que vous utilisez IRC (le port le revele) mais pas ce que vous dites. C'est la meme protection que HTTPS pour le web.

Les raisons de deployer TLS :

  • Confidentialite : Les messages prives et les mots de passe ne circulent plus en clair.
  • Authentification serveur : Le client verifie qu'il se connecte au bon serveur et pas a un imposteur (attaque MITM).
  • Authentification client : Le CertFP (fingerprint du certificat client) permet l'identification sans mot de passe. Plus sur que SASL PLAIN.
  • Confiance : Un serveur avec TLS et un certificat valide inspire plus de confiance. Les utilisateurs techniques verifieront.
Rappel : TLS protege le trafic entre le client et le serveur (et entre serveurs links). Il ne protege PAS les messages une fois arrives sur le serveur. Un operateur IRC peut toujours lire les messages qui transitent par son serveur. Pour une confidentialite de bout en bout, il faudrait du chiffrement E2E — ce qu'IRC ne supporte pas nativement.

Obtenir un certificat Let's Encrypt

# Installer Certbot :
sudo apt update
sudo apt install certbot

# Methode 1 : Standalone (le plus simple)
# Necessite que le port 80 soit libre
sudo certbot certonly --standalone -d irc.votredomaine.com

# Methode 2 : Webroot (si un serveur web tourne deja)
sudo certbot certonly --webroot -w /var/www/html \
  -d irc.votredomaine.com

# Methode 3 : DNS challenge (pas besoin de port 80)
# Utile si votre serveur IRC n'a pas de serveur web
sudo certbot certonly --manual --preferred-challenges dns \
  -d irc.votredomaine.com
# Certbot vous demandera de creer un enregistrement TXT

# Les certificats sont stockes dans :
# /etc/letsencrypt/live/irc.votredomaine.com/
#   fullchain.pem   <- Certificat + intermediaires
#   privkey.pem     <- Cle privee
#   cert.pem        <- Certificat seul
#   chain.pem       <- Intermediaires seuls

Le challenge standalone est le plus simple pour un serveur IRC dedie. Si aucun serveur web ne tourne sur la machine, le port 80 est libre et Certbot peut l'utiliser temporairement pour la validation.

Pour le DNS challenge, vous devez avoir acces a la configuration DNS de votre domaine. C'est plus lent (propagation DNS) mais ne necessite aucun port ouvert. Certains plugins Certbot supportent l'automatisation du DNS challenge avec des APIs de registrars (Cloudflare, OVH, etc.).

Configuration UnrealIRCd

# Copier les certificats pour l'utilisateur ircd :
sudo cp /etc/letsencrypt/live/irc.votredomaine.com/fullchain.pem \
  /home/ircd/unrealircd/conf/tls/server.cert.pem
sudo cp /etc/letsencrypt/live/irc.votredomaine.com/privkey.pem \
  /home/ircd/unrealircd/conf/tls/server.key.pem
sudo chown ircd:ircd /home/ircd/unrealircd/conf/tls/*.pem
sudo chmod 600 /home/ircd/unrealircd/conf/tls/*.pem

# Dans unrealircd.conf :
set {
  tls {
    certificate "/home/ircd/unrealircd/conf/tls/server.cert.pem";
    key "/home/ircd/unrealircd/conf/tls/server.key.pem";
    options {
      no-client-certificate;
    };
    /* Ciphers modernes (TLS 1.2+) */
    ciphers "TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256";
    protocols "TLSv1.2,TLSv1.3";
  };
};

# Listener TLS :
listen {
  ip *;
  port 6697;  /* Port standard pour IRC sur TLS */
  options { tls; };
};

# Appliquer sans redemarrer :
./unrealircd rehash

Le port 6697 est le port standard pour IRC sur TLS (defini dans RFC 7194). Gardez aussi le port 6667 en non-TLS si vous voulez accepter les connexions non chiffrees — mais encouragez TLS dans le MOTD.

Configuration InspIRCd

# Copier les certificats :
sudo cp /etc/letsencrypt/live/irc.votredomaine.com/fullchain.pem \
  /home/ircd/inspircd-install/conf/cert.pem
sudo cp /etc/letsencrypt/live/irc.votredomaine.com/privkey.pem \
  /home/ircd/inspircd-install/conf/key.pem
sudo chown ircd:ircd /home/ircd/inspircd-install/conf/*.pem
sudo chmod 600 /home/ircd/inspircd-install/conf/*.pem

# Generer les parametres DH (optionnel, GnuTLS) :
certtool --generate-dh-params \
  --outfile /home/ircd/inspircd-install/conf/dhparams.pem

# Dans inspircd.conf :

# Charger le module TLS :

# Ou : 

# Configuration GnuTLS :


# Configuration OpenSSL (alternative) :
# 

# Listener TLS :


# Recharger sans redemarrer :
/REHASH

InspIRCd supporte deux backends TLS : GnuTLS et OpenSSL. GnuTLS est le choix recommande — l'integration est plus mature et la configuration de priorite est plus lisible. Utilisez OpenSSL seulement si vous avez une raison specifique (compliance, HSM).

Renouvellement automatique

Les certificats Let's Encrypt expirent apres 90 jours. Le renouvellement doit etre automatise.

# Certbot renouvelle automatiquement via un timer systemd
# ou un cron. Verifiez :
sudo systemctl list-timers | grep certbot
# Ou :
crontab -l | grep certbot

# Le probleme : apres renouvellement, il faut copier
# les nouveaux certificats et notifier l'IRCd.

# Solution 1 : deploy hook de Certbot
# Creer /etc/letsencrypt/renewal-hooks/deploy/ircd.sh :

#!/bin/bash
# Copier les certificats renouveles
cp /etc/letsencrypt/live/irc.votredomaine.com/fullchain.pem \
  /home/ircd/unrealircd/conf/tls/server.cert.pem
cp /etc/letsencrypt/live/irc.votredomaine.com/privkey.pem \
  /home/ircd/unrealircd/conf/tls/server.key.pem
chown ircd:ircd /home/ircd/unrealircd/conf/tls/*.pem
chmod 600 /home/ircd/unrealircd/conf/tls/*.pem

# Notifier l'IRCd (rehash pour recharger les certificats)
kill -HUP $(cat /home/ircd/unrealircd/data/unrealircd.pid)

chmod +x /etc/letsencrypt/renewal-hooks/deploy/ircd.sh

# Solution 2 : Cron hebdomadaire
# Moins elegant mais fonctionne :
# Ajouter dans la crontab root :
0 3 * * 1 /usr/bin/certbot renew --quiet && \
  /etc/letsencrypt/renewal-hooks/deploy/ircd.sh

# Solution 3 : Symlinks (le plus simple)
# Au lieu de copier, faire des liens symboliques.
# Attention : l'utilisateur ircd doit pouvoir lire
# les fichiers dans /etc/letsencrypt/live/
# (par defaut, seul root peut).
sudo chmod 750 /etc/letsencrypt/live/
sudo chmod 750 /etc/letsencrypt/archive/
sudo chgrp ircd /etc/letsencrypt/live/
sudo chgrp ircd /etc/letsencrypt/archive/
ln -s /etc/letsencrypt/live/irc.votredomaine.com/fullchain.pem \
  /home/ircd/unrealircd/conf/tls/server.cert.pem
ln -s /etc/letsencrypt/live/irc.votredomaine.com/privkey.pem \
  /home/ircd/unrealircd/conf/tls/server.key.pem
Attention : La methode des symlinks est la plus simple mais modifie les permissions par defaut de Let's Encrypt. Si d'autres services utilisent les memes certificats, verifiez que les permissions restent correctes pour tout le monde. La copie avec deploy hook est plus sure dans un environnement multi-services.

Verification et debug

# Verifier le certificat avec openssl :
openssl s_client -connect irc.votredomaine.com:6697 \
  -servername irc.votredomaine.com

# Ce que vous devez voir :
# - "Verify return code: 0 (ok)" -> chaine valide
# - Le bon CN ou SAN dans le certificat
# - La date d'expiration (Not After)

# Verifier les dates :
openssl s_client -connect irc.votredomaine.com:6697 \
  -servername irc.votredomaine.com 2>/dev/null | \
  openssl x509 -noout -dates

# Verifier la chaine complete :
openssl s_client -connect irc.votredomaine.com:6697 \
  -servername irc.votredomaine.com -showcerts

# Verifier les ciphers supportes :
nmap --script ssl-enum-ciphers -p 6697 irc.votredomaine.com

# Tester depuis un client IRC :
# En irssi, la connexion TLS affiche :
# "The server's certificate is trusted"
# Si le certificat n'est pas valide :
# "The server's certificate is NOT trusted"

# En WeeChat :
# /set irc.server.monserveur.ssl_verify on
# Si la verification echoue, WeeChat refuse la connexion

Si openssl s_client affiche "Verify return code: 0 (ok)", votre configuration est correcte. Si vous voyez une erreur comme "unable to verify the first certificate", c'est que la chaine intermediaire est incomplete — utilisez fullchain.pem, pas cert.pem.

Configuration avancee

Pour les administrateurs qui veulent durcir leur configuration TLS :

  • Desactiver TLS 1.0 et 1.1 : Ces versions ont des vulnerabilites connues. N'acceptez que TLS 1.2 et 1.3. Tous les clients IRC modernes supportent TLS 1.2.
  • Preferer les ciphers AEAD : AES-GCM et ChaCha20-Poly1305. Evitez CBC qui est vulnerable au padding oracle.
  • OCSP Stapling : Certains IRCds supportent l'agrafage OCSP, qui permet au serveur de prouver que son certificat n'a pas ete revoque sans que le client contacte l'autorite de certification.
  • CertFP pour l'authentification : Les utilisateurs peuvent s'identifier avec un certificat client. Le fingerprint SHA-256 du certificat est lie au compte NickServ. C'est plus sur qu'un mot de passe.
# Generer un certificat client pour CertFP :
openssl req -x509 -new -newkey ec \
  -pkeyopt ec_paramgen_curve:prime256v1 \
  -sha256 -days 3650 -nodes \
  -keyout irc-client.key -out irc-client.cert \
  -subj "/CN=VotreNick"

# Voir le fingerprint :
openssl x509 -in irc-client.cert -noout -fingerprint -sha256

# Configurer dans irssi :
/server add -auto -tls -tls_cert ~/.irssi/irc-client.cert \
  -tls_pkey ~/.irssi/irc-client.key \
  -network Libera irc.libera.chat 6697

# Enregistrer le fingerprint dans NickServ :
/msg NickServ CERT ADD

Questions frequentes

Le certificat auto-signe est-il suffisant ?

Techniquement, un certificat auto-signe chiffre le trafic aussi bien qu'un certificat Let's Encrypt. Mais les clients affichent un avertissement et la plupart refusent la connexion par defaut. Avec Let's Encrypt gratuit et automatique, il n'y a plus de raison d'utiliser un auto-signe en production.

Faut-il garder le port 6667 non-TLS ?

Opinion controversee : non. Si votre serveur est destine a des utilisateurs competents, n'ouvrez que le 6697 TLS et forcez la migration. Si vous avez des utilisateurs avec des clients anciens qui ne supportent pas TLS (cas rare en 2025), gardez le 6667 temporairement avec un message MOTD incitant a migrer.

Wildcard ou certificat par hostname ?

Pour un seul serveur, un certificat par hostname (irc.votredomaine.com) suffit. Pour un reseau avec plusieurs serveurs (irc1, irc2, irc3), un wildcard (*.votredomaine.com) simplifie la gestion. Let's Encrypt supporte les wildcards mais uniquement avec le DNS challenge.