Crowdsec – ispconfig / iptables

Je suis passé de fail2ban (que j’utilise depuis lonnngtemps) à Crowdsec pour les raisons suivantes :

  • fail2ban est (très) gourmand en ressource serveur (trop)
  • Crowdsec dispose d’un volet « scénario » que je trouve bien malin et qui le rend « plus intelligent » et permet de mutualiser les IP frauduleuse.

Au final je bloque certainement plus d’attaques pour bien moins de CPU (surtout) consommés.

C’est plutôt flagrant sur le côté « économie de ressources CPU » sur les graph :

Comparatif stats (munin) avant avec fail2ban et après avec crowdsec

Mise en œuvre

Mon contexte : des serveurs avec le panel ISPconfig (ce dernier écoute sur le port 8080 – important pour la suite) sur Debian 11.

Je ne vais pas détailler ici ce qu’il y a dans la documentation Crowdsec, d’autant que ça peut changer. Pour mon OS (Debian) actuellement c’est :

# Installation du dépôt
curl -s https://install.crowdsec.net | sudo sh
# Installation de crowdsec
apt install crowdsec

Du coup, comme ISPconfig écoute déjà sur le port 8080 et que Crowdsec utilise ce port pour son API il faut modifier celui-ci (moi je passe à 8079) :

sed -i -e "s/8080/8079/g" /etc/crowdsec/config.yaml
sed -i -e "s/8080/8079/g" /etc/crowdsec/local_api_credentials.yaml
systemctl restart crowdsec

ISPconfig n’utilise pas logrotate pour la rotation de log apache, il a son propre processus intégré. Pour que Crowdsec puisse lire tout les logs HTTP (ici apache) il va falloir lui donner le chemin. MAIS. ISPconfig nomme les logs par date et créer un lien symbolique vers « access.log » :

# ls /var/log/ispconfig/httpd/david.mercereau.info/ -la
total 173480
drwxr-xr-x   2 root root     4096 30 juin  12:19 .
drwxr-xr-x 176 root root    12288 21 juin  16:05 ..
[...]
-rw-r--r--   1 root root  4712747 29 juin  23:59 20240629-access.log
-rw-r--r--   1 root root  2836678 30 juin  14:08 20240630-access.log
lrwxrwxrwx   1 root root       19 30 juin  12:19 access.log -> 20240630-access.log
lrwxrwxrwx   1 root root       55 30 juin  00:12 yesterday-access.log -> /var/www/clients/client3/web196/log/20240629-access.log

Ceci cause un problème pour la surveillance des changement crowdsec : https://github.com/crowdsecurity/crowdsec/issues/574. On pourrait indiquer /var/log/ispconfig/httpd/*/access.log mais il faudrait modifier le paramètre : https://docs.crowdsec.net/docs/data_sources/file/#poll_without_inotify et les performances (occupation) CPU s’en font directement sentir… C’est dommage. J’ai donc préféré indiquer /var/log/ispconfig/httpd//*[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]*.log à crowdsec :

echo "filenames:
  # Vhost
  - /var/log/ispconfig/httpd/*/[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]*.log
labels:
  type: apache2" > /etc/crowdsec/acquis.d/ispconfig.yaml

Mais pour que le « nouveau » log soit pris en considération je fais un restart du service crowdsec à 0:20 (la rotation ayant lieu à ~0:10) chez moi au vu des date de création des fichiers de logs :

20 0 * * * systemctl restart crowdsec

C’est un peu du bricolage mais c’est le meilleurs compromis que j’ai jusque là.

EDIT : j’ai changé mon fusil d’épaule pour (aussi) ménager le nombre de fichier suivi par crowdsec (j’ai un serveur avec 200 vhost). En effet je me suis rendu compte que /var/log/apache2/other_vhosts_access.log était surveillé via /etc/crowdsec/acquis.yaml donc il y avait double surveillance des access. J’ai donc juste ajouté les « error.log » dans mon /etc/crowdsec/acquis.d/ispconfig.yaml

filenames:
  - /var/log/ispconfig/httpd/*/error.log
labels:
  type: apache2

J’ajoute d’autres « collection » en fonction des services que j’ai sur ce serveur :

cscli collections install crowdsecurity/base-http-scenarios
cscli scenarios install   crowdsecurity/http-bf-wordpress_bf  crowdsecurity/http-bf-wordpress_bf_xmlrpc  crowdsecurity/http-wordpress_user-enum  crowdsecurity/http-wordpress_wpconfig
cscli collections install crowdsecurity/dovecot
echo "filenames:
  - /var/log/mail.log
labels:
  type: syslog " > /etc/crowdsec/acquis.d/mail.yaml 
cscli collections install fulljackz/pureftpd

A ce stade il n’y a aucun ‘effet’ (pas de blocage). De mon côté j’utilise le firewall iptables donc j’ai utiliser le bouncer qui va bien pour lui :

apt install crowdsec-firewall-bouncer-iptables

De la même façon on change le port pour joindre l’API

sed -i -e "s/8080/8079/g" /etc/crowdsec/bouncers/crowdsec-firewall-bouncer.yaml
systemctl restart crowdsec-firewall-bouncer

Des commandes utiles :

cscli decision list  
cscli alert list
# Pour voir toutes les IP blacklisté (intégrant les IP renvoyé par l'API centrale crowdsec
ipset list crowdsec-blacklists 
# Supprimer une IP bloqué
cscli decisions delete -i x.x.x.x

Il est possible d’aller bien plus loin, avant de blacklisté on peut demander un captcha à l’utilisateur : https://www.it-connect.fr/comment-proteger-son-site-wordpress-avec-crowdsec/ (pas mal…)

Ressources :

Bémols

Du fait de la « mutualisation » des blacklistes il y a de la data qui est envoyé chez un tiers… bon même si la société est Française le site est hébergé à San Francisco (mention légal) Typiquement le modèle économique est de récupérer de la data (les IP malveillantes) sur les « crowdsec community » pour détecter des intrusions et vendre des bases d’IP à bloquer aux autres… (note : ce partage vers l’API centrale est désactivable : FAQ / Troubleshooting | CrowdSec)

Le dashboard local est déprécié Cscli dashboard deprecation | CrowdSec au profil de l’APP en ligne crowdsec non open source pour le coup… (pour le coup c’est pas indispensable à l’usage de Crowdsec)

J’ai l’impression que le modèle économique se dessine et que ça se ferme un peu…

Toute proportion gardé bien sûr, on parle d’IP malveillante et non de data utilisateur… Je voudrais pas faire mon « libo-terroriste » hein :slight_smile:

Plugin Munin

Moi j’aime bien monitorer ce qui ce passe et comme le dashboard local Crowdsec n’est plus maintenu, a minima j’ai fais un plugin pour avoir des graph’ dans Munin :

Il permet d’avoir des graph’s par pays et par scénario.

ISPconfig : migrer Mailman2 vers Sympa

Debian 11 ne supporte plus mailman2, et mailman2 n’est plus maintenu depuis… (trop longtemps) il était donc grand temps de changer d’outil pour les mailings liste… Oui mais voilà, mon panel c’est ISPconfig et celui-ci ne supporte pour le moment QUE mailman2 🙁 (pas de mailman3 ni de sympa prévu)

Pour l’instant mon serveur est en Debian 10, mais dans l’optique d’un migration vers Debian 11 il fallait avancer. Après avoir tester mailman3 je me suis dit qu’il était très lourd (en ressources serveurs) par rapport à mon besoin (il s’avère être dimensionné pour les gros système) de plus il c’est un jeune logiciel alors que Sympa a de la bouteille, sont développement est encore soutenu, il est léger et des scripts de migration existe, ça serait donc Sympa !

A noter que beaucoup migre vers Discourse qui ouvre d’autres possibilités.

Tant pi pour l’intégration dans le panel ISPconfig pour le moment.. Un jour peut être…

Installation

Installation de sympa

Sur mon serveur Debian 10 j’ai commencé par installer Sympa en parallèle de Mailman2 :

# Pour éviter une erreur dpkg
echo "retzo.net" > /etc/mailname
apt install sympa # dire non à toutes les questions apt... on s'en occupe après...

Ensuite je crée la base de donnée MySql « sympa » avec un utilisateur restreint.

SELECT PASSWORD('MOTDEPASSE');
# Récupérer le hash du mot de passe
CREATE USER 'sympa'@'localhost' IDENTIFIED VIA mysql_native_password USING '*F72C19A910531DA39D6EC7BB91BEB11A37753023'; 
GRANT USAGE ON *.* TO 'sympa'@'localhost' REQUIRE NONE WITH MAX_QUERIES_PER_HOUR 0 MAX_CONNECTIONS_PER_HOUR 0 MAX_UPDATES_PER_HOUR 0 MAX_USER_CONNECTIONS 0;
CREATE DATABASE IF NOT EXISTS `sympa`;
GRANT ALL PRIVILEGES ON `sympa`.* TO 'sympa'@'localhost';
FLUSH PRIVILEGES;

Modification de l’URL (j’aime pas /wws/ je préfère /sympa ) dans le fichier /etc/apache2/conf-enabled/sympa.conf

-    ScriptAlias /wws /usr/lib/cgi-bin/sympa/wwsympa-wrapper.fcgi
+    ScriptAlias /sympa /usr/lib/cgi-bin/sympa/wwsympa-wrapper.fcgi

Je modifie ensuite le fichier /etc/sympa/sympa/sympa.conf

- listmaster      listmaster@retzien.fr
+ listmaster      adresse-email-admin@retzo.net
- lang    en
+ lang    fr
- wwsympa_url     http://retzo.net/wws
+ wwsympa_url     http://lists.retzo.net/sympa
+ db_type        MySQL
+ db_host        localhost
+ db_port        3306
+ db_name        sympa
+ db_user        sympa
+ db_passwd      plvlOBpDuljmz0Dh

Je relance sympa pour qu’il crée les tables :

service sympa restart ; service apache2 restart

Lancer la commande suivante et lire les instructions selon votre cas

sympa_wizard --check

Pour ma part le check révèle surtout qu’il manque Data::Password

cpan install Data::Password

Intégration dans postfix (multi domaines)

Ensuite j’ai suivi la documentation pour les « multi-domaines » avec Postfix : https://sympa-community.github.io/manual/install/configure-mail-server-postfix.html#virtual-domain-setting

Pour la suite on va enter ces variables dans le terminal, ça nous simplifia la lecture :

SYSCONFDIR=/etc/sympa
EXPLDIR=/var/lib/sympa/list_data

Créer le fichier $SYSCONFDIR/list_aliases.tt2

#--- [% list.name %]@[% list.domain %]: list transport map created at [% date %]
[% list.name %]@[% list.domain %] sympa:[% list.name %]@[% list.domain %]
[% list.name %]-request@[% list.domain %] sympa:[% list.name %]-request@[% list.domain %]
[% list.name %]-editor@[% list.domain %] sympa:[% list.name %]-editor@[% list.domain %]
[% list.name %]-subscribe@[% list.domain %] sympa:[% list.name %]-subscribe@[%list.domain %]
[% list.name %]-unsubscribe@[% list.domain %] sympa:[% list.name %]-unsubscribe@[% list.domain %]
[% list.name %][% return_path_suffix %]@[% list.domain %] sympabounce:[% list.name %]@[% list.domain %]

Ajouter les lignes suivantes à la fin du fichier /etc/sympa/sympa/sympa.conf

sendmail_aliases /etc/sympa/sympa_transport
aliases_program postmap
aliases_db_type hash

Créer les fichiers qui vont bien :

touch $SYSCONFDIR/transport.sympa
touch $SYSCONFDIR/virtual.sympa
touch $SYSCONFDIR/sympa_transport
chmod 644 $SYSCONFDIR/sympa_transport
chown sympa:sympa $SYSCONFDIR/sympa_transport
postmap hash:$SYSCONFDIR/transport.sympa
postmap hash:$SYSCONFDIR/virtual.sympa
/usr/lib/sympa/bin/sympa_newaliases.pl
postmap hash:$SYSCONFDIR/sympa_transport
chmod 640 $SYSCONFDIR/sympa_transport $SYSCONFDIR/sympa_transport.db
chgrp postfix $SYSCONFDIR/sympa_transport $SYSCONFDIR/sympa_transport.db

Dans le fichier /etc/postfix/master.cf ajouter à la fin :

sympa   unix    -       n       n       -       -       pipe
flags=hqRu null_sender= user=sympa argv=/usr/lib/sympa/bin/queue ${nexthop}
sympabounce unix -     n       n       -       -       pipe
flags=hqRu null_sender= user=sympa argv=/usr/lib/sympa/bin/bouncequeue ${nexthop}

Modifier le fichier /etc/postfix/main.cf comme suite, supprimer ce qui est mailman au profil de sympa :

- alias_maps = hash:/etc/aliases, hash:/var/lib/mailman/data/aliases
- alias_database = hash:/etc/aliases, hash:/var/lib/mailman/data/aliases
+ alias_maps = hash:/etc/aliases
+ alias_database = hash:/etc/aliases
- virtual_alias_maps = hash:/var/lib/mailman/data/virtual-mailman, proxy:mysql:/etc/postfix/mysql-virtual_forwardings.cf, proxy:mysql:/etc/postfix/mysql-virtual_alias_maps.cf, proxy:mysql:/etc/postfix/mysql-virtual_email2email.cf
- virtual_mailbox_domains = proxy:mysql:/etc/postfix/mysql-virtual_domains.cf
- virtual_mailbox_maps = proxy:mysql:/etc/postfix/mysql-virtual_mailboxes.cf
+ virtual_alias_maps = proxy:mysql:/etc/postfix/mysql-virtual_forwardings.cf, proxy:mysql:/etc/postfix/mysql-virtual_alias_maps.cf, proxy:mysql:/etc/postfix/mysql-virtual_email2email.cf, hash:/etc/sympa/virtual.sympa
+ virtual_mailbox_domains = proxy:mysql:/etc/postfix/mysql-virtual_domains.cf, hash:/etc/sympa/transport.sympa
+ virtual_mailbox_maps = proxy:mysql:/etc/postfix/mysql-virtual_mailboxes.cf, hash:/etc/sympa/transport.sympa, hash:/etc/sympa/sympa_transport, hash:/etc/sympa/virtual.sympa
- transport_maps = hash:/var/lib/mailman/data/transport-mailman, proxy:mysql:/etc/postfix/mysql-virtual_transports.cf
---
+ transport_maps = proxy:mysql:/etc/postfix/mysql-virtual_transports.cf, hash:/etc/sympa/transport.sympa, hash:/etc/sympa/sympa_transport

Attention : cette modification sera a faire à chaque mise à jours d’ISPconfig si vous choisissiez de reconfigurez les services.

Si vous voulez que cette modification soit « incluse » dans ISPconfig, même après mise à jour il vous fait récupérer le fichier du répertoire d’installation qui correspond à votre distribution (chez moi Debian) : ispconfig3/install/tpl/debian_postfix.conf.master et le mettre dans /usr/local/ispconfig/server/conf-custom/install/ sur votre serveur et d’appliquer les mêmes changements que précédemment cité dans le main.cf.

Ajouter les domaines

Contrairement à ce qui est dans la documentation : https://sympa-community.github.io/manual/install/configure-mail-server-postfix.html#virtual-domain-setting dans « Adding new domain »

Si vous ajouter dans le fichier transport.sympa la ligne

mail.example.org                error:User unknown in recipient table

SI ce domaine contient des boîtes e-mails dans ISPconfig, celles-ci ne fonctionneront plus. Il est donc préférable, dans notre cas de ne pas ajouter cette ligne (sauf si ce le nom de domaine est uniquement fait pour les mailings listes)

Un petit script script bash qui liste les domaines présent dans mailman et qui crée les configurations pour Sympa :

cat /var/lib/mailman/data/virtual-mailman | egrep -v "^$|^#|mailman" | cut -d@ -f2 | cut -d" " -f1 | sort | uniq > /tmp/mailman_domaine_liste
SYSCONFDIR=/etc/sympa
EXPLDIR=/var/lib/sympa/list_data
while read -r line;
do
    echo $line
    mkdir -m 755 $SYSCONFDIR/$line
    touch $SYSCONFDIR/$line/robot.conf
    chown -R sympa:sympa $SYSCONFDIR/$line
    mkdir -m 750 $EXPLDIR/$line
    chown sympa:sympa $EXPLDIR/$line
    echo "http_host  lists.$line
listmaster adresse-email-admin@retzo.net
create_list  listmaster
wwsympa_url     http://lists.$line/sympa" > $SYSCONFDIR/$line/robot.conf
    echo "sympa@$line          sympa:sympa@$line
listmaster@$line     sympa:listmaster@$line
bounce@$line         sympabounce:sympa@$line
abuse-feedback-report@$line  sympabounce:sympa@$line" >>  $SYSCONFDIR/transport.sympa
    echo "sympa-request@$line  postmaster@retzo.net
sympa-owner@$line    postmaster@retzo.net" >>  $SYSCONFDIR/virtual.sympa
done < /tmp/mailman_domaine_liste
postmap hash:$SYSCONFDIR/transport.sympa
postmap hash:$SYSCONFDIR/virtual.sympa

Migration avec mailman2sympa

Il existe un script « mailman2sympa » : https://www.sympa.org/contribs/migration_and_archives/index#mailman2sympa après usage j’ai contribué à son amélioration (débugge) sur Github : https://github.com/LAKostis/mailman2sympa/pulls?q=is%3Apr+author%3Akepon85 le mainteneur du dépôt git n’est pas l’auteur du script : https://github.com/LAKostis/mailman2sympa/commit/f628cd2b968b2e1959f0e631e895b189e8110f1d

Quelques dépendances non satisfaite chez moi :

apt install jq libjson-perl procmail

Téléchargement du script :

cd ~
git clone https://github.com/LAKostis/mailman2sympa.git
cd mailman2sympa
mv conf/mailman2sympa.conf.debian conf/mailman2sympa.conf

Modifier le fichier conf/mailman2sympa.conf

- DOMAIN=''
+ DOMAIN="retzo.net"
- PASSWORDDB=""
+ PASSWORDDB="zXne&375"
- DEFAULT_OWNER=""
+ DEFAULT_OWNER="adresse-email-admin@retzo.net"

Puis lancer le script de migration :

rm -fr /tmp/mailman ; bash mailman2sympa.sh

Si, comme moi vous avez plusieurs domaine il vous faut recommencer en éditant conf/mailman2sympa.conf :

- DOMAIN="retzo.net
+ DOMAIN="autredomaine.net

Et relancer le script mailman2sympa.sh, boucler tant que vous avez des domaines à importer…

A propos des archives, à la fin, connectez vous http://lists.retzo.net/sympa/serveradmin/archives (utiliser « première connexion » la première fois) et lancer une reconstitution des archives

Enfin re-générer le fichier sympa_transport précisé dans la variable sendmail_aliases du fichier sympa.conf

root@srvmail:~# /usr/lib/sympa/bin/sympa.pl --make_alias_file
Sympa aliases file /var/spool/sympa/tmp/sympa_aliases.179676 was made.  You probably need to install it in your SMTP engine.
root@srvmail:~# cat  /var/spool/sympa/tmp/sympa_aliases.179676 > /etc/sympa/sympa_transport
root@srvmail:~# postmap /etc/sympa/sympa_transport

Désactiver mailman

Avant de le désinstaller on peut passer par une période de transition en désactivant l’interface par exemple, dans le fichier /etc/mailman/apache.conf

-ScriptAlias /cgi-bin/mailman/ /usr/lib/cgi-bin/mailman/
+RedirectPermanent /cgi-bin/mailman/ /sympa/

DKIM / DMARC

Pour sympa il y a pas mal de configuration DMARc/DKIM : https://www.sympa.org/doc/formation/sympa_avance

Pour que ça fonctionne avec ISPconfig il faut ajouter l’utilisateur « sympa » au groupe « amavis »

usermod -a -G amavis sympa

Ensuite dans les fichiers « robot.conf » (/etc/sympa/DOMAIN/robot.conf) il faut ajouter en fin de fichier :

dkim_feature on
dkim_private_key_path	/var/lib/amavis/dkim/retzo.net.private
dkim_signature_apply_on any
dkim_signer_domain	retzo.net
dkim_selector	default
dmarc_protection_mode dmarc_reject

Redirection de la page du panel ISPconfig

ISPconfig ne supoprte pas Sympa mais Mailman, pour éviter que des utilisateurs crée des listes mailman (et donc génère des erreurs) je redirige la page « Mailing list » du panel vers la documentation. Pour ça modifier la page /usr/local/ispconfig/interface/web/mail/templates/mail_mailinglist_list.htm

+ <script type="text/javascript">
+ window.location.href = "https://lists.retzo.net/";
+ </script>
+ 
+ <p>Cette page du panel n'est plus à utiliser, vous allez être rediriger vers la page de Sympa : <a href="https://lists.retzo.net/">https://lists.retzo.net/</a></p>
+ 
+ <!--
73c80
-     
---
+ -->

Script API Ispconfig : changement d’IP dans toutes les zones DNS

Je m’occupe d’un service d’hébergement destiné aux actions politiques / citoyennes / artistiques… Ce service va rejoindre physiquement des voisins/copains eux aussi CHATONS : https://retzien.fr/. Nous allons mutualiser les serveurs et le temps de cerveau alloué au tâches administrative qui incombe à la gestion de ce type de service.

Pour préparer la migration de serveur j’ai fais un petit script qui se connecte à l’API d’ISPconfig et qui change tout les enregistrements DNS A ayant l’IP « X » par l’IP « Y » dans toutes les zones DNS du serveur. Ce script peut aussi s’avérer très utile en cas de changement de box internet Il se lance comme ceci :

php dnsChange.php -o=IP_ORIGINALE -n=NOUVELLE_IP

Le voici

<?php
/* 
 * Script de modification des enregistrements DNS A en cas de changement d'IP serveur
 * 
 * Exemple de lancement : 
 * 		php dnsChange.php -o=IP_ORIGINAL -n=NOUVELLE_IP
 * 
 * Sous licence Beerware
 * Par David Mercereau : http://david.mercereau.info
 */

// Configuration de la connexion ISPconfig
$CONFIG['remoteUser'] = 'UTILISATEUR DISTANT API ISPCONFIG';
$CONFIG['remotePassword'] = 'MOT DE PASSE DE L'UTILISATEUR DISTANT API ISPCONFIG';
$CONFIG['remoteSoapLocation'] = 'https://localhost:8080/remote/index.php';
$CONFIG['remoteSoapUri'] = 'https://localhost:8080/remote/';


// Test arguments
$options = getopt('o:n:');
if (count($options) < 2) {
	exit("Certains arguments sont manquants. -o ANCIENNEIP -n NOUVELLEIP .\n");
}
if (!filter_var($options['o'], FILTER_VALIDATE_IP)) {
        exit("L'origin n'est pas une IP valide.\n");
}
if (!filter_var($options['n'], FILTER_VALIDATE_IP)) {
        exit("La nouvelle IP n'est pas une IP valide.\n");
}

// Connexion à ISPconfig
$client = new SoapClient(null, array('location' => $CONFIG['remoteSoapLocation'],
	'uri'      => $CONFIG['remoteSoapUri'],
	'stream_context'=> stream_context_create(array('ssl'=> array('verify_peer'=>false,'verify_peer_name'=>false))),
	'trace' => 1));

// Login
if($session_id = $client->login($CONFIG['remoteUser'], $CONFIG['remotePassword'])) {
	echo "Login Ok. Session ID:".$session_id."\n\n";
}

echo "############################################################################################################################\n";
echo "Recherche de l'IP ".$options['o']." dans tout les enregistrements A des zones DNS du serveur pour la remplacer par ".$options['n']."\n";
echo "############################################################################################################################\n\n";

try {

	$dns_a_gets = $client->dns_a_get($session_id, -1);
        $nb_dns_a_get=0;
	foreach ($dns_a_gets as $dns_a_get) {
                if ($dns_a_get['type'] == 'A' && $dns_a_get['data'] == $options['o']) {
                        $nb_dns_a_get++;
                        $dns_zone_get = $client->dns_zone_get($session_id, $dns_a_get['zone']);
                        echo "Ip trouvé dans la zone ".$dns_zone_get['origin']." avec l'enregistrement ".$dns_a_get['name'].".".$dns_zone_get['origin'].". Voulez-vous la remplacer ? (Y/n) \n";
                        $handle = fopen ("php://stdin","r");
                        $line = fgets($handle);
                        if(trim($line) == 'yes' || trim($line) == 'y' || trim($line) == 'Y' || trim($line) == 'Yes'){
                                $dns_record = $client->dns_a_get($session_id, $dns_a_get['id']);
                                //print_r($dns_record);
                                $dns_record['data']=$options['n'];
                                //print_r($dns_record);
                                $affected_rows = $client->dns_a_update($session_id, $dns_a_get['sys_userid'], $dns_a_get['id'], $dns_record);
                                echo "Le changement à bien été opéré sur ".$affected_rows." enregistrement\n";
                        } else {
                                echo "Aucun changement effectué sur ".$dns_a_get['name'].".".$dns_zone_get['origin']."\n";
                        }
                        fclose($handle);
                }
        }

        if ($nb_dns_a_get == 0) {
                echo "Aucun enregistrement A avec l'IP  ".$options['o']."  n'a été trouvé. \n";
        }
	if($client->logout($session_id)) {
		echo "\nLogged out\n";
	}


} catch (SoapFault $e) {
	echo $client->__getLastResponse();
	die('SOAP Error: '.$e->getMessage()."\n");
}

?>

Script API Ispconfig création utilisateur

Je m’occupe d’un service d’hébergement destiné aux actions politiques / citoyennes / artistiques… Le serveur était plein de chez plein, ça tournait sans que je m’en occupe trop… J’ai décroché de ces geekeries pour d’autres occupations… Mais voilà Debian 7 était en fin de support, j’ai migré, fais du ménage… du coup il y a de nouveau de la place sur le serveur donc je ré-ouvre les portes.

De ce fait j’ai automatisé une tâche qui me prenait du temps jadis : la création des comptes (même si avec Ispconfig, c’est quand même clique clique). J’ai donc accouché d’un script PHP qui utilise l’API d’ISPconfig, on y passe en paramètre :

  • Nom d’utilisateur
  • Email de l’utilisateur
  • Sous domaine souhaité (ici : cequejesouhait.zici.fr)

Et il nous génère :

  • Création de l’utilisateur « client » pour l’accès au panel Ispconfig
  • Création du site web
    • Création d’une base de donnée et de son utilisateur
    • Création d’un compte FTP et SFTP pour l’accès au site web
  • Création d’un transfère mail (ici cequejesouhait@zici.fr vers l’email de l’utilisateur)

Le script est téléchargeable ici.

[ispconfig] Managesieve (dovecot) & Horde

sieve.infoDes dires de Wikipedia : « Sieve est un langage de filtrage du courrier électronique. Il est normalisé dans le RFC 5228. Sieve permet de filtrer sur les en-têtes d’un message qui suit le format du RFC 5322, c’est-à-dire un message Internet typique.  »

Sieve c’est très pratique car le filtrage du courrier est effectué au niveau du serveur dès la réception de l’email. Ce qui est presque indispensable quand on utilise plusieurs clients de messagerie (web &/ou desktop). Je vais donc utiliser Managesieve (qui est la partie serveur du protocole) pour Dovecot (projet Pigeonhole).

Actuellement le panel ISPconfig me permet d’éditer les filtres Sieve mais n’utilise pas Managesieve. ISPconfig stock en base (table mail_user_filter) et écrase le fichier à chaque modification.

Je ne souhaite plus passer par ISPconfig pour modifier mes filtres, mais directement par Horde (via Ingo) ou Roundcube (plugin) ou encore par thunderbird (plugin) selon mes besoins.

Installation de Managesieve

Rien de plus simple :

aptitude install dovecot-managesieved

Modifier le fichier /etc/dovecot/dovecot.conf :

< protocols = imap
> protocols = imap sieve

Puis redémarrer le service, le port 4190 doit ensuite être à l’écoute :

$ service dovecot restart
$ netstat -pnat | grep 4190
tcp        0      0 0.0.0.0:4190            0.0.0.0:*               LISTEN      11111/dovecot

Horde (ingo) & Sieve

Il vous suffit de modifier le fichier ingo/config/backends.php de votre instance horde de la façon suivante :

[...]
/* IMAP Example */
$backends['imap'] = array(
    // ENABLED by default
<    'disabled' => false,
>    'disabled' => true,
    'transport' => array(
        Ingo::RULE_ALL => array(
            'driver' => 'null',
            'params' => array(),
        ),
    ),
[...]
$backends['sieve'] = array(
    // Disabled by default
<    'disabled' => true,
>    'disabled' => false,
    'transport' => array(
        Ingo::RULE_ALL => array(
            'driver' => 'timsieved',
            'params' => array(
                // Hostname of the timsieved server
                'hostspec' => 'localhost',
                // Login type of the server
                'logintype' => 'PLAIN',
                // Enable/disable TLS encryption
                'usetls' => false,
                // Port number of the timsieved server
                'port' => 4190,
                // Name of the sieve script
<                'scriptname' => 'ingo',
>                'scriptname' => 'filtres',
                // Enable debugging. The sieve protocol communication is logged
[...]

Ne faites (peut être) pas ça chez vous

En effet ça ne s’avère pas être forcément la meilleure des solutions :

  • Il n’est apparemment pas possible d’importer des scripts existants.
  • Plus embêtant il s’avère que Horde fonctionne presque de la même façon qu’ISPconfig. A savoir qu’il stock en base les filtres et écrase le script sieve (via managesieve quand même) Ce qui me condamne à n’utilise qu’une interface (horde) pour modifier mes filtres :’-(

Bon je m’en contente, il est toujours plus agréable de modifier ses filtres via son webmail (horde) que via le panel ISPconfig.

[ispconfig] Remplacer Amavis/Spamassassin par Dspam

dspam-logo-textAjouter des services décentralisés « à la maison » c’est le bien mais à force d’empiler des briques… ça déborde. Et là j’étais à un stade ou la SWAP était un chouilla trop utilisée.

J’avais déjà désactivé ClamAv (anti-virus) pour économiser de la mémoire vive mais ça ne suffisait pas. Mon autre plus gros poste de dépense en RAM était Amavis/Spamassasin. Je me suis donc mis à chercher une alternative ; La plus légère et efficace semble être DSPAM.

Attention : Le fait de remplacer Amavis/Spamassasin va, de fait vous amputer de fonctionnalité administrable par le panel ISPconfig « Stratégie anti-spam », « liste blanche » car Ispconfig ne support pas (encore !?) DSPAM

Préparation

Étant donné que le serveur est déjà en prod j’ai modifié mon script de firewall (iptables) en spécifiant seulement mon adresse IP pour l’accès au SMTP (pour les tests) ça aura pour effet de faire patienter vos emails en file d’attente sur le serveur émetteur quoi que vous fassiez comme bêtise…

< iptables -A INPUT -p tcp --dport smtp -j ACCEPT
> iptables -A INPUT -p tcp --dport smtp -s VOTRE.IP.DE.MAISON -j ACCEPT

5 jours, c’est par défaut le temps d’attente maximal de la plupart des MTA. Vous pouvez donc théoriquement bricoler pendant 5 jours sans perdre d’email dans cet état…

Installation

Je suis sous Debian squeeze, les paquets Dsapm existe pour squeeze mais dans le backport (non activé pour ma part)

Installation des dépendances :

$ aptitude install libgd-gd2-perl libgd-graph-perl libgd-graph3d-perl libgd-text-perl dbconfig-common postfix-pcre

Ensuite on récupère les paquets sur le site de debian et ont les installent

$ dpkg -i libdspam7_3.10.1+dfsg-3~bpo60+1_amd64.deb
$ dpkg -i libdspam7-drv-mysql_3.10.1+dfsg-3~bpo60+1_amd64.deb
$ dpkg -i dspam_3.10.1+dfsg-3~bpo60+1_amd64.deb
$ dpkg -i dspam-webfrontend_3.10.1+dfsg-3~bpo60+1_all.deb

Note : dbconfig-common va vous demander ce qu’il faut pour créer la base de données.. »suivez le guide. »

Configuration

Postfix

Nous allons, dans postfix désactiver la partie Amavis et activer la partie Dspam /etc/postfix/main.cf :

58c58
< smtpd_client_restrictions = check_client_access mysql:/etc/postfix/mysql-virtual_client.cf
---
> smtpd_client_restrictions = check_client_access mysql:/etc/postfix/mysql-virtual_client.cf, check_client_access pcre:/etc/postfix/dspam_filter_access
71,72d70
< content_filter = amavis:[127.0.0.1]:10024
< receive_override_options = no_address_mappings
74a73,76
>
> dspam_destination_recipient_limit = 1

Même chose dans le fichier /etc/postfix/master.cf :

smtp      inet  n       -       -       -       -       smtpd
11a12
>    -o content_filter=dspam:
116,129c117,118
< 127.0.0.1:10025 inet n - - - - smtpd
<         -o content_filter=
<         -o local_recipient_maps=
<         -o relay_recipient_maps=
<         -o smtpd_restriction_classes=
<         -o smtpd_client_restrictions=
<         -o smtpd_helo_restrictions=
<         -o smtpd_sender_restrictions=
<         -o smtpd_recipient_restrictions=permit_mynetworks,reject
<         -o mynetworks=127.0.0.0/8
<         -o strict_rfc821_envelopes=yes
<         -o receive_override_options=no_unknown_recipient_checks,no_header_body_checks
<         -o smtpd_bind_address=127.0.0.1
< 
---
> dspam   unix    -       n       n       -       10      pipe
>         flags=Rhqu user=dspam argv=/usr/bin/dspam --deliver=innocent --user $user -i -f $sender -- $recipient

Dspam

Dans mon cas j’ai choisi de tout le temps délivrer les SPAM et de tagger le sujet. L’apprentissage se fera via l’interface web (dont nous verrons la configuration plus tard)

Activer le démarrage de Dspam /etc/default/dspam

< start=NO
---
> start=YES

La configuration de Dspam à largement été inspiré du howto d’UNIX garden :

29c29
< StorageDriver /usr/lib/dspam/libhash_drv.so
---
> StorageDriver /usr/lib/dspam/libmysql_drv.so
48c48
< TrustedDeliveryAgent "/usr/bin/procmail"
---
> TrustedDeliveryAgent "/usr/sbin/sendmail"
144c144
< Trust root
---
> #Trust root
146,149c146,149
< Trust www-data
< Trust mail
< Trust daemon
< Trust amavis
---
> #Trust www-data
> #Trust mail
> #Trust daemon
> #Trust amavis
151a152
> Trust postfix
297c298
< Preference "signatureLocation=message"	# { message | headers } -> default:message
---
> Preference "signatureLocation=headers"	# { message | headers } -> default:message
371a373,380
> MySQLServer     	127.0.0.1
> #MySQLPort
> MySQLUser               dspam
> MySQLPass               MOTDEPASSEDEMALADE
> MySQLDb                 dspam
> MySQLCompress           true
> MySQLUIDInSignature    on
> 
471c480
< LocalMX 127.0.0.1
---
> #LocalMX 127.0.0.1

Pour finir sur les tags j’ai dû faire la chose suivante :

$ mkdir /var/spool/dspam/txt/
$ echo ‘Scanned and tagged as SPAM by DSPAM’ > /var/spool/dspam/txt/msgtag.spam

Premier test

Redémarrage des services pour appliquer tous ces changements :

$ service amavis stop
$ service postfix restart
$ service dspam start

Pour tester vous pouvez en envoyer un message avec la commande telnet. Voici un petit script pratique pour automatiser le test :

#!/bin/bash
from="nimportequi@domain.fr"
to="david@domain.fr"
smtp="smtp.domain.fr"
(
    sleep 1
    echo "ehlo x"
    sleep 1
    echo "mail from:${from}"
    sleep 1
    echo "rcpt to:${to}"
    sleep 1
    echo "data"
    sleep 1
    echo "subject:Test message"
    sleep 1
    echo "from:${from}"
    sleep 1
    echo "to:${to}"
    sleep 1
    echo " "
    echo "Coucou."
    sleep 1
    echo "."
    sleep 1
    echo "QUIT"
) | telnet ${smtp} 25

Dans les entêtes du message vous devriez avoir du X-DSPAM comme ceci :

X-DSPAM-Result: Innocent
X-DSPAM-Processed: Thu Jul 1 00:03:19 2050
X-DSPAM-Confidence: 0.9751
X-DSPAM-Probability: 0.0000
X-DSPAM-Signature: 1,51e7a147199049585619662

Si tout fonctionne on dégage amavis (dit « le gros amavis ») du démarrage :

update-rc.d dspam defaults
update-rc.d amavis remove

Sinon fouiller vos logs (/var/log/mail.log /var/log/syslog…)

Interface web

L’interface web est en CGI et nous allons utiliser apache & suexec (qui est déjà embarqué avec ISPconfig) pour le faire tourner

Voici la configuration du virtualhost (sites-available/dspam)

<IfModule mod_suexec.c>
    <VirtualHost *:80>
        DocumentRoot /var/www/dspam

        # Problème css, image : 
        Alias /usr/share/dspam /usr/share/dspam

        ServerName dspam.domain.fr
        ServerAdmin dspam@domain.fr

        SuexecUserGroup dspam dspam

        <Directory /var/www/dspam>
            Options ExecCGI
            Options -Indexes
            Addhandler cgi-script .cgi
            DirectoryIndex dspam.cgi
        </Directory>

        <Directory />
            Options FollowSymLinks
            AllowOverride None
            Order allow,deny
            allow from all
            AuthType Basic
            AuthName "Restricted DSPAM user"
            Auth_MYSQLhost localhost
            Auth_MYSQLusername ispconfig
            Auth_MYSQLpassword MOTDEPASSESUPERCHAUD
            Auth_MYSQLdatabase dbispconfig
            Auth_MYSQLpwd_table mail_user
            Auth_MYSQLuid_field login
            Auth_MYSQLpwd_field password
        </Directory>
    </VirtualHost>
</IfModule>

On active le virtualhost :

$ a2ensite dspam
$ service apache2 graceful

On ajoute le compte admin de l’interface :

$ echo "david" > /etc/dspam/admins

Vous devriez maintenant pouvoir vous rendre sur l’interface :

  • http://dspam.domain.fr/ (interface utilisateur)
  • http://dspam.domain.fr/admin.cgi (interface d’administration)

Conclusion

L’objectif premier était d’économiser de la mémoire vive, c’est chose faite ! la preuve en image :

memory-day

Je suis aussi très satisfait de l’apprentissage de DSPAM. Au début ça peut faire peur parce qu’il laisse vraiment tout passer, mais l’apprentissage est rapide et significatif :

Les premiers jours d'utilisation de DSPAM
Les premiers jours d’utilisation de DSPAM

Ressources

Les sites ressources que j’ai utilisées :

ISPconfig – service email : DKIM & Amavis

By Nemo (Public Domain CC0)

Edit 13/04/2015 : Ajout d’@mynetworks pour que les réseaux connus soient marqués DKMI.

DKIM (DomainKeys Identified Mail)  est une norme d’authentification par clef publique/privé du nom de domaine de l’expéditeur d’un courrier électronique. Une partie de la signature est comprise dans l’entête du message & une autre dans un enregistrement DNS TXT dédié.

Elle constitue une protection efficace contre le spam et l’hameçonnage. Elle permet aussi surtout (et c’est en ça qu’elle nous intéresse le plus) d’éviter de se faire considérer comme SPAM.

Je parle d’ISPconfig dans mon titre car c’est ce qui motorise mon serveur en ce moment, mais je pense que la procédure fonctionne avec Amavis en règle générale.

Mise en place

Il faut déjà préparer le terrain :

srv:~$ mkdir /etc/amavis/pki
srv:~$ ln -s /etc/amavis/pki /var/lib/amavis/pki

Ensuite on génère la clef :

srv:~$ amavisd-new genrsa /var/lib/amavis/pki/dkmi-mercereau.info-key.pem

Puis il faut créer le fichier /etc/amavis/conf.d/99-dkmi avec la configuration suivante :

$enable_dkim_verification = 1;
$enable_dkim_signing = 1;
dkim_key('mercereau.info', 'default', '/var/lib/amavis/pki/dkmi-mercereau.info-key.pem');
@dkim_signature_options_bysender_maps = (
    { '.' => { ttl => 21*24*3600, c => 'relaxed/simple' } } 
);
@mynetworks = qw(0.0.0.0/8 
                127.0.0.0/8     
                123.123.123.123/32  # IP maison 1
                456.456.456.456/32  # IP boulot
);

Ensuite il faut redémarrer le service Amavis :

srv:~$ service amavis restart

Ensuite récupérer la clef DKIM qu’il va falloir insérer dans votre enregistrement DNS avec la commande suivante : :

srv:~$ amavisd-new showkeys
; key#2, domain mercereau.info, /var/lib/amavis/pki/dkmi-mercereau.info-key.pem
default._domainkey.mercereau.info.    3600 TXT (
  "v=DKIM1; p="
  "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDvF925xN7NeMekLrSMSTtZaSx6"
  "9u6njS+mG99DcM1kqj+9RW79KsdKxNXlMull3Mcp6KwKHV7eb8bSvx2TeJ0YUxuA"
  "hZK0dc971R+F6Xmq4fYW02PeuF1fiyl2oL/rxojGT20anxEc9hzFR8jaCFv4CXhh"
  "1efU2BxngTD/onYQVQIDAQAB")

Il faut donc créer un enregistrement DNS comme tel :

default._domainkey 18000 TXT « v=DKIM1; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKB
[..]
QVQIDAQAB »

Vérification

Après propagation DNS (que vous pouvez vérifier avec l’outil Dig), vous pouvez lancer la commande :

srv:~$ amavisd-new testkeys
TESTING#2: default._domainkey.mercereau.info => pass

Pour être vraiment certain que votre message est signé vous pouvez vous envoyer un email sur une adresse externe et vérifier les entêtes. Sinon vous pouvez envoyer un email à : check-auth [arobase] verifier.port25.com et vous reverser un rapport complet sur « l’état de votre port 25 »

==========================================================
Summary of Results
==========================================================
SPF check: pass
DomainKeys check: neutral
DKIM check: pass
Sender-ID check: pass
SpamAssassin check: ham

[…]
———————————————————-
SpamAssassin check details:
———————————————————-
SpamAssassin v3.3.1 (2010-03-16)

Result: ham (-2.0 points, 5.0 required)

La partie importante pour nous est donc le DKIM check qui doit être à « pass ». D’autre part je ne peux que vous conseiller d’ajouter aussi un enregistrement SPF.

Le rapport m’indique que j’ai un SpamAssassin score de -2 ce qui est très bon car la configuration par défaut de SpamAssassin annonce les messages en SPAM lorsqu’il dépasse un score de +5.

Ressources :

En continuant à utiliser le site, vous acceptez l’utilisation des cookies (au chocolat) Plus d’informations

Les cookies sont utilisés à des fin de statistique de visite du blog sur une plateforme indépendante que j'héberge moi même. Les statistiques sot faites avec un logiciel libre. Aucune information n'est redistribué à google ou autre. Je suis seul autorisé à lire ces informations

Fermer