NyroBlog
Banniere NyroBlog
Image de Loic 3d - ?
« mai 2010
lunmarmerjeuvensamdim
12
3456789
10111213141516
17181920212223
24252627282930
31

Reinvente the calendar

All of us has already figure out that: calculate dates through years is difficult. You have to worry about leap years, weeks of 7 days, months with different number of days, etc...

Starting from this observation, I started to search information about time notion, and more precisely in the measure that was done by humans.

In most of the worlds we're using the Gregorian calendar: established on 1582, it's using the SUN and the earth rotation around it to define the year and the day. Since this time the calendar included the 29th of February every 4 years to obtain a year with 365,25 days.

But the earth go round the Sun in 365,24219 days. Which means there is a tiny shift which is getting ride every millennium but not adding the 29th of February. And because day of the week are never at the same date from a year to another, it's becoming hard to know which day of the week was the March, End of 1954! Moreover this calendar is really marked by the Christian culture.

And we also have to edit new calendars every years, re-think the holidays, etc...

Here are the problems that we can evoke about our current calendar. Let's have a look about other calendars now.

The first and probably the most important to note here is the Maya calendar. This calendar cut the time in many different unities regarding the time length. One surprising thing is that it's ending on December 21st, 2012. There is plenty of different explanations for it that I can't speak about them here.

An other calendar that we could speak about here is the Republican calendar which was created during the French Revolution. In the same idea to separate references about monarchy like the foot, it has been etablished to be a time unit on base 10, with weeks of 10 days, months of 30 days, etc... It was used only for a few years after the French revolution and finaly went to the bin, probably because of the week length, too long....

Finally the Muslim calendar is based on the moon and its phases. That's why there is a shift with the Gregorian calendar.

OK, and what?

So one day I asked myself if it wouldn't be possible to create a new calendar that we could use and establish simply. The aim of this calendar and it's new time scale would be to propose fixed days throughout years without having to use an additional day every 4 years. This imply that the notion of day would be modified to operate. And so on the hours and the minutes.

As the second is the scientific time unit, this calendar will keep the relation with the current second. That will also simplify the computer change, because the time is stored in seconds, before being converted in a human readable date. The year will also be kept: it's determined by the time the earth use to go around the Sun. The weeks will still be with 7 days, to avoid bigger change in the work world.

Let's construct this calendar

nTime

For the units, I simply used the current name and prefixing the letter n.

We have 365 nDays to dispose. We can see that 365 = 52 * 7 + 1. So we can start that we'll have 52 nWeeks + 1 nDay.

52 = 4 * 13 : Let's place 13 nMonths of 4 nWeeks each one, which 28 nDays in 1 nMonth.

that way the calendar obtained is very strict and each nth nDay from the mth nMonth will be eaxctly the same xth day of the week.

Regarding units during the day, why don't cut the nDay in 10 nHours, and every nHour in 100 nMinutes? I didn't already make the conversion calculs, because I'll need to know the exact number of seconds in one year, year as it's astronomical term. Don't forget that 1 second = 1 nSecond.

We can notice that this change of scall for the hours and minutes will imply a tweak problem for the conversion from Gregorian dates to a date of this new calendar. In fact the minutes around midnight will sometimes be equal to the previous day, sometimes not. This will depend from Sun gap, so depends about the leap years... One more time once the conversion calcul will be done, the answers to these questions will be very clear and simple.

There is still one thing to do: define the relation with the current calendar and when it should be used. As the December 21st, 20012 seems to be an important date for many reasons, I propose to use this date as the first date of this new calendar. That's imply that the first nDay of the year will also be the winter's day, or more scientifically speaking the day of the winter solstice; date from when the days starts to become longer (in the north hemisphere).

I created a web page to show this calendar, with the dates relation.

This imply many nice thing for the season:

  • The spring will be the 7th nDay of the 4th nMonth, which will be equivalent to a Sunday.
  • The summer will be the 14th nDay of the 7th nMonth, still a Sunday.
  • the autumn will be the 21st nDay of the 10th nMonth, one more time a Sunday.

And if you look on the calendar, these dates are obliquely line up.

That's it about the theorical part of this calendar. You probably thought I'm totally crazy because I thought at least more than one second about this craziness, but why not?

After all most of the inventors was taken for fool at their time because they didn't think with the same paradigm than the others.

And you, what do you think about that?

Version française de ce billet

Réinventer le calendrier

Nous l'avons tous déjà remarqué : calculer des dates au fil des ans et difficile. Il faut jouer avec les années bisextiles, les semaines de 7 jours, les mois avec des nombres de jours différents, etc...

Partant de cette observation, j'ai commencé à me renseigné sur la notion de temps, et plus précisément de la mesure qui en a été fait par les hommes.

Dans la majeure partie du monde, nous utilisons le calendrier grégorien : mis en place en 1582, il se base sur le Soleil et la rotation de la Terre autour de celui-ci pour définir l'année et le jour. Dès cette époque, ce calendrier incluait le 29 février une année sur 4 pour obtenir une année de 365,25 jours.

Or, la Terre tourne autour du soleil en 365,24219 jours. Il y a donc un léger décalage, qui se rattrape aux années millésimes en n'ajoutant pas le 29 février. Et comme les jours de la semaine ne tombent jamais en même temps d'une année sur l'autre, cela devient compliqué pour savoir quel jour était le 2 mars 1954 ? De plus, ce calendrier est très marqué par la culture chrétienne.

Et puis on doit aussi éditer de nouveaux calendriers chaque année, repensé les jours fériés et ponts chaque année, etc...

Voilà pour ce qui est des problèmes que l'ont peu évoqué de notre calendrier actuel. Étudions brièvement les autres calendriers qui ont existé ou existent encore.

Le premier et sans doute le plus important à noter ici est le calendrier Maya. Ce calendrier découpe le temps qui passe en tout un tas d'unités selon la longueur du temps. Chose étonnante pour ce calendrier, il s'arrête le 21 décembre 2012. Différentes explications ont été envisagés pour cela, mais je n'entrerai pas dans les détails ici.

Un autre calendrier que l'on peut indiquer est le calendrier républicain qui a été crée pendant la révolution française. Dans la même idée de se séparer des références à la royauté comme le coude, le pied, etc..., il a été mis en place pour être une unité de temps à base 10, avec des semaines de 10 jours, des mois de 30 jours, etc... Il n'a été utilisé que quelques années après la révolution, puis passé aux oubliettes, sans doute à cause des semaines trop longues...

Enfin, le calendrier musulman est basé sur la Lune est ses phases. C'est pourquoi il y a un décalage avec le calendrier grégorien.

Oui, et alors ?

Alors un jour, je me suis demandé s'il ne serait pas possible de créer un nouveau calendrier que l'on pourrait utiliser et mettre en place simplement. Le but de calendrier et de cette nouvelle échelle de temps serait de proposer des jours fixes au fil des ans sans avoir à recourir à un jour supplémentaire. Ceci implique donc que la notion de jour devra être modifié pour fonctionner. Donc la notion d'heure et de minutes aussi.

Mais comme la seconde est l'unité scientifique de temps actuel, ce calendrier gardera la correspondance avec les secondes actuelles. Ce qui simplifiera d'ailleurs les changements informatiques, puisque le temps est exprimé en secondes, avant d'être converti dans une date lisible par l'être humain. L'année sera aussi conservé : elle est déterminé par le temps que met la Terre pour tourner autour du soleil. Les semaines devront toujours être de 7 jours pour ne pas changer encore plus les habitudes.

Passons à la construction de ce calendrier.

nTime

Pour les unités, j'ai simplement décider de prendre le nom actuelles et d'y préfixer la lettre n.

Nous avons 365 nJours à placer. On peut remarquer que 365 = 52 * 7 + 1. On peut donc partir du principe que nous aurons 52 nSemaines + 1 nJour.

52 = 4 * 13 : mettons donc en place 13 nMois de 4nSemaines chacun, soit 28 nJours.

De cette façon, le calendrier alors obtenu est très strict, et chaque nème nJour du mème nMois tombera toujours le xème même jour de la semaine.

Pour ce qui est des unités dans la journée, pourquoi ne pas en profiter pour découper la journée en 10 nHeures, et chaque nHeure en 100 nMinutes ? Je n'ai pas encore fais les calculs de conversion, car j'aurai besoin pour ça de connaître le nombre de secondes très précis qu'il y a dans une année, année au sens astronomique du terme. N'oublions pas que 1 seconde = 1 nSeconde.

Il est à noté que ce changement d'échelle pour les heures et minutes impliquera un léger problème pour la conversion des dates grégoriennes vers une date de ce nouveau calendrier. En effet, les minutes aux alentours de minuit seront parfois le jour équivalent précédent, parfois pas. Et cela dépendra de l'écart avec le soleil, et donc des années bissextiles... Encore une fois, lorsque des calculs plus poussés seront effectués, les réponses seront claires et simples.

Reste encore à définir la correspondance de ce calendrier et sa mise en place. Comme le 21 décembre 2012 semblre être une date charnière pour tout un tas de raison, je propose d'utiliser cette date comme étant le 1er jour de ce nouveau calendrier. Ce qui impliquera que le 1er nJour de l'année sera aussi le début de l'hiver, au plus scientifiquement parlant, le jour du solstice d'hiver, date à partir de laquelle les jours commencent à rallonger (dans l'hémisphère nord).

J'ai mis en place une page web représentant ce calendrier, avec la correspondance des dates.

Cela implique d'autres choses assez sympathique pour les autres saisons :

  • Le printemps serait le 7ème nJour du 4ème nMois, qui serait alors l'équivalent du dimanche.
  • L'été serait le 14ème nJour du 7ème nMois, toujours un dimanche.
  • L'automne serait le 21ème nJour du 10ème nMois, encore une fois un dimanche.

Et si on regarde sur le calendrier, ces dates sont alignés dans l'oblique du calendrier.

Voilà ce qu'il en est pour la partie théorique de ce calendrier. Vous aurez sûrement pensez que je suis complètement fou d'avoir penser ne serait-ce qu'un instant à une telle folie, mais pourquoi pas ?

Après tout, la plupart des inventeurs étaient pris pour des fous à leur époques car il ne pensait pas avec le même paradigme que leurs semblables.

Et vous, que pensez-vous de cette idée ?

Bilan (Serveur Web sur Debian Lenny)

Voilà, notre serveur est maintenant opérationnel en tout point.

Encore faut-il ajouter des sites internet dessus, transférer les fichiers, faire pointer les DNS dessus, etc...

Voici donc la marche à suivre pour ajouter un nouveau site sur le site :

I : Ajouter un nouvel utilisateur avec la commande :

useradd -m -g www-data DOMUSER
Comme nous avons créer le dossier www dans /etc/skel, la création de l'utilisateur va directement crée le /home de ce dernier avec le dossier pour contenir les fichiers du futur site web.

II : Ajouter le virtualhost dans Apache

Même si les DNS pointent vers notre serveur, Il n'y a encore rien qui indique que le serveur doit répondre à cette requête ; pire encore, on ne sait pas quels fichiers desservir... C'est pourquoi on ajoute dans /etc/apache2/sites-available/domain.dtd :
<VirtualHost *:80>
        ServerName domain.dtd
        ServerAlias www.domain.dtd
        DocumentRoot /home/DOMUSER/www/
        <Directory /home/DOMUSER/www/>
                Options -Indexes FollowSymLinks MultiViews
                AllowOverride All
        </Directory>
        ErrorLog /var/log/apache2/DOMUSER_error.log
        CustomLog /var/log/apache2/DOMUSER_access.log combined
</VirtualHost>
Puis on active le site et recharges la configuration d'apache :
a2ensite domain.dtd
/etc/init.d/apache2 force-reload

III : Ajouter la base de données

Vous voudrez probablement utilisez une base de données avec votre site. Il suffit d'exécuter les commandes suivantes :
mysql --user=root --password=PASSROOT --execute="CREATE DATABASE DOMUSER;"
mysql --user=root --password=PASSROOT --execute="GRANT ALL PRIVILEGES ON DOMUSER.* TO 'DOMUSER'@'localhost' IDENTIFIED BY 'PASSDOMUSER';"
mysql --user=root --password=PASSROOT --execute="FLUSH PRIVILEGES;"
De cette façon, on crée la base de donnée MySQL DOMUSER et l'utilisateur du même nom, qui a des droits uniquement sur cette base de données.

IV : Paramétrer les DNS

Pour que tout fonctionne bien, les DNS du serveur doivent être paramétrer pour répondre aux requêtes DNS. Pour ce faire, nous allons simplement ajouter des lignes dans notre base de données serverconf crée plus tôt :
mysql --user=serverconfuser --password=serverconfpass --database=serverconf --execute="INSERT INTO domain (name) VALUES ('domain.dtd');"

# $IDDB = id du domaine dans la table domain
# $SERVERNAME = nom unique de votre serveur (ksNNNNN.kimsufi.com par exemple)
# $SECONDDNS = adresse unique du second DNS (ns6.gandi.net par exemple)
# SERVERIP = adresse IP de votre serveur

mysql --user=serverconfuser --password=serverconfpass --database=serverconf --execute="INSERT INTO domainDNS (domain_id, master) VALUES ($IDDB, 'NATIVE');"
mysql --user=serverconfuser --password=serverconfpass --database=serverconf --execute="INSERT INTO record (domain_id, name, type, content) VALUES ($IDDB, 'domain.dtd', 'SOA', '$SERVERNAME. postmaster.domain.dtd `date +%Y%m%d`01 21600 3600 604800 86400');"
mysql --user=serverconfuser --password=serverconfpass --database=serverconf --execute="INSERT INTO record (domain_id, name, type, content) VALUES ($IDDB, 'domain.dtd', 'NS', '$SERVERNAME');"
mysql --user=serverconfuser --password=serverconfpass --database=serverconf --execute="INSERT INTO record (domain_id, name, type, content) VALUES ($IDDB, 'domain.dtd', 'NS', '$SECONDDNS');"
mysql --user=serverconfuser --password=serverconfpass --database=serverconf --execute="INSERT INTO record (domain_id, name, type, content, prio) VALUES ($IDDB, 'domain.dtd', 'MX', 'mail.domain.dtd', 25);"
mysql --user=serverconfuser --password=serverconfpass --database=serverconf --execute="INSERT INTO record (domain_id, name, type, content) VALUES ($IDDB, 'domain.dtd', 'A', '$SERVERIP');"
mysql --user=serverconfuser --password=serverconfpass --database=serverconf --execute="INSERT INTO record (domain_id, name, type, content) VALUES ($IDDB, 'www.domain.dtd', 'A', '$SERVERIP');"
mysql --user=serverconfuser --password=serverconfpass --database=serverconf --execute="INSERT INTO record (domain_id, name, type, content) VALUES ($IDDB, '*.domain.dtd', 'A', '$SERVERIP');"
La dernière ligne, avec *.domain.dtd, permet de mettre en place catch-all, ce qui veut dire que n'importe quel sous-domaine de domain.dtd sera pris en compte et envoyé vers le serveur. Ceci permet la mise en place beaucoup plus simple et plus rapide pour de nouveaux sous-domaines : il n'y a pas besoin de modifier les DNS !

Et voilà, vous pouvez maintenant envoyer vos fichiers par ftp en utilisant par exemple l'adresse ftp.domain.dtd.

V : Ajouter des adresses email

Avec votre sites, vous voudrez sans doute créer des adresses emails. Tout se fait là aussi en ajoutant des lignes dans la base de données serverconf :
mysql --user=serverconfuser --password=serverconfpass --database=serverconf --execute="INSERT INTO user (domain_id, user, password) VALUES ($IDDB, 'USER', MD5('PASS'));"
On créé ici l'adresse USER@domain.dtd avec le mot de passe PASS.

VI : Ajouter des alias d'adresse email

Mais parfois, les utilisateurs préfèrent garder leurs adresses email avec un alias. Rien de plus simple :
mysql --user=serverconfuser --password=serverconfpass --database=serverconf --execute="INSERT INTO alias (domain_id, source, destination) VALUES ($IDDB, 'USER', 'redir@email.com');"
Vous devriez donc maintenant être capable les éléments de base de votre serveur. Si vous avez quelques questions, utilisez les commentaires !

Pour ma part, mon serveur tourne depuis plus d'un mois maintenant sans aucun problème particulier...

Retour au sommaire.

Autres : ntpdate, apticron, etc... (Serveur Web sur Debian Lenny)

Dans ce dernier billet, je vais recensé tout un tas de petites choses qui améliore la vie du serveur et de l'administrateur.

Tout d'abord, je vous conseille de modifier les heures d'exécution des tâches cron dans /etc/crontab pour mettre des heures de creux de votre serveur ; pensez aux graphes de munin pour définir ces heures !

Ensuite, installons de nouveaux paquets :
apt-get install screen ncftp ntpdate apticron
Screen permet de lancer un nouveau shell dans un shell courant. Si votre connexion coupe ou si vous quittez le shell, il continue à s'exécuter sur le serveur : vous pouvez ensuite le reprendre. Très utile pour des tâches qui prennent énormément de temps.
Ncftp vous permettra d'effectuer des échanges FTP directement en ligne de commande, pour des opérations de sauvegardes par exemple.

A vous de consulter les documentations de ces paquets pour comprendre comment ils fonctionnent.

Ntpdate permet de mettre à l'heure votre serveur grâce au protocole ntp. Nous allons donc créer une tâche cron pour le faire chaque jour dans /etc/cron.daily/ntpdate :
#!/bin/sh
ntpdate cdns.ovh.net
Puis les droits d'éxécution :
chmod +x /etc/cron.daily/ntpdate
Apticron va regarder les mises à jour disponible sur votre serveur avec apt, et envoyer un email de rapport si des nouvelles sont disponibles. Il suffit de paramétrer l'email d'envoi dans /etc/apticron/apticron.conf :
EMAIL="server@domain.tld"
Nous avons mis en place un serveur de mail avec un antispam. Comme la plupart des antispam, DSpam a besoin d'entrâinement pour être efficace. il existe des corpus d'email pour réaliser cet entrâinement. Comme cela peut prendre longtemps, nous utilisons screen :

screen

cd /tmp
wget http://spamassassin.apache.org/publiccorpus/20050311_spam_2.tar.bz2
wget http://spamassassin.apache.org/publiccorpus/20030228_easy_ham_2.tar.bz2
tar xvfj 20050311_spam_2.tar.bz2
tar xvfj 20030228_easy_ham_2.tar.bz2
dspam_train dspam@test.com spam_2/ easy_ham_2/
rm -r 20030228_easy_ham_2.tar.bz2  20050311_spam_2.tar.bz2 easy_ham_2  spam_2 /home/var/vmail/test.com/ /var/spool/dspam/data/* /home/var/log/dovecot-deliver.log
touch /home/var/log/dovecot-deliver.log
chmod 777 /home/var/log/dovecot-deliver.log
exit
Enfin, lorsque nous allons ajouter un site, la 1ère étape sera d'ajouter un utilisateur système sur le serveur. Il est possible de gérer les fichiers et dossier créer dans le /home d'un nouvel utilisateur en les créant dans /etc/skel. Pour nous, supprimons tous les fichiers et dossiers qui y sont, puis ajoutons le dossier www :
rm /etc/skel/.* /etc/skel/*
mkdir /etc/skel/www

Et voilà notre serveur totalement terminé et opérationnel. Place maintenant à un bilan de tout ce que nous avons.

Retour au sommaire.

Monitoring : monit, munin (Serveur Web sur Debian Lenny)

Notre serveur fonctionne bien, avec quelques bans pour différents services. Mais qu'arrive-t-il si un démon tombe en panne ? Et puis comment connait-on la charge du serveur ?
Monit va répondre à la première question en vérifiant à intervalle régulier tous les services et les redémarrer si besoin.
Munin quant à lui va créer de nombreux graphes sur le serveur pour que vous puissiez vous rendre compte de la charge qu'il encaisse.

Munin

Commençons par activer le server-status d'apache, quis era utilisé par munin pour calculé des stats de processus et requêtes d'apache. Ajouter le fichier /etc/apache2/conf.d/server-status.conf :
ExtendedStatus On
<Location /server-status>
    SetHandler server-status

    Order Deny,Allow
    Deny from all
    Allow from 127.0.0.1
</Location>
Puis on peut passé à l'installation (les différents paquets perl sont utilisé par munin) :
apt-get install munin munin-node libhtml-parser-perl libhtml-tagset-perl libhtml-tree-perl liburi-perl libwww-perl
On ajoute quelques plugins à munin qui ne le sont pas par défaut, en appliquant les bons droits :
ln -s /usr/share/munin/plugins/netstat /etc/munin/plugins/netstat
ln -s /usr/share/munin/plugins/postfix_mailstats /etc/munin/plugins/postfix_mailstats
ln -s /usr/share/munin/plugins/apache_accesses /etc/munin/plugins/apache_accesses
ln -s /usr/share/munin/plugins/apache_processes /etc/munin/plugins/apache_processes
ln -s /usr/share/munin/plugins/apache_volume /etc/munin/plugins/apache_volume
ln -s /usr/share/munin/plugins/uptime /etc/munin/plugins/uptime
chown munin:munin /home/var/www/munin
Avec Lenny, le plugin netstat de munin à un problème de droit. Pour le résoudre, on le paramètre pour qu'il s'éxécute en root avec :
echo "[netstat]" > /etc/munin/plugin-conf.d/netstat
echo "user root" >> /etc/munin/plugin-conf.d/netstat
Avec la configuration actuelle, munin place ces fichiers dans /home/var/www/munin. Avec notre configuration actuelle d'apache, on ne pourrait pas y accéder.
Pour plus de simplicité, on va créer un sous-domaine en accès sécurisé pour voir ses stats. On commence par créer le certificat :
openssl req -new -x509 -days 3650 -nodes -out /etc/ssl/certs/munin.crt -keyout /etc/ssl/private/munin.key
On crée ensuite le .htpasswd pour le protéger :
htpasswd -c /home/var/www/munin/.htpasswd user
Puis on configure apache pour ce sous-domaine dans /etc/apache/sites-available/munin.domain.tld :
<VirtualHost *:443>
    ServerName munin.domain.tld

    # Activation du support SSL
    GnuTLSEnable on
    GnuTLSPriorities NORMAL
    GnuTLSCertificateFile /etc/ssl/certs/munin.crt
    GnuTLSKeyFile /etc/ssl/private/munin.key

    <location />
        AuthUserFile /home/var/www/munin/.htpasswd
        AuthGroupFile /dev/null
        AuthName "Restricted Area"
        AuthType Basic
        <Limit GET POST>
            require valid-user
        </Limit>
    </Location>

    DocumentRoot /home/var/www/munin
    ErrorLog /var/log/apache2/munin_error.log
    CustomLog /var/log/apache2/munin_access.log combined
</VirtualHost>
On active ce site pour apache, et on redémarre les services :
a2ensite munin.domain.tld
/etc/init.d/munin-node force-reload
/etc/init.d/apache2 force-reload

Monit

Monit va nous permettre de vérifier l'état des démons et d'effectuer les opérations nécessaires à son bon fonctionnement, tout en alertant l'administrateur. Dans la plupart des cas, un simple redémarrage sera effectué et tout ira bien.

On l'installe simplement :
apt-get install monit
On conserve la configuration par défaut :
mv /etc/monit/monitrc /etc/monit/monitrc_default
Pui on configure dans /etc/monit/monitrc :
set daemon  600
set logfile syslog facility log_daemon
set mailserver localhost
set mail-format {
        from: me@domain.tld
        subject: [monit] $SERVICE: $EVENT
}
set eventqueue basedir /home/var/monit slots 100
set alert server@domain.tld
set httpd port 9999 and
        allow user:pass

include /etc/monit/conf.d/*
On le configure avec une interface web accessible sur le port 9999 avec comme nom d'utilisateur user et mot de passe pass. S'il s'avère que l'envoi de mail échoue, monit conservera les messages dans /home/var/monit pour les renvoyer dès que possible. La fréquence des tests est toutes les 10 minutes.

Puis, nous allons devoir configurer chacun des démons que l'on veut monitorer. La plupart du temps il s'agira d'un pid et des commandes de démarrage et d'arrêt du démon. Si le pid change entre 2 tests, monit enverra simplement un email.
mkdir /etc/monit/conf.d
Dans /etc/monit/conf.d/apache :
check process apache with pidfile /var/run/apache2.pid
    group www
    start program = "/etc/init.d/apache2 start"
    stop program  = "/etc/init.d/apache2 stop"
    if cpu > 60% for 2 cycles then alert
    if cpu > 90% for 5 cycles then restart
    if totalmem > 500 MB for 5 cycles then restart
    if children > 250 then restart
    if loadavg(5min) greater than 10 for 8 cycles then stop
    if 3 restarts within 5 cycles then timeout
Le fichier de config le plus compliqué, il permet de redémarrer apache s'il prend trop de place en mémoire ou s'il a trop de processus enfant.

Dans /etc/monit/conf.d/clamav :
check process clamav with pidfile /var/run/clamav/clamd.pid
    group virus
    start program = "/etc/init.d/clamav-daemon start"
    stop  program = "/etc/init.d/clamav-daemon stop"
    if failed host localhost port 3310 then restart
    if 5 restarts within 5 cycles then timeout

check process freshclam with pidfile /var/run/clamav/freshclam.pid
    group virus
    start program = "/etc/init.d/clamav-freshclam start"
    stop  program = "/etc/init.d/clamav-freshclam stop"
    if 5 restarts within 5 cycles then timeout
Dans /etc/monit/conf.d/cron :
check process cron with pidfile /var/run/crond.pid
    group system
    start program = "/etc/init.d/cron start"
    stop  program = "/etc/init.d/cron stop"
    if 5 restarts within 5 cycles then timeout
Dans /etc/monit/conf.d/dovecot :
check process dovecot with pidfile /var/run/dovecot/master.pid
    group mail
    start program = "/etc/init.d/dovecot start"
    stop  program = "/etc/init.d/dovecot stop"
    if failed host localhost port 993 type tcpssl sslauto protocol imap then restart
    if failed host localhost port 995 type tcpssl sslauto protocol pop then restart
    if failed host localhost port 143 protocol imap then restart
    if failed host localhost port 110 protocol pop then restart
    if 5 restarts within 5 cycles then timeout
Dans /etc/monit/conf.d/dspam :
check process dspam with pidfile /var/run/dspam/dspam.pid
    group mail
    start program = "/etc/init.d/dspam start"
    stop program = "/etc/init.d/dspam stop"
    if 5 restarts within 5 cycles then timeout
Dans /etc/monit/conf.d/fail2ban :
check process fail2ban with pidfile /var/run/fail2ban/fail2ban.pid
    start program = "/etc/init.d/fail2ban start"
    stop  program = "/etc/init.d/fail2ban stop"
    if failed unixsocket /var/run/fail2ban/fail2ban.sock then restart
    if 5 restarts within 5 cycles then timeout
Dans /etc/monit/conf.d/munin :
check process munin-node with pidfile /var/run/munin/munin-node.pid
    group system
    start program = "/etc/init.d/munin-node start"
    stop program  = "/etc/init.d/munin-node stop"
    if failed host localhost port 4949 then restart
    if 5 restarts within 5 cycles then timeout
Dans /etc/monit/conf.d/mysql :
check process mysql with pidfile /var/run/mysqld/mysqld.pid
    group database
    start program = "/etc/init.d/mysql start"
    stop program = "/etc/init.d/mysql stop"
    if failed unix "/var/run/mysqld/mysqld.sock" then restart
    if failed host 127.0.0.1 port 3306 then restart
    if 5 restarts within 5 cycles then timeout
Dans /etc/monit/conf.d/postfix :
check process postfix with pidfile /var/spool/postfix/pid/master.pid
    group mail
    start program = "/etc/init.d/postfix start"
    stop  program = "/etc/init.d/postfix stop"
    if failed port 25 protocol smtp for 2 times within 2 cycles then restart
    if failed port 465 protocol smtp for 2 times within 2 cycles then restart
    if failed port 10026 protocol smtp for 2 times within 2 cycles then restart
    if 5 restarts within 5 cycles then timeout
Dans /etc/monit/conf.d/powerdns :
check process powerdns with pidfile /var/run/pdns.pid
    start program = "/etc/init.d/pdns start"
    stop program = "/etc/init.d/pdns stop"
    if failed host localhost port 53 then restart
    if 5 restarts within 5 cycles then timeout

check process powerdns-recursor with pidfile /var/run/pdns_recursor.pid
    start program = "/etc/init.d/pdns-recursor start"
    stop program = "/etc/init.d/pdns-recursor stop"
    if failed host localhost port 54 then restart
    if 5 restarts within 5 cycles then timeout
Dans /etc/monit/conf.d/rsyslog :
check process rsyslogd with pidfile /var/run/rsyslogd.pid
    group system
    start program = "/etc/init.d/rsyslog start"
    stop  program = "/etc/init.d/rsyslog stop"
    if 5 restarts within 5 cycles then timeout
Dans /etc/monit/conf.d/sshd :
check process sshd with pidfile /var/run/sshd.pid
    start program  "/etc/init.d/ssh start"
    stop program  "/etc/init.d/ssh stop"
    if failed port 22 protocol ssh then restart
    if 5 restarts within 5 cycles then timeout
Dans /etc/monit/conf.d/vsftpd :
check process vsftpd with pidfile /var/run/vsftpd/vsftpd.pid
    start program = "/etc/init.d/vsftpd start"
    stop program  = "/etc/init.d/vsftpd stop"
    if failed port 21 protocol ftp then restart
    if 5 restarts within 5 cycles then timeout
Enfin, nous devons activé monit dans /etc/default/monit :
startup=1
CHECK_INTERVALS=600
Et on redémarre le démon pour que le monitoring démarre :
/etc/init.d/monit force-reload
Le serveur est tout à fait opérationnel maintenant ! Il ne reste plus qu'un tout petit peu d'éléments à mettre en place.

Retour au sommaire.

Sécurité du serveur : fail2ban (Serveur Web sur Debian Lenny)

fail2ban est utilisé pour lire les log de tous les autres démons et bannir des adresses IP s'ils ont échoués à plusieurs reprises de se connecter.
On installe simplement par apt :
apt-get install fail2ban
Puis on configure fail2ban dans /etc/fail2ban/jail.conf
bantime  = 600
destemail = server@domain.tld
action = %(action_mwl)s

[postfix]
action   = %(action_)s
bantime  = 3600
De cette façon, on recevra un email lorsque fail2ban fera une action quelconque. Il a été désactivé pour postfix car les emails étaient très très nombreux !!!
Ensuite, activez les démons que vous désirez. Dans notre installation, il s'agit de pam-generic, vsftpd, postfix, apache, apache-noscripts, apache-overflows et sasl : il suffit de mettre enabled à true dans les sections concernés.

Il existe aussi une attaque sur le serveur Apache qui envoie des requêtes étranges sur la racine du serveur en cherchant un fichier commencant par w00tw00t. Nous pouvons bannir aussi les IP qui effectuent ces requêtes en ajoutant le fichier /etc/fail2ban/filter.d/apache-w00tw00t.conf :
#<HOST> - - [29/Apr/2008:22:54:08 +0200] "GET /w00tw00t.at.ISC.SANS.DFind:) HTTP/1.1" 400 326

[Definition]
# Option:  failregex
# Notes.:  regex to match the w00tw00t scan messages in the logfile. The
#          host must be matched by a group named "host". The tag "<HOST>" can
#          be used for standard IP/hostname matching.
# Values:  TEXT
failregex = ^<HOST> -.*"GET \/w00tw00t\.at\.ISC\.SANS\.DFind\:\).*".*

# Option:  ignoreregex
# Notes.:  regex to ignore. If this regex matches, the line is ignored.
# Values:  TEXT
ignoreregex =
Puis il faut activer ce filtre dans /etc/fail2ban/jail.conf en ajoutant :
[apache-w00tw00t]
enabled = true
filter  = apache-w00tw00t
port = all
banaction = iptables-allports
port     = anyport
logpath  = /var/log/apache*/access.log
maxretry = 1
bantime = 86400

En plus, je me suis aperçu que de nombreux spammeurs essayaient d'envoyer des emails à des adresses inexistantes. Par défaut, le filtre de fail2ban ne banni que les emails rejeté par le serveur (erreur 554) et pas les emails rejeté pour une adresse inexistante. c'est pour cela qu'on édite le fichier /etc/fail2ban/filter.d/postfix.conf pour simplement supprimé le 4 de failregex = reject: RCPT from (.*)\[<HOST>\]: 55 pour bannir n'importe quelle erreur.

Et pour finir, on recharge le démons pour prendre en compte nos changements :
/etc/init.d/fail2ban force-reload
Maintenant que notre serveur fonctionne avec les démons que l'on veut, si on monitorait pour avoir quelques stats et outils ?

Retour au sommaire.

Serveur de mail : postfix, dovecot, dspam, clamav (Serveur Web sur Debian Lenny)

Cette partie sera la plus grande car la plus complexe. Et on ne se facilite pas la tâche puisque le serveur de mail incluras un antispam avec vérifications des éventuels virus contenu dans les emails. L'antispam pourra aussi apprendre de ses erreurs lorsque l'utilisateur final déplacera simplement ses emails dans les dossiers IMAP.

Bref, commençons par supprimer l'éventuel Exim 4 qui serait présent sur le serveur :
apt-get remove exim4 exim4-base exim4-config exim4-daemon-light
Puis on installe tous les paquets d'un coup :
apt-get install mysql-server postfix postfix-mysql dovecot-imapd dovecot-pop3d dspam dspam-doc libdspam7-drv-mysql bzip2 clamav-daemon make
Durant l'installation, Postfix demande le type de configuration, qui sera naturellement "Sites Internet". Puis le nom du serveur ; entrez simplement le nom de domaine principal de votre serveur comme domain.tld.

Puis libdspam7-drv-mysql (le driver de stockage des informations de DSpam sur MySQL) vous demandera s'il faut créer la base de données. Répondez simplement oui. Le mot de passe MySQL root est demandé ensuite. Enfin, un mot de passe pour cette base de donnée est demandé. Laissez simplement le champ vide pour qu'il en choisisse un pour vous.

Commençons par créer les tables contenant les informations des emails et alias des sites web avec le fichier de création. Ces tables sont naturellement dans la même base de donnée que powerdns, puisqu'un email devra forcément être rattaché à un nom de domaine géré par le serveur DNS.
mysql -h localhost -u root --password=MySQL serverconf < /PATH/TO/postfix.sql
Postfix a besoin de savoir comment s'adresser à MySQL pour vérifier les mots de passe ou trouver les alias. Ces fichiers seront créé dans /etc/postfix/mysql :
mkdir  /etc/postfix/mysql
Puis on créé les fichiers :
/etc/postfix/mysql/email2email.cf est utilisé pour connaître les adresse email existantes :
hosts = 127.0.0.1
dbname = serverconf
user = serverconfuser
password = serverconfpass
query = SELECT CONCAT(user.user, '@', domain.name) AS email FROM domain,user WHERE user.domain_id=domain.id AND CONCAT(user.user, '@', domain.name)='%s'
/etc/postfix/mysql/virtual-alias-maps.cf est utilisé pour connaître les alias (les redirection d'emails) :
hosts = 127.0.0.1
dbname = serverconf
user = serverconfuser
password = serverconfpass
query = SELECT destination FROM alias, domain WHERE alias.domain_id=domain.id AND CONCAT(alias.source, '@', domain.name)='%s'
/etc/postfix/mysql/virtual-mailbox-domains.cf est utilisé pour connaître les domaines gérés :
hosts = 127.0.0.1
dbname = serverconf
user = serverconfuser
password = serverconfpass
query = SELECT 1 FROM domain WHERE name='%s'
Enfin /etc/postfix/mysql/virtual-mailbox-maps.cf est utilisé pour vérifier si une adresse email est bien géré par le serveur :
hosts = 127.0.0.1
dbname = serverconf
user = serverconfuser
password = serverconfpass
query = SELECT 1 FROM user,domain WHERE user.domain_id=domain.id AND CONCAT(user.user, '@', domain.name)='%s'

Enfin, il faut paramétrer postfix pour réagir sur différents ports dans le fichier /etc/postfix/master.cf :
Supprimer la ligne commençant par smtp et remplacer là par :
smtp inet       n       -       -       -       -       smtpd -o content_filter=lmtp:unix:/var/spool/postfix/var/run/dspam.sock
smtps inet      n       -       -       -       -       smtpd -o content_filter=lmtp:unix:/var/spool/postfix/var/run/dspam.sock
Afin que les courriers arrivant par smtp ou smtps soit filtrer par l'antispam.

Remplacer la ligne commençant par ltmp par
lmtp      unix  -       -       n       -       -       lmtp
Pour qu'il ne soit pas chrooté.

Enfin ajouter :
127.0.0.1:10026 inet    n       -       -       -       -       smtpd
        -o content_filter=
        -o receive_override_options=no_unknown_recipient_checks,no_header_body_checks
        -o smtpd_helo_restrictions=
        -o smtpd_client_restrictions=
        -o smtpd_sender_restrictions=
        -o smtpd_recipient_restrictions=permit_mynetworks,reject
        -o mynetworks=127.0.0.0/8
        -o smtpd_authorized_xforward_hosts=127.0.0.0/8

dovecot   unix  -       n       n       -       -       pipe
    flags=DRhu user=vmail:vmail argv=/usr/lib/dovecot/deliver -d ${recipient}
Le port 10026 est ici ouvert uniquement en local pour permettre à DSpam de renvoyer les emails non vérolés. Enfin la ligne avec dovecot permet d'utiliser ce dernier pour remettre l'email à l'utilisateur.

Tous nos emails vont être crée par un même utilisateur serveur, nommé vmail. Il faut donc le créer :
groupadd -g 5000 vmail
useradd -g vmail -u 5000 vmail -d /home/var/vmail -m
rm -rf /home/var/vmail/* /home/var/vmail/.*
Passons à la configuration de postfix :
postconf -e virtual_mailbox_domains=mysql:/etc/postfix/mysql/virtual-mailbox-domains.cf
postconf -e virtual_uid_maps=static:5000
postconf -e virtual_gid_maps=static:5000
postconf -e virtual_mailbox_maps=mysql:/etc/postfix/mysql/virtual-mailbox-maps.cf
postconf -e virtual_alias_maps=mysql:/etc/postfix/mysql/virtual-alias-maps.cf,mysql:/etc/postfix/mysql/email2email.cf
postconf -e virtual_transport=dovecot
postconf -e dovecot_destination_recipient_limit=1
postconf -e smtpd_sasl_type=dovecot
postconf -e smtpd_sasl_path=private/auth
postconf -e smtpd_sasl_auth_enable=yes
postconf -e smtpd_use_tls=yes
postconf -e mydestination=localhost
postconf -e smtpd_tls_auth_only=yes
postconf -e maximal_queue_lifetime=3d
postconf -e smtpd_recipient_restrictions=permit_mynetworks,permit_auth_destination,permit_sasl_authenticated,reject_unauth_destination
Avec smtpd_use_tls, seules les connexions sécurisés seront autorisé pour smtp. La dernière ligne est sans doute la plus important et la plus difficile à comprendre.
Elle permet de définir qui a le droit d'envoyer des emails. Paramètre très important pour que son serveur ne soit pas utilisable comme open relay et utilisé par les spammeurs...
On autorise les envoies du réseau (donc le serveur lui même), vers les adresses locales existantes (indispensable pour que les FAI puissent vous envoyer des emails par exemple), avec une connexion authentifié (donc les utilisateurs de votre serveur qui ont une adresse email sur votre serveur), et on rejette le reste.

Un petit peu d'autorisations sur ces fichiers est nécessaire pour vmail :
chgrp postfix /etc/postfix/mysql/*.cf
chmod u=rw,g=r,o= /etc/postfix/mysql/*.cf

Comme indiqué en haut de page, les utilsateurs vont pouvoir entrainé DSpam par de simples déplacement de mails en IMAP. Dovecot ne permet pas de mettre en place ceci directement, mais ce plugin le permet. Télécharger le à cette adresse et envoyer le sur votre serveur (vous avez un serveur FTP maintenant, non ?) et placer le dans /usr/src. Puis dégzippage :
cd /usr/src
gzip -d dovecot-antispam-HEAD.tar.gz
tar xvf dovecot-antispam-HEAD.tar
cd dovecot-antispam
Pour pouvoir compiler, ce plugin a besoin des sources de dovecot :
apt-get source dovecot
tar xfv dovecot_1.0.15.orig.tar.gz

Puis on paramètre ce plugin :
cp defconfig .config
Et on édite .config
BACKEND=dspam-exec
DOVECOT=./dovecot-1.0.15
Le backend spécifie de quelle façon le plugin va réapprendre à DSpam les emails déplacés. Après quelques tests, l'appel direct à DSpam s'est avéré le plus efficace. On peut donc compiler :
make install
Le fichier /usr/lib/dovecot/modules/imap/lib90_antispam_plugin.so devrait être créé.

Et on peut passer à la configuration de dovecot dans /etc/dovecot/dovecot.conf :
protocols = imap imaps pop3 pop3s managesieve
mail_location = maildir:/home/var/vmail/%d/%n/Maildir:INBOX=/home/var/vmail/%d/%n/Maildir/:INDEX=/home/var/vmail/%d/%n/Maildir/tmp/index
Dans la partie protocol imap :
  mail_plugins = antispam
  imap_client_workarounds = outlook-idle delay-newmail
Dans la partie protocol pop3 :
  pop3_client_workarounds = outlook-no-nuls
Dans la partie protocol lda :
   postmaster_address = postmaster@domain.tld
   auth_socket_path = /var/run/dovecot/auth-master
   mail_plugins = cmusieve
   log_path = /home/var/log/dovecot-deliver.log
   global_script_path = /home/var/vmail/globalsieverc
Dans la partie auth default :
 mechanisms = plain login
 # Commenter la partie passdb pam
 # Décommenter la partie passdb sql avec comme paramètres :
    args = /etc/dovecot/dovecot-sql.conf
 Dans la partie userdb static :
    args = uid=5000 gid=5000 home=/home/var/vmail/%d/%n allow_all_users=yes
 Dans la partie socket listen :
    master {
        path = /var/run/dovecot/auth-master
        mode = 0600
        user = vmail
    }
    client {
        path = /var/spool/postfix/private/auth
        mode = 0660
        user = postfix
        group = postfix
    }

Dans la partie plugin, nous allons paramètrer le plugin précédemment compilé :
  ##################################
  # Antispam plugin

  # mail signature (used with any backend requiring a signature)
  antispam_signature = X-DSPAM-Signature

  # semicolon-separated list of Trash folders (default unset i.e. none)
  # antispam_trash =
  antispam_trash = trash;Trash;Deleted Items;&AMk-l&AOk-ments supprim&AOk-s

  # semicolon-separated list of spam folders
  antispam_spam = Spam;spam;Junk;junk;Courrier ind&AOk-sirable

  # semicolon-separated list of unsure folders (default unset i.e. none)
  # antispam_unsure =
  # Whether to allow APPENDing to SPAM folders or not. Must be set to
  # "yes" (case insensitive) to be activated. Before activating, please
  # read the discussion below.
  # antispam_allow_append_to_spam = no

  antispam_dspam_binary = /usr/bin/dspam
  antispam_dspam_args = --user;root;--source=error
Le protocole managesieve permettra à l'utilsateur de créer des filtres côtés serveur, pour par exemple pour créer une réponse automatique.

Il faut créer le fichier de log :
touch /home/var/log/dovecot-deliver.log
chmod 777 /home/var/log/dovecot-deliver.log
Et comme ce fichier de log va grossir, nous devons paramétrer la rotation de ce fichier de log an ajoutant le fichier /etc/logrotate.d/dovecot :
/var/log/dovecot*log {
       weekly
       missingok
       rotate 4
       compress
       delaycompress
       notifempty
       create 777 root adm
}
Donner les droits à vmail sur la config de dovecot :
chown vmail:vmail /etc/dovecot/dovecot.conf
chmod g+r /etc/dovecot/dovecot.conf
Enfin, il faut paramétrer dovecot pour se connecter à MySQL et vérifier les mot de passes dans /etc/dovecot/dovecot-sql.conf :
driver = mysql
connect = host=127.0.0.1 dbname=serverconf user=serverconfuser password=serverconfpass
default_pass_scheme = PLAIN-MD5
password_query = SELECT CONCAT(user.user, '@', domain.name) AS user,user.password FROM user,domain WHERE user.domain_id=domain.id AND CONCAT(user.user, '@', domain.name)='%u'
Comme le serveur utilise des protocoles sécurisés, nous devons créés des certificats :
openssl req -new -x509 -days 3650 -nodes -out /etc/ssl/certs/dovecot.pem -keyout /etc/ssl/private/dovecot.pem
# Country Name (2 letter code) [AU]:                        FR
# State or Province Name (full name) [Some-State]:            France
# Locality Name (eg, city) []:                            Besancon
# Organization Name (eg, company) [Internet Widgits Pty Ltd]:        Company Name
# Organizational Unit Name (eg, section) []:                    .
# Common Name (eg, YOUR name) []:                            domain.tld
# Email Address []:                                    certs@domain.tld
openssl req -new -x509 -days 3650 -nodes -out /etc/ssl/certs/postfix.pem -keyout /etc/ssl/private/postfix.pem
Et de donner les droits nécessaires :
chmod o= /etc/ssl/private/dovecot.pem
chmod o= /etc/ssl/private/postfix.pem
Pour enfin les utilisé dans postfix :
postconf -e smtpd_tls_cert_file=/etc/ssl/certs/postfix.pem
postconf -e smtpd_tls_key_file=/etc/ssl/private/postfix.pem
S'en est terminé avec postfix et dovecot, passons à l'antispam :
Il faut d'abord créer son dossier et donner les droits nécessaires dans le pool de postfix :
mkdir -p /var/spool/postfix/var/run/
chown dspam:dspam /var/spool/postfix/var/run/
Et le paramétrer dans /etc/dspam/dspam.conf :
StorageDriver /usr/lib/dspam/libmysql_drv.so
#TrustedDeliveryAgent "/usr/lib/dovecot/deliver -d %u"
DeliveryHost 127.0.0.1
DeliveryPort 10026
DeliveryIdent localhost
DeliveryProto SMTP
QuarantineAgent "/usr/lib/dovecot/deliver -d %u -m Spam"
Trust vmail
SupressWebStats on
Preference "spamAction=quarantine"
Preference "signatureLocation=headers"  # 'message' or 'headers'
#Preference "showFactors=on"
Opt out
TrackSources spam virus
ClamAVPort     3310
ClamAVHost     127.0.0.1
ClamAVResponse reject
ServerPID /var/run/dspam/dspam.pid
ServerMode auto
ServerPass.Relay1 "secret"
ServerParameters        "--deliver=innocent -d %u"
ServerIdent "localhost.localdomain"
ServerDomainSocketPath "/var/spool/postfix/var/run/dspam.sock"
ClientHost /var/spool/postfix/var/run/dspam.sock
ClientIdent "secret@Relay1"
Lorsque des spams seront détectés, ils seront directement envoyer dans le dossier Spam de l'utilsataeur. Si un virus est détecté, on rejette l'email.

Dans /etc/dspam/dspam.d/mysql.conf :
MySQLUIDInSignature    on
chown -R dspam:dspam /etc/dspam/*
echo "dspam:shared:*" > /var/spool/dspam/group
Dans /etc/default/dspam :
Start=yes
Enfin, nous devons autorisé DSpam à délivrer les messages directement via deliver de dovecot. Mais il doit avoir le bon userid lorsqu'il exécute ce programme. C'est pourquoi nous utilisons et setuid sur ce dernier :
chmod +s /usr/lib/dovecot/deliver
Il faudra réiterer cette commande à chaque mise à jour de dovecot.

Il ne reste plus qu'à configurer l'antivirus, ClamAv. très rapidement, on édite /etc/clamav/clamd.conf
#Comment localSocket and Add
TCPAddr 127.0.0.1
TCPSocket 3310
Enfin, on redémarre tous les services paramétrés :
/etc/init.d/clamav-daemon force-reload
/etc/init.d/dspam force-reload
/etc/init.d/dovecot force-reload
/etc/init.d/postfix force-reload
Notre serveur de mail complet est maintenant terminé. Ouf, c'était le plus gros point de notre serveur. Il est d'ailleurs maintenant tout à fait opérationnel, mais on va encore y ajouter quelques éléments pour la sécurité et le monitoring.

Retour au sommaire.

< 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 >