Les relais ouverts

Tester en ligne un serveur SMTP

Il existe un problème de sécurité mal connu sur l’Internet: celui des serveur relais-ouvert. Ce problème concerne les serveurs de messagerie sortante ou SMTP; normalement lorsque l’on envoie un e-mail, on utilise un serveur SMTP destiné à  un usage exclusif. Les personnes autorisées sont généralement celles qui sont issues du même réseau (wanadoo.fr, skynet.be,…)En aucun cas, un serveur SMTP ne devrait pouvoir être utilisé par un utilisateur d’un autre réseau. La raison en est toute simple: quiconque sur Internet serait en mesure de l’utiliser.Le petit « axiome » suivant garantit l’intégrité d’un serveur SMTP:
– le serveur SMTP fait partie du même réseau IP que son utilisateur,
OU
– le serveur SMTP envoie du courrier uniquement vers un utilisateur appartenant à  son réseau IP.Bien sà»r, il peut exister des serveurs intermédiaires destinés à  repartir la charge des transactions SMTP. Maintenant, du fait d’un mauvais paramétrage, un serveur SMTP peut très bien accepter du courrier de n’importe quel utilisateur d’Internet vers n’importe quel autre utilisateur: le serveur SMTP est alors placé en position de relais-ouvert.

Ceci est très dangereux car la plupart des personnes générant du courrier non sollicité (encore appelé spam) utilisent ce genre de relais. Ils ont moins de chance de se faire repérer en utilisant un serveur tiers plutôt que celui de leur FAI (Fournisseur d’Accès Internet).

Pour information, les spammeurs envoient généralement des milliers voire des dizaines de milliers d’emails; on voit clairement le risque encouru lorsqu’un serveur est relais ouvert.

Nous allons maintenant tester manuellement un serveur SMTP afin de voir si oui ou non, celui-ci est un relais ouvert.
La première chose à  faire est d’extraire du DNS le MX (Mailer Exchanger), en fait le nom du serveur SMTP qui peut nous faire entrer sur un domaine de messagerie. Ceci se fait grâce à  la commande NSLOOKUP:
nslookup -q=mx domaine.fr 194.2.0.20

Le « -q=mx » indique que l’on s’intéresse uniquement au champs MX du DNS, le domaine.fr représente le domaine de messagerie et l’adresse IP est tout simplement le DNS que l’on interroge, ici celui d’Oleane.
Le même résultat peut être obtenu avec la commande DIG:
dig mx domaine.fr

En retour, nous obtenons:
mail.domaine.fr

Nous pénétrons sur le serveur au moyen d’un simple telnet:
telnet mail.domaine.fr 25

Le 25 correspond au numéro du port SMTP. En réponse, nous obtenons quelque chose de semblable à  ceci:
220 mail.domaine.fr Simple Mail Transfer Service Ready

Le 220 indique que la connexion a été acceptée et qu’un dialogue SMTP peut commencer.
Nous commençons par nous identifier:
helo mamachine.domaine.com
ou
ehlo mamachine.domaine.com

Nous lui donnons notre adresse SMTP, lui indiquant la source du message:
mail from: moi@mondomaine.com

Attention, le domaine doit exister car bien souvent le serveur SMTP fait une requête DNS pour vérifier que celui-ci n’est pas factice. Certains serveurs demandent également d’utiliser une syntaxe quelque peu différente:
mail from: <moi@mondomaine.com>

Nous lui donnons l’adresse SMTP correspondant au destinataire du message:
rcpt to: lui@sondomaine.com
ou
rcpt to: <lui@sondomaine.com>

Ici, il y a deux possibilités:
554 : Recipient address rejected: Relay access denied

Le code d’erreur 554 indique que le serveur SMTP n’accepte pas le relais.

250 OK

Le code de retour 250 autorise le relais: le serveur est donc un relais ouvert. On ne peut toutefois en être absolument sà»r car certains serveurs peuvent rejeter le relayage après le dialogue SMTP.

Vous avez la possibilité de tester en ligne si un serveur est relais ouvert ou non en cliquant ici.
Le programme consiste à  tester plusieurs formes de relayage possible. Le résultat est toutefois à  prendre au conditionnel car certains serveurs SMTP feignent d’accepter du courrier mais l’effacent par la suite. Toutefois, le fait d’échouer sur le premier test indique tout de même une grosse faille potentielle.

Ce petit programme Perl effectue une dizaine de tests sur un serveur SMTP donné. Il faut, bien sà»r, se trouver à  l’extérieur du réseau sur lequel se trouve ce serveur.
Attention, suivant le serveur que vous utilisez, le programme peut vous indiquer qu’il est relais-ouvert mais en fait il n’en est rien, car le message est rejeté en interne après la clôture de la transaction SMTP.

Si vous voulez être absolument sà»rs que le serveur est un relais ouvert, remplacez les deux variables $domaine et $test dans la fonction tst() respectivement par votre domaine de messagerie ainsi que par votre compte POP.

Exemple:
$domaine= »wanadoo.fr »;
$test= »jacques.vanpiperzen »;

Si le serveur est effectivement relais alors vous recevrez prochainement du courrier.
Le programme demande une adresse IP ou un nom de machine comme argument; il y aurait moyen de l’améliorer en y ajoutant des alarm() afin de pallier à  d’éventuels dépassements de temps sur l’accès au serveur.

La meilleure façon de se protéger efficacement contre le relayage est bien évidement d’avoir un serveur SMTP bien configuré mais ce n’est pas forcément évident à  mettre en oeuvre surtout sur des systèmes aussi complexes qu’Exchange Server ou Lotus Notes; ces deux serveurs demandent généralement une bonne pratique avant d’être parfaitement maà®trisés.

Aussi, je m’appuierai plus sur une sécurité à  l’échelle d’IP; l’avantage est que l’on devient complètement indépendant de la configuration SMTP.
Une approche pourrait être que chaque fois que l’on découvre quelqu’un utilisant son serveur SMTP de façon illicite, alors on interdit à  toute la classe IP de ce même utilisateur d’accéder au serveur. Cette approche (déjà  rencontrée) est très mauvaise:
– elle pénalise autrui, à  savoir les utilisateurs innocents,
– elle ne résout pas le problème,
– a ce rythme, des pans entiers d’Internet ne pourront bientôt plus communiquer avec le serveur.

La meilleure façon de procéder consiste à  appliquer les étapes suivantes:
– Tout d’abord, on laisse gérer le courrier par le FAI; celui-ci dont le métier est l’Internet doit être capable de répondre à  la problématique suivant:
« Je ne veux pas que mon serveur SMTP soit relais ouvert ».
Pour être plus précis, on va confier la gestion du MX du domaine au FAI; suite à  l’extraction du MX, tout le courrier entrant arrivera donc directement chez le FAI.
– Le FAI ré-acheminera tout le courrier sur notre serveur SMTP.
– Le port 25 de notre serveur de messagerie ne sera accessible que par le(s) adresses IP du/des serveur(s) SMTP de notre FAI.

Ceci se fera grâce à  un filtrage élémentaire sur le routeur (Exemple CISCO):
access-list 125 permit tcp host 10.0.0.10 host 192.168.0.10 eq smtp
access-list 125 deny tcp any any eq smtp log

où le 10.0.0.10 représente le serveur du FAI et le 192.168.0.10 le nôtre.
Toutes les autres tentatives d’utiliser le(s) serveur(s) SMTP sont enregistrées.

On peut faire la même chose grâce à  un iptable sous Linux :
/sbin/iptables -A INPUT -j ACCEPT -p tcp -s 10.0.0.10 -d 192.168.0.10 –dport 25

Grâce à  cette technique, on canalise le flux SMTP et on interdit ainsi à  quiconque de l’utiliser, si ce n’est les personnes autorisées.

Surveiller la file d’attente de Sendmail

Lorsque Sendmail reçoit un message, il tente de le livrer à  destination immédiatement. Si cela n’est pas possible alors il le dépose dans sa file d’attente et tente une nouvelle livraison par la suite. Le délai entre deux livraisons est fixé grâce au paramètre « -q » de Sendmail. Par exemple :
# /usr/sbin/sendmail -q15m

fixera à  15 minutes le délai entre deux tentatives de livraison. Idéalement, une file d’attente devrait être toujours vide ; mais bien entendu, cela n’est pas possible : le serveur de destination n’est pas disponible, la charge moyenne du serveur est trop importante, il n’y a pas assez de place sur le disque, etc.

Il est intéressant de surveiller le nombre de messages contenus dans la file d’attente ; ceci permet d’anticiper les pannes et aussi d’isoler certains problèmes récurrents tels que les serveurs en difficulté. Lorsqu’une file d’attente croà®t régulièrement sans se stabiliser alors il arrive un moment où il faut se poser des questions : est-ce que mon serveur est suffisamment bien calibré, ai-je assez de bande passante, etc.

Pour surveiller cette file, nous allons utiliser une combinaison de scripts que nous passerons à  MRTG via SNMP.

Tout d’abord, nous devons extraire le nombre de requêtes contenues dans la file. Ceci se fait via la commande « mailq ». Les informations résultantes de cette dernière ressemblent à  ceci :
h9GFItZ2020003 95399 Thu Oct 16 17:18
8BITMIME (host map: lookup (toulouse.xyz.fr): deferred)
<123@toulouse.xyz.fr>
h9GEvdZ2017358 95399 Thu Oct 16 16:57
8BITMIME (host map: lookup (xyz.fr): deferred)
<5432@xyz.fr>
h9GEEgZ2012871 4567 Thu Oct 16 16:14 <>
8BITMIME (Deferred: Connection refused by m5.labas.com.)

h9GCYYZ2007297 13646 Thu Oct 16 14:34 <>
8BITMIME (Deferred: Connection refused by newton.vanpiperzen.fr.)

Total requests: 708

La dernière ligne nous intéresse directement; ici, il y a donc 708 messages bloqués dans la file d’attente. Afin d’extraire le nombre, une simple combinaison de commandes et un script Awk suffit :
# /usr/bin/mailq | /usr/bin/tail -1 | /usr/bin/awk ‘BEGIN {} { j= $3} END {printf « %s « ,j }’

* La première instruction (mailq) déclenche l’affichage de la file d’attente
* La deuxième passe le résultat dans la commande « tail » qui n’affiche que la dernière ligne ( Total requests: 708)
* Le script awk n’affiche que le dernier mot (708)

Ceci fait, nous allons désormais passer ces informations à  MRTG; la façon la plus commode est d’utiliser SNMP.
Pour ce faire, il faut rajouter un OID propriétaire dans le snmpd.conf ; ici, nous travaillons avec ucd-snmp. Voici cet OID :
exec .1.3.6.1.4.1.2021.61 queue /home/s/queue.sh

Avec le script queue.sh contenant:
# !/bin/sh
# /usr/bin/mailq | /usr/bin/tail -1 | /usr/bin/awk ‘BEGIN {} { j= $3} END {printf « %s « ,j }’

Ceci terminé, il faut relancer le SNMP : # service snmpd restart (Sous RedHat)
# /etc/init.d/snmpd restart (Autre)

Essayons d’extraire les différents OID depuis la NMS (Network Management Server) :
# snmpwalk serveur-sendmail communaute enterprises.ucdavis.61
enterprises.ucdavis.61.1.1 = 1
enterprises.ucdavis.61.2.1 = « queue »
enterprises.ucdavis.61.3.1 = « /home/s/queue.sh »
enterprises.ucdavis.61.100.1 = 0
enterprises.ucdavis.61.101.1 = « 522 »
enterprises.ucdavis.61.102.1 = 0

Ca fonctionne, et nous allons donc travailler avec l’OID enterprises.ucdavis.61.101.1
La prochaine étape est de créer une entrée MRTG afin de grapher régulièrement les entrées obtenues par notre script. La seule difficulté est que notre script Awk renvoie l’information sous forme de caractères; MRTG, quand à  lui, attend un nombre. Nous allons donc devoir encore développer un script pour convertir la chaà®ne de caractères en nombre. Voici ce script, écrit en PERL, nous l’appellerons queue.pl :
#!/usr/bin/perl
$ip = shift @ARGV;
$com = shift @ARGV;
$mib1 = shift @ARGV;
$etat=`snmpget $ip $com $mib1`;
chomp($etat);
($etat) = ($etat =~ /= « (.+) »/);
if($etat eq «  »)
{
print « 0\n0\n »;
}
else
{
print « $etat\n$etat\n »;
}

Le script commence par récupérer l’OID au moyen de l’instruction « snmpget », puis il nettoie la chaà®ne des guillemets et finalement affiche le nombre en deux exemplaires, car MRTG attend toujours un minimum de deux nombres.
Pour utiliser notre script, il faudra donc taper :
# ./queue.pl
522
522

Il ne nous reste plus qu’à  créer le chapitre MRTG :
Target[sendmail.queue]: `/home/s/queue.pl 192.168.0.2 com enterprises.ucd avis.61.101.1`
Directory[sendmail.queue]: sendmail
Options[sendmail.queue]: gauge,nopercent
MaxBytes[sendmail.queue]: 3500
XSize[sendmail.queue]: 580
YSize[sendmail.queue]: 100
YLegend[sendmail.queue]: Nbre de messages en attente
ShortLegend[sendmail.queue]: msg
Legend1[sendmail.queue]: Messages en attente
Legend2[sendmail.queue]: Messages en attente
LegendI[sendmail.queue]: Messages en attente
LegendO[sendmail.queue]: Messages en attente
Title[sendmail.queue]:Messages dans la file d’attente
PageTop[sendmail.queue]: <H1>Messages dans la file d’attente sur Sendmail</H1>

Note: des problèmes peuvent survenir avec SNMP et la commande mailq en cas de surcharge du serveur ; il est tout à  fait envisageable que MRTG soit dans l’incapacité de récupérer les informations. Pour pallier à  ce problème, le mieux est de faire tourner le script qui va chercher le nombre de messages dans la file d’attente directement sur le serveur SMTP ; ce script devra être lancé régulièrement via une entrée dans la crontab et le résultat placé dans un fichier. Après, ce nombre pourra être récupéré par SNMP par un simple « cat ».

Transformer des adresses grâce à  Sendmail

Dans un environnement de messagerie, il est parfois intéressant de pouvoir transformer des adresses email:
Lorsqu’une entreprise change de dénomination sociale, une personne se marie et change de nom, pour des raisons de sécurité, etc.

Sendmail offre un dispositif standard de réécriture d’adresses: la genericstable.
Ce dispositif est destiné à  transformer une adresse en une autre durant l’expédition d’un message. Malheureusement, ceci ne fonctionne qu’avec les domaines locaux, ceux qui sont gérés via le local-host-name. Le problème se pose donc lorsque l’on veut modifier une adresse distante, celle d’un FAI par exemple.

Heureusement, la grande force de Sendmail est justement de pouvoir réécrire n’importe quelle adresse. Il suffit donc de créer une nouvelle règle et de l’insérer dans le fichier sendmail.mc. Néanmoins pour des raisons de clarté, il est préférable de mettre la règle dans un fichier satellite.

J’ai appelé celui-ci « rewrite », et en voici son contenu:

LOCAL_RULE_3
D{DOMAINE}mon-domaine.com #` mon-domaine.com’
D{WANAGOO}wanagoo.fr #`wanagoo.fr’
Rlaurent<@${DOMAINE}>$* laurent.baloche<@${WANAGOO}>$1
Rcharles<@${DOMAINE}>$* charles.vanpiperzen<@${WANAGOO}>$1

Et en voici les explications:

Tout d’abord, la règle sera placée dans le groupe numéro 3 (LOCAL_RULE_3) en charge du prétraitement des adresses.
La lettre D définit la macro « DOMAINE » et y affecte le domaine, ici mon-domaine.com.
La lettre D définit la macro « WANAGOO » et y affecte le domaine distant, ici wanagoo.fr.
L’instruction suivante utilise la réécriture, la lettre « R » pour transformer l’adresse initiale lauren@mon-domaine.com en laurent.baloche@wanagoo.fr.
Idem pour charles@mon-domaine.com qui est transformée en charles.vanpiperzen@wanagoo.fr

Ceci fait, il suffit d’inclure les règles dans le fichier sendmail.mc:

include(`/etc/mail/rewrite’)

Puis de reconstruire le sendmail.cf:

#m4 sendmail.mc >sendmail.cf

et enfin faire relire à  sendmail sa configuration:

#kill -HUP `head -1 /var/run/sendmail.pid’

Attention, cette opération doit être exécutée à  chaque fois que l’on insère une nouvelle entrée dans le fichier rewrite.

Le SMTP spoolé

Même si la plupart d’entre nous possède désormais une connexion permanente à  Internet comme l’ADSL ou le câble, il existe encore des situations où l’on utilise des connexions intermittentes comme le RNIS, l’ISDN ou le RTC: liens de secours, lieux non-couverts par l’ADSL, etc.

Celui qui utilise une connexion intermittente se retrouve généralement face à  la problématique suivante: Comme la connexion n’est pas permanente, il n’est à  priori pas possible d’avoir son propre serveur SMTP gérant la réception du courrier en provenance de l’Internet. On doit alors laisser la gestion de tout le courrier électronique au FAI (Fournisseur d’Accès Internet), ce qui est somme toute dommage, surtout si l’on dispose d’un service informatique capable de gérer les services Internet.

Il est toutefois possible de contourner ce problème grâce aux extensions du protocole SMTP, défini par le ESMTP (Extended Simple Mail Protocol).

L’idée est la suivante:
– le courrier arrive sur le serveur SMTP du FAI,
– le FAI stocke le courrier dans une file d’attente,
– le client récupère toute la file d’attente lorsqu’il se connecte.

Attention, ici il n’est nullement question d’accéder à  des boites aux lettres via POP mais bien de récupérer toute la file d’attente SMTP d’un domaine sans se soucier d’éventuelles erreurs de destinataires. Ces mêmes erreurs seront gérées par la suite par le serveur SMTP de destination; le FAI n’a qu’un rôle d’intermédiaire: il est serveur-relais, tout simplement.

Le mécanisme de récupération de la file d’attente SMTP se fait via la commande ETRN; c’est cette même commande qui sera étudiée plus tard et un petit programme en C illustrera son utilisation.

Voici la trame d’un message transitant depuis l’émetteur du message jusqu’au destinataire final, au-delà  de la connexion intermittente:

Le client envoie son message vers son serveur de courrier via une transaction SMTP. Ce même serveur extrait le MX (Mail Exchanger) de son DNS et l’expédie via une autre requête SMTP sur le serveur relais. Ce dernier se contente de stocker le message dans la file d’attente; à  ce stade, il n’y a plus aucune notion de délai de livraison: c’est le client lui même qui va récupérer le courrier quand bon lui semble. Lorsque la connexion intermittente monte, le serveur SMTP de destination exécute la commande ETRN et toute la file d’attente est récupérée. Le destinataire du message n’a plus qu’à  récupérer son courrier via POP.

Une commande ETRN consiste en fait à  accéder au port 25 d’un serveur SMTP, et à  envoyer cette même commande. Le serveur SMTP tente alors d’accéder au port 25 de l’émetteur de la transaction et déclenche un dialogue SMTP entre les deux serveurs.
Le dialogue suivant vous montre comment se passe une transaction ETRN:
telnet mx.mondomaine.fr 25
220 mx.mondomaine.fr ESMTP Sendmail 8.10.0/8.10.0;
ehlo mx.tondomaine.fr
250-mx.mondomaine.fr Hello mx.tondomaine.fr [192.168.0.1] (may be forged),
etrn @tondomaine.fr
250 2.0.0 Queuing for node @tondomaine.fr started
quit
221 2.0.0 mx.mondomaine.fr closing connection

La commande « etrn @mx.tondomaine.fr » déclenche la transaction SMTP entre les deux serveurs. Il y a deux façons d’utiliser la commande ETRN:
soit par domaine (@tondomaine.fr), soit par file d’attente (#file), cela dépend du fournisseur et de sa façon de procéder.
Attention, la commande ETRN ne fonctionne qu’avec des serveurs ESMTP, d’où le « ehlo » qui est là  pour tester la nature du serveur.

Dans la plupart des cas, le serveur utilisé est un Sendmail 8.10 ou plus doté d’une mailertable pour rediriger le courrier grâce à  un mailer particulier appelé DSMTP.
Ci-dessous, un exemple de configuration pour sendmail:
Sendmail.mc
divert(-1)
dnl
dnl Configuration sendmail côté FAI
dnl
divert(0)
include(`/usr/lib/sendmail-cf/m4/cf.m4′)
VERSIONID(`Sendmail pour mx0.d0.com’)dnl
OSTYPE(`linux’)dnl
define(`confMAX_MESSAGE_SIZE’, `5000000′)dnl
define(`STATUS_FILE’, `/etc/mail/sendmail.st’)dnl
define(`confDOMAIN_NAME’, `mx0.d0.com’)dnl
define(`ALIAS_FILE’, `/etc/mail/aliases’)dnl
define(`confTO_QUEUEWARN’, `72h’)dnl
define(`confTO_QUEUERETURN’, `7d’)dnl
FEATURE(`access_db’,`hash -o /etc/mail/access’)dnl
FEATURE(`mailertable’,`hash -o /etc/mail/mailertable’)dnl
FEATURE(always_add_domain)dnl
MAILER(smtp)dnl

Mailertable
d1.com dmstp:[mail.d0.com]
d2.com dmstp:[mail.d0.com]
d3.com dmstp:[mail.d0.com]
d4.com dmstp:[mail.d0.com]

Sendmail.mc
divert(-1)
dnl
dnl Configuration sendmail sur une ligne RNIS/ISDN
dnl
divert(0)
include(`/usr/lib/sendmail-cf/m4/cf.m4′)
VERSIONID(`Sendmail pour mail.d0.com’)dnl
OSTYPE(`linux’)dnl
define(`confMAX_MESSAGE_SIZE’, `5000000′)dnl
define(`STATUS_FILE’, `/etc/mail/sendmail.st’)dnl
define(`confDOMAIN_NAME’, `mail.d0.com’)dnl
define(`SMART_HOST’,`esmtp:[mx0.d0.com]’)dnl
define(`confCON_EXPENSIVE’, `true’)dnl
define(`ALIAS_FILE’, `/etc/mail/aliases’)dnl
define(`confTO_QUEUEWARN’, `72h’)dnl
define(`confTO_QUEUERETURN’, `7d’)dnl
MODIFY_MAILER_FLAGS(`SMTP’,`+e’)dnl
FEATURE(`access_db’,`hash -o /etc/mail/access’)dnl
FEATURE(`virtusertable’,`hash -o /etc/mail/virtusertable’)dnl
FEATURE(always_add_domain)dnl
FEATURE(local_procmail)dnl
FEATURE(use_cw_file)dnl
MAILER(smtp)dnl

Pour lancer l’ETRN, placez ce petit programme dans votre crontab sur la machine au delà  de la connexion intermittente.