Afin de réaliser des maintenances sur mon service web (ou les services attenant tel que Mysql) j’ai mis en place un petit mot d’excuse qui dit en substance : « maintenance en cours, merci de repasser plus tard ». C’est mieux que « La connexion a échoué » ou « Can’t Connect to MySQL Server on nian nian nian » non ?
La configuration de prod :
Apache sur le port 80
La configuration de maintenance :
Apache sur le port 80 (le même)
Lighttpd sur le port 81
Iptables redirige le trafic arrivant sur le port 80 vers le port 81 en PREROUTING sauf pour mon IP (ça permet donc de bricoler)
Installation de lighttpd
Apeuté, et ayé :
aptitude -y install lighttpd
update-rc.d lighttpd remove
mkdir /var/www/maintenance
echo "Serveur en maintenance" > /var/www/maintenance/index.html # Vous pouvez faire une belle page html c'est mieux !
Il est certainement possible de faire plus propre sur ce point. Actuellement je gère le message dans le index.html que je met dans le error404. Des redirection 302 quelque soit l’URL serait à envisager.
Maintenance On/Off
Pour se mettre en mode maintenance :
# Démarrage du serveur d'excuse
service lighttpd start
# Redirection du port 80 vers 81 sauf pour mon IP
iptables -A INPUT -p tcp --dport 81 -j ACCEPT
iptables -t nat -A PREROUTING \! -s ${IPMAISONDEMOI} -p tcp --dport 80 -j DNAT --to-destination ${IPDUSERVEUR}:81
iptables -t nat -A POSTROUTING -j MASQUERADE
Et pour désactiver le mode maintenance :
# Si vous n'avez pas d'autres règles (c'est mal) :
iptables -F
iptables -t nat -F
# Sinon redémarrer votre service iptables
# Lighttpd n'est plus utile
service lighttpd stop
Des 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 :
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.
EDIT 24/02/2015 : ‘Il n’est plus nécessaire d’utiliser cloudfiles comme backend pour duplicity. À la place, il faut utiliser un backend spécial hubic intégré à duplicity récemment »voir le commentaire de blankoworld
EDIT 02/2015 : suppression du « DeprecationWarning » dans le log.
Mon ADSL est depuis peut chez OVH. De ce fait je bénéficie d’un compte hubiC avec un espace de stockage d’1To. Quelle aubaine pour des sauvegardes ! Mais bon donner mes mails, mes sites, mes documents administratifs à un tiers… bof bof. Il faudrait un minimum de chiffrage !
python-cloudfiles-hubic est nécessaire car duplicity n’intègre pas nativement le service cloud « HubiC » pour une sombre histoire de protocole d’authentification non standard de la part d’OVH (détail par l’auteur)
aptitude install python-setuptools git
cd /usr/src
git clone https://github.com/Gu1/python-cloudfiles-hubic.git
cd python-cloudfiles-hubic
python setup.py install
Utilisation
Dans vos paramètre sur hubic.com dans votre menu « Vos application » il va falloir ajouter une application :
Nom : cequevousvoulez
Domaine de redirection : http://localhost/
Quand l’application est créer récupérer le « client id » ainsi que le « client secret » dans l’interface
Quelques petits tests pour la prise en main :
# Désactiver le bash_history (c'est pénible avec les mots de passes)
unset HISTFILE
# Les variables
export CLOUDFILES_USERNAME=toto@toujours.lui
export CLOUDFILES_APIKEY=je.vais.pas.vous.donner.le.mot.de.passe.de.toto
# CLOUDFILES_AUTHURL="hubic|client id|client secret|http://localhost/"
export CLOUDFILES_AUTHURL="hubic|api_hubic_XXXX|YYYYY|http://localhost/"
# Sauvegarde
duplicity /root cf+http://default
# Observer l'état
duplicity collection-status cf+http://default
# Liste les fichiers distants
duplicity list-current-files cf+http://default
# Test la restauration d'un fichier
duplicity --file-to-restore .bash_alias cf+http://default /tmp/bash_alias_recup
Rendez-vous ensuite dans votre interface hubiC. Et là normalement il y a plein de fichier duplicity-BLABLA-blabla.bla ! On supprime tout ! (c’était juste pour les tests)
Il ne semble pas possible d’écrire dans un sous répertoire. Mais, comme je l’ai signalé dans mon commentaire, il semble possible d’écrire dans un autre « container » sur hubiC (autre que default). Il ne sera visible qu’après modification de l’URL. Exemple si vous avez écrit dans le conteneur backup rendez vous sur l’URL : https://hubic.com/home/browser/#backup
Le script
Voici mon script :
#!/bin/bash
###################################
## Backup sur HubiC avec duplicity
# Script sous licence BEERWARE
# Version 0.4.1 02/2015
###################################
set -eu
##### Paramètres
# Utilisateur Hubic
HUBICUSER="leuserdevotrehubic"
# Mot de passe HubiC
HUBICPASSWORD="lemotdepassedevotrehubic"
# Application client id Hubic
HUBICAPPID="api_hubic_XXXXX"
# Application client secret Hubic
HUBICAPPSECRET="YYYYYY"
# Application domaine de redirection Hubic
HUBICAPPURLREDIRECT="http://localhost/"
# Liste à sauvegarder (voir le man duplicity avec le filelist)
DUPLICITYFILELIST="/etc/backup-`hostname`.filelist"
# Passphrase pour le chiffrement
PASSPHRASE="VotrePassPhraseDeOufQueYaQueVousEtVousSeulQuiSavez:-p"
# Fréquence des sauvegardes complètes
FULLIFOLDERTHAN="1W"
# Rétention des sauvegardes
RETENTION="2M"
# Log d'erreur
LOGERROR="/var/tmp/backup-hubic-error.log"
# Bin de duplicity
DUPLICITY_BIN="/usr/bin/duplicity"
# Email pour les erreurs (0 pour désactiver)
EMAIL="toto@mondomaine.com"
# Envoyer un rapport par email sur l'état des backup
RAPPORT=1
# Log d'erreur
exec 2> ${LOGERROR}
##### Début du script
function cleanup {
echo "exit..."
unset CLOUDFILES_USERNAME
unset CLOUDFILES_APIKEY
unset PASSPHRASE
grep -v "has been deprecated" ${LOGERROR} > ${LOGERROR}.tmp
mv ${LOGERROR}.tmp ${LOGERROR}
if [ "`stat --format %s ${LOGERROR}`" != "0" ] && [ "$EMAIL" != "0" ] ; then
cat ${LOGERROR} | mail -s "$0 - Error" ${EMAIL}
fi
}
trap cleanup EXIT
# Gentil avec le système
ionice -c3 -p$$ &>/dev/null
renice -n 19 -p $$ &>/dev/null
if ! [ -f ${DUPLICITYFILELIST} ] ; then
echo "Aucun fichier filelist : ${DUPLICITYFILELIST}"
exit 1
fi
export CLOUDFILES_USERNAME=${HUBICUSER}
export CLOUDFILES_APIKEY=${HUBICPASSWORD}
export CLOUDFILES_AUTHURL="hubic|${HUBICAPPID}|${HUBICAPPSECRET}|${HUBICAPPURLREDIRECT}"
export PASSPHRASE
# Backup
${DUPLICITY_BIN} --full-if-older-than ${FULLIFOLDERTHAN} / cf+http://default --include-globbing-filelist ${DUPLICITYFILELIST} --exclude '**'
# Suppression des vieux backups
${DUPLICITY_BIN} remove-older-than ${RETENTION} cf+http://default --force
# Rapport sur le backup
if [ "$RAPPORT" != "0" ] && [ "$EMAIL" != "0" ] ; then
${DUPLICITY_BIN} collection-status cf+http://default | mail -s "$0 - collection-status" ${EMAIL}
fi
unset CLOUDFILES_USERNAME
unset CLOUDFILES_APIKEY
unset PASSPHRASE
exit 0
A noter que mes bases de données sont dumpées à plat de façon indépendante du script de backup distant (par mysql_dump.sh)
Attention : les fichiers et répertoires à exclure doivent apparaître avant l’inclusion d’un répertoire parent. En effet, duplicity s’arrête à la première règle qui matche un chemin donné pour déterminer s’il doit l’inclure ou l’exclure. (sources)
WordPress étant très populaire il est (malheureusement) de fait très attaqué.. La principale (hors SPAM sur les commentaires) est faite par brute-force sur la page wp-login.php. Je l’avais déjà remarqué, mais j’ai récement eu des problèmes d’indisponibilités suite à plusieurs attaques venant de multiple adresse IP (l’attaque passant donc de brute-force à DDOS) J’ai donc dû réagir et pour ce faire j’ai configuré fail2ban pour bloquer les IP’s faisant plus de 6 tentatives de connexions sur tous les sites wordpress du serveur.
Configuration de fail2ban
Note : mon installation de fail2ban est existante et fonctionne déjà pour le FTP & le SSH
Créer le fichier /etc/fail2ban/jail.d/apache-wp-login.conf :
Pour finir : un restart du service fail2ban & vous n’avez plus qu’à tester en faisant plus de 6 tentatives de mot de passe sur la page votreblog/wp-admin/
$ service fail2ban restart
$ tail -f /var/log/fail2ban.log
2013-09-05 16:33:39,559 fail2ban.actions: WARNING [apache-wp-login] Ban XX.XX.XX.XX
Pour information, le lendemain 47 IP ont été bloquées grâce à ce système…
$ fail2ban-client status apache-wp-login Status for the jail: apache-wp-login |- Filter | |- Currently failed: 7 | |- Total failed: 59966 | `- File list: /var/log/apache2/mercereau.info/access.log `- Actions |- Currently banned: 0 |- Total banned: 4128 `- Banned IP list:
Si comme moi vous gérez un hébergement mutualiser vous pouvez ajouter un script qui toutes les nuits scan votre /var/www à la recherche de wp-login.php et ajout le log dans fail2ban. Ce script est adapté à l’architecture d’ISPconfig :
#!/bin/bash
# Détection des wordpress sur le serveur
# Ajout des logs du site en question dans fail2ban
# Fonctionne avec l'arbo du panel ISPconfig3
# A mettre en tâche planifié
fail2banConf='/etc/fail2ban/jail.d/apache-wp-login.conf'
echo -n "[apache-wp-login]
enabled = true
port = http,https
filter = apache-wp-login
maxretry = 8
logpath = " > $fail2banConf
find /var/www/clients -name wp-login.php | while IFS=$'\n' read f ; do
clientId=`echo $f | cut -d"/" -f5`
siteId=`echo $f | cut -d"/" -f6`
# Test si le lien symbolique n'est pas mort
readlink=`readlink /var/www/clients/$clientId/$siteId/log/access.log`
ls /var/www/clients/$clientId/$siteId/log/${readlink} &>/dev/null
if ! (($?)) ; then
echo " /var/www/clients/$clientId/$siteId/log/access.log " >> $fail2banConf
fi
done
/etc/init.d/fail2ban restart >/dev/null
Vous pouvez aussi faire la même chose pour bloquer wp-xmlrpc (qui est très sollicitée en brute force. Dans le script d’automatisation je télécharge les IP utilisé par JetPack (non pas que j’aime ce plugin mais certain de mes utilisateurs l’utilise et c’est bloquant pour xmlrpc…
#!/bin/bash
# Détection des wordpress sur le serveur
# Ajout des logs du site en question dans fail2ban
# Fonctionne avec l'arbo du panel ISPconfig3
# A mettre en tâche planifié
# https://wpchannel.com/wordpress/tutoriels-wordpress/lutter-attaques-ddos-xml-rpc-php-fail2ban/
cd /tmp
wget https://jetpack.com/ips-v4.txt
if ! (($?)) ; then
ips=`sed ':a;N;$!ba;s/\n/ /g' /tmp/ips-v4.txt`
else
ips=''
fi
fail2banConf='/etc/fail2ban/jail.d/apache-wp-xmlrpc.conf'
echo -n "[apache-wp-xmlrpc]
enabled = true
filter = apache-wp-xmlrpc
bantime = 86400
maxretry = 1
port = http,https
ignoreip = 127.0.0.1/8 ns1.wordpress.com ns2.wordpress.com ns3.wordpress.com ns4.wordpress.com jetpack.wordpress.com $ips
logpath = " > $fail2banConf
find /var/www/clients -name wp-login.php | while IFS=$'\n' read f ; do
clientId=`echo $f | cut -d"/" -f5`
siteId=`echo $f | cut -d"/" -f6`
# Test si le lien symbolique n'est pas mort
readlink=`readlink /var/www/clients/$clientId/$siteId/log/access.log`
ls /var/www/clients/$clientId/$siteId/log/${readlink} &>/dev/null
if ! (($?)) ; then
echo " /var/www/clients/$clientId/$siteId/log/access.log " >> $fail2banConf
fi
done
/etc/init.d/fail2ban restart >/dev/null
Et le fichier : /etc/fail2ban/filter.d/apache-wp-xmlrpc.conf
Modification de la configuration d’OpenDKIM (/etc/opendkim.conf) :
Socket inet:8891@localhost
LogWhy yes
MilterDebug 1
# Log to syslog
Syslog yes
# Required to use local socket with MTAs that access the socket as a non-
# privileged user (e.g. Postfix)
UMask 002
KeyTable /etc/dkim/KeyTable
SigningTable /etc/dkim/SigningTable
ExternalIgnoreList /etc/dkim/TrustedHosts
InternalHosts /etc/dkim/TrustedHosts
Il faut maintenant générer les clefs & ce script va nous y aider :
#!/bin/bash
# Script sous licence BEERWARE
SELECTOR="mail"
REPERTOIRE="/etc/dkim"
DOMAINE=$1
USERDKIM="opendkim"
GROUPDKIM="opendkim"
if ! [ -d "${REPERTOIRE}" ] ; then
echo "Le répertoire ${REPERTOIRE} n'existe pas."
exit 1
fi
if [ -z ${DOMAINE} ] ; then
echo "Vous devez avoir renseigner le domaine en argument du script."
exit 2
fi
if [ -d "${REPERTOIRE}/keys/${DOMAINE}" ] ; then
echo "Le répertoire ${REPERTOIRE}/keys/${DOMAINE} existe déjà... vous devez déjà avoir dû lancé le script."
exit 3
else
mkdir -p ${REPERTOIRE}/keys/${DOMAINE}
fi
opendkim-genkey -D ${REPERTOIRE}/keys/${DOMAINE} -r -d ${DOMAINE} -s ${SELECTOR}
chown ${USERDKIM}:${GROUPDKIM} ${REPERTOIRE}/keys/${DOMAINE}/${SELECTOR}.private
echo "${SELECTOR}._domainkey.${DOMAINE} ${DOMAINE}:${SELECTOR}:${REPERTOIRE}/keys/${DOMAINE}/${SELECTOR}.private" >> ${REPERTOIRE}/KeyTable
echo "${DOMAINE} ${SELECTOR}._domainkey.${DOMAINE}" >> ${REPERTOIRE}/SigningTable
echo "${DOMAINE}" >> ${REPERTOIRE}/TrustedHosts
if [ -f ${REPERTOIRE}/keys/${DOMAINE}/${SELECTOR}.txt ]; then
cat ${REPERTOIRE}/keys/${DOMAINE}/${SELECTOR}.txt
else
echo "Une erreur s'est produite !"
fi
Exemple d’utilisation du script :
$ ./addDkimKey.sh mercereau.info
mail._domainkey IN TXT "v=DKIM1; g=*; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDEOxRe2sVbsmDYbnB1pRWdx5U6FgZiwUKRl0gPFmsgPNA035P7gBLmhXrmALeJLZv0n7ARkStoIvl/ZNAbUep/YUgMynW5q2fsh4Pa/q82ocPKRKGLBYTxFDa+tyhG0oi5pzI6d37Ji9M40c5DgD/2QqTfyY5ywLqKG47+HuivJQIDAQAB" ; ----- DKIM mail for mercereau.info
Le script vous sort l’enregistrement DNS a ajouter pour terminer la configuration
On redémarre les services :
$ service opendkim restart
$ service postfix restart
Ajouter 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…
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)
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 :
L’objectif premier était d’économiser de la mémoire vive, c’est chose faite ! la preuve en image :
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 :
Horde c’est LE webmail/calendrier/note/tâche/signets que je trouve le plus a même de remplacer les services traditionnels cloudé (google & co)
Horde s’installe maintenant facilement grâce à Pear. C’est pratique à l’installation mais pas forcément pratique pour la maintenance (surtout en cas de mutualisation) Je vais expliquer ici comment l’installer de façon « standelone » (non dépendante)
Note : la configuration d’apache ne sera pas traitée ici, je fais pointer le DocumentRoot dans /var/www/horde
Commencer par créer un environnement pear pour votre instance horde :
Maintenant que nous avons notre environnement pear il ne reste plus qu’à l’utiliser :
/var/www/horde/pear/pear -c /var/www/horde/pear.conf channel-discover pear.horde.org
/var/www/horde/pear/pear -c /var/www/horde/pear.conf install horde/horde_role
/var/www/horde/pear/pear -c /var/www/horde/pear.conf run-scripts horde/horde_role
# Question : Filesystem location for the base Horde application :
# Répondre : /var/www/horde
/var/www/horde/pear/pear -c /var/www/horde/pear.conf install -a horde/webmail
Il faut ensuite éditer le /var/www/horde/.htaccess
Note : Attention ce fichier .htaccess sera écrasé à chaque mise à jour de Horde.
# Protection du pear.conf si celui-ci est accessible en http
<Files pear.conf>
order deny,allow
deny from all
</Files>
# Spécifie l'emplacement de pear
php_value include_path /var/www/horde/pear/php
SetEnv PHP_PEAR_SYSCONF_DIR /var/www/horde
Protéger aussi votre répertoire pear si celui-ci est accessible en http (/var/www/horde/pear/.htaccess) :
order deny,allow
deny from all
Ensuite, il vous faut configurer correctement votre service http et rendez-vous sur la page de horde. Personnellement, à ce stade, je n’ai configuré que la partie SQL. Il vous suffit de suivre les indications pour mettre à jour les configurations et les schémas de bases (c’est du clique clique je vous laisse vous en dépatouiller…)
J’ai modifié une préférence par défaut, c’est l’option qui dit d’utiliser la corbeille et non de marquer les messages tels que supprimés :
A l’expédition d’un message avec pièce jointe j’ai eu l’erreur « unable to open VFS file« , pour résoudre ce problème il faut modifier la configuration d’IMP :
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