+++

title = "Docker dans LXC, l’aventure"
date = 2019-09-01
aliases = [ "post/2019/09/01/Docker-dans-LXC,-l’aventure"]
draft = true
[taxonomies]
tags = [ "lxc", "docker", "système" ]
+++
((/39fmvg.jpg|))<!-- more -->Ceci ne fait pas exactement partie de la série sur mon auto-hébergement. Pour une raison assez simple : cet article a une portée un peu plus importante.

!!!Les conteneurs, c’est bien, en abuser, ça craint !

LXC/LXD, ça devrait parler à tout le monde ici : c’est un système permettant de faire des VE (''Virtual Environments''). A contrario des VM (''Virtual Machines''), les VE sont bien plus légers : ils ne se préoccupent pas de la couche de gestion du matériel.

Ainsi un Linux de base prendra entre 120 et 200 Mio de mémoire en VM, mais seulement 15 à 20 Mio de mémoire en VE.

Par contre, les VE sont bien plus limités : impossible de formater un système de fichiers, de monter un disque, etc… Ce n’est pas fait pour ça. C’est fait essentiellement pour isoler un peu le système invité du système hôte, mais on continue à utiliser le noyau de l’hôte (avec tous ces modules).

Docker aussi, ça devrait parler à tout le monde (au moins parce que c’est la mode). C’est exactement pareil, mais l’idée est ici de faire tourner un environnement qui ne fait lui-même fonctionner qu’un seul processus. Si le VE ressemble donc à une VM castré, Docker, c’est simplement un moyen de distribuer un logiciel avec toutes ces librairies et dépendances dans un seul « pack ».

!!! LXC/LXD et les privilèges

Par défaut, LXC tourne en __non-privilégié__. En clair, ça veut dire que le ''root'' dans le conteneur est « squashé » vers un numéro bien plus haut au niveau de l’hôte (généralement +100 000).
+++

title = "DMARC : toi aussi aide tes petits camarades à vérifier qu’ils n’ont pas merdé (1/2)"
date = 2019-12-16 10:00:00
aliases = [ "post/2019/11/28/DMARC-:-toi-aussi-aide-tes-petits-camarades-à-vérifier-qu’ils-n’ont-pas-merdé"]
+++
Parce que personne n’est parfait, surtout pas toi…<!-- more -->DMARC, c’est le machin qui est imposé maintenant par Google, Microsoft & Co dès que tu veux leur envoyer un message. Et en vrai, c’est pas une si mauvaise idée que ça. Le principe de base est le suivant :

- on t’a obligé à avoir du SPF, sinon on refuse tes messages. Mais le souci, c’est que les redirections (fréquentes dans ce domaine), ça casse tout et on ne peut rien y faire ;
- on t’a du coup obligé à avoir du DKIM. Ça signe tous les messages, et ça permet de s’assurer qu’effectivement, ça vient bien de là où ça prétend venir.

On a donc, d’une certaine manière, résolu une partie du problème : si le SPF merde pour une raison ou pour une autre, DKIM peut permettre de s’assurer que les messages sont bien légitimes. Inversement, si DKIM merde (non-signature, message technique d’un relais, etc…), on peut au moins s’assurer que le message vient du bon endroit.

ais, il manque quand même un élément crucial à tout ça : que faire des messages « non-conformes » ? Qui va décider que les messages non-signés DKIM ou non-provenant de la bonne adresse SPF, faut les jeter à la poubelle ou pas ?

## DMARC to the rescue!!

C’est précisément là qu’intervient DMARC : l’idée est de donner une politique générale sur ce qu’il faut faire si le message semble chelou. « Chelou » en DMARC, ça veut dire qu’il vient du mauvais endroit (donc viole la politique SPF) **ET** qu’il n’est pas signé (donc viole la politique DKIM).

Et quand on y réfléchit bien, un tel message est effectivement tout sauf légitime : aucune raison d’accepter un message non-signé qui vient d’une IP russe^Wchinoise^Wde Google. En plus, DMARC permet de recevoir des rapports qui donnent des indications précieuses sur les messages qui ont été reçus par les destinataires.

Petite précision importante, c’est bien un **ET** et pas un **OU** : le protocole prévoit le fait qu’un message peut être redirigé (donc violer sciemment la politique SPF, mais en conservant dans la plupart des cas la signature DKIM d’origine) ou que certains messages de service (abonné absent, mauvaise passerelle, etc…) peuvent ne pas être signés.

Tu vas donc pouvoir indiquer comment tu veux que tes messages soient traités en cas de souci, mais en plus, on va t’informer de ce qui a été fait et pourquoi. Ça peut aussi te permettre de repérer les p’tits malins qui essaient de te barber au passage…

Et la politique DMARC en question, ça ressemble à quoi ? 3 formes possibles :

- ''none'' : tu fais rien, je veux juste avoir les rapports, c’est tout
- ''quarantine'' : tu classes en pourriel
- ''reject'' : pas la peine d’accepter les messages, visiblement, c’est de la merde

Dans les deux derniers cas, tu peux même spécifier un pourcentage de message qui subiront ce traitement. L’idée est ici de permettre à de grosses organisations, qui envoient beaucoup de messages, de progressivement mettre en place le système et de permettre à leurs usagers de se rendre compte qu’ils font de la merde.

## Bon, vas-y, tu me l’as vendue ta merde, comment je fais pour ça chez moi ?

La première chose à faire est de s’assurer que tu peux recevoir les rapports DMARC des autres. Pour cela, c’est relativement simple, il suffit d’ajouter un enregistrement de ce type dans ta zone :

```
_dmarc.tamere.lol.	3600\	IN\	TXT\	"v=DMARC1; p=none; rua=mailto:postmaster@tamere.lol;"\
```

Avec ça, tu précises :

- tu as une politique DMARC (doh!)
- tu précises qu’il n’y a pas de politique pour le moment ''none''
- tu précises où tu veux recevoir les mails de rapport

Petite précision supplémentaire, si tu veux recevoir les rapports DMARC sur une adresse qui n’est pas dans le domaine à protéger, tu dois rajouter dans le domaine en question un enregistrement de type TXT dans la zone de réception :

```
youplaboom.com._report._dmarc.tamere.lol. 21600 IN TXT "v=DMARC1;"
```

Dans cet exemple, à condition d’avoir posé un enregistrement ''_dmarc'' dans la zone `youplaboom.com`, tu peux recevoir les rapports avec une adresse en `@tamere.lol`.

Ces rapports viennent sous forme de fichiers XML zippés ou gzippés à l’adresse indiquée. Ils ne sont pas bien compliqués à lire « à la main », mais il y a plein de logiciels en ligne qui permettent de visualiser de manière un peu plus simple les choses et de repérer plus facilement les erreurs de configuration.

Pour commencer, il est très fortement recommandé de laisser pendant quelques jours, voire quelques semaines, la politique à ''none''. Pour une raison très simple : ça permet de récupérer des données et de voir si ton serveur de courriels est correctement configuré. On se rend compte de belles conneries parfois en faisant ça : un relais bizarrement fait, des signatures DKIM qui ne correspondent pas, etc…

Une fois que tu es confiant dans ce que tu as dans ton serveur de messagerie, tu peux commencer à changer la politique et mettre quelque chose de plus restrictif. Tu peux même préciser un pourcentage de traitement (avec la commande `pct=<chiffre entre 0-100>`) pour dire que tu veux qu’un certain pourcentage de message soit traité de cette manière là. L’idée est toujours la même : aller le plus progressivement possible vers la politique la plus stricte possible, à savoir `p=reject;`.

## Protéger aussi les autres

Une bonne idée avant de fermer tout ça : si tu as des domaines dont tu ne te sers pas pour envoyer du courriel, tu as probablement grandement intérêt à préciser les élements suivants :

- SPF à `v=spf1 -all`
- DMARC à `v=DMARC1; p=reject; rua=mailto:postmaster@tamere.lol;`

Cela permet de préciser à tout ceux qui font du DMARC qu’il est **TOTALEMENT** anormal de recevoir des messages sur ce domaine. De cette manière, non seulement tu te protèges toi (ta réputation, les noms de domain que tu as acheté), mais tu protèges aussi les autres des cyber-squatteurs et autres enfoirés qui pourraient essayer de te barber…

## Conclusage

Voilà, t’as déjà de quoi t’amuser un moment et tu vas pouvoir voir non seulement si ta configuration est bonne dans tous les cas, mais en plus voir s’il n’y a pas des enfoirés qui essaient de te la mettre à l’envers.

Dans le prochain épisode, nous verrons comment faire pour envoyer des zolis rapports à tous nos correspondants histoire de rendre service à tout le monde en plus ;)
+++

title = "Journaliser les conversations qui passent par ses serveurs SMTP"
date = 2020-06-25 13:48:00
aliases = [ "post/2020/06/25/Journaliser-les-conversations-qui-passent-par-ses-serveurs-SMTP"]
+++
Parce que ça peut toujours servir<!-- more -->Récemment, je me suis un peu fritté avec Postfix et ElasticSearch et j’ai fini par me dire que ça pourrait en intéresser certains. Le challenge est assez simple en réalité : être capable de repérer très rapidement qui a parlé à qui et à quel moment.

Et en fait, c’est pas aussi simple que ça.

## Au début, il y avait **syslog**

La base du problème n’est finalement pas si compliqué que ça : quand on a un ou plusieurs serveurs SMTP, on peut commencer par balancer l’ensemble des logs dans **syslog**. Ça permet de les centraliser et ça permet également de faire des recherches croiser quand on en a plusieurs.

Jusque là, rien de bien sorcier. Je vous passe également le fait de balancer ces logs dans **Logstash**. Je ne dis pas que c’est à la portée du premier con venu, mais ça dépasse quelque peu le cadre de cet article (je te rassure on va quand même en faire un peu, mais je ne détaillerai pas plus que ça).

Bref, je pars du principe que vous avez un **syslog** qui concentre tout et qui repasse le bébé à un **Logstash**.

## Ensuite, il fallu faire un peu le tri

alheureusement, comme souvent avec ELK, il va être nécessaire de faire le tri en amont pour ne pas se retrouver avec des grosses conneries un peu partout. Dans **Logstash**, il va falloir faire un **pipeline** et y appliquer des filtres. Donc, on va insérer ça dans le fichier `/etc/logstash/pipelines.yml` :

~~~
- pipeline.id: syslog
   path.config: "/etc/logstash/syslog/conf.d/*.conf"
~~~

Ça permet de créer une configuration complètement à part pour **syslog** avec des entrées, des sorties et tout ce qui va bien, tout en faisant un truc à peu près propre. À partir de ce moment-là, on peut créer, dans `/etc/logstash/syslog/conf.d/`, deux fichiers `10_input.conf` et `90_output.conf` :

`10_input.conf` :

~~~
input {
    udp {
        port => 1234
        type => "syslog"
    }
}
~~~

`90_output.conf` :

~~~
output {
  elasticsearch {
    index => "syslog-%{+YYYY.MM.dd}"
    template_name => "syslog-*"
  }
}
~~~

**Si tu te poses la question, il faut que les fichiers soient lus dans le bon ordre pour faire les choses correctement, donc oui, je mets des chiffres en début de fichiers, c’est moche mais au moins, je suis certain que la conf est lue dans le bon sens.**

Ça permet de créer une entrée (type **syslog**) et une sortie dans un **template** Elasticsearch. Jusque là, on n’a pas vraiment réinventé la mayonnaise, on prend juste des entrées et on les balance dans des sorties (et figurez-vous que ça fonctionne, c’est un truc de gue-din). Bon, maintenant, on a certes des données, mais elles ne sont absolument pas triées.

En gros, on a une date et un message, mais c’est à peu près tout. Et ça ne nous avance pas beaucoup. Donc, on va faire un premier filtre qui va permettre de récupérer les données **syslog** et de commencer à faire un premier tri. Tu peux faire un fichier intermédiaire (qu’on appellera `20_filter_10_begin.conf`) :

~~~
filter {
  if [type] == "syslog" {
    grok {
      match => { "message" => "%{SYSLOGTIMESTAMP:syslog_timestamp} %{SYSLOGHOST:syslog_hostname} %{PROG:syslog_program}(?:\[%{POSINT:syslog_pid}\\])?: %{GREEDYDATA:syslog_message}" }\
      add_field => [ "received_at", "%{@timestamp}" ]
      add_field => [ "received_from", "%{host}" ]
    }
    date {
      match => [ "syslog_timestamp", "MMM  d HH:mm:ss", "MMM dd HH:mm:ss" ]
    }
  }
}
~~~

Voilà, maintenant, tu relances ton **Logstash** et tu devrais commencer à récupérer quelques données. Elles sont relativement brutes : tu as le serveur, la date et l’heure, le nom du programme et c’est à peu près tout. Ça peut déjà pas mal servir, mais on va quand même essayer d’affiner un peu…

## Et après, on laisse affiner pendant quelques mois, comme pour le Beaufort

aintenant, tu vas [aller télécharger ces quelques fichiers](https://github.com/whyscream/postfix-grok-patterns) et les coller dans les bons répertoires (`/etc/logstash/syslog/patterns/` pour le fichier `.grok` et dans `conf.d` pour le reste, en faisant bien attention à le renommer pour qu’il soit lu après le reste, mais avant le **output**).

Une fois que tu as fait ça, tu peux de nouveau relancer **Logstash**. Ces modèles sont très très bien faits et permettent de vraiment trier complètement les différentes étapes de traitement de chaque message : mise en queue, traitement, livraison, nettoyage, etc…

Tu peux déjà t’amuser dans l’interface de Kibana pour essayer de retrouver certains messages, des destinataires, des expéditeurs et ainsi de suite :

![img](https://blog.libertus.eu/postfix_premier_tri.png)

Et rien qu’avec ça, tu peux déjà faire pas mal de merdes ! Tu peux faire des rapports permettant de voir le nombre de messages échangés (suffit de compter les **queueid** uniques), tu peux voir le volume moyen des messages échangés, etc…

Tout ça, c’est très bien, mais à un moment, quelqu’un viendra forcément te poser la question : et comment je fais pour savoir qui a écrit à qui ?

## Ça a l’air simple comme ça, mais en fait non…

Dit comme ça, ça a effectivement l’air tout con et dans l’absolu, tu te dis probablement que tu as la donnée, donc que ça ne devrait pas être si compliqué que ça à extraire. En fait, si. Le souci, c’est que tu as effectivement la donnée : si tu tries en fonction du **queueid** de Postfix, tu peux effectivement savoir qui a écrit à qui. *Mais d’un point de vue données, tu n’as pas tout sur une seule ligne !*

Et Elasticsearch a ce côté un peu chiant : si tu n’as pas toutes les infos dont tu as besoin sur la même ligne, dans le même document, dans le même enregistrement, alors faire des recoupements peut devenir extrêmement pénible. Alors évidemment, pour de la recherche manuelle, ce n’est pas bien compliqué : tu cherches le destinataire, tu trouves le **queueid**, tu retries par **queueid** et tu finiras bien par tomber dessus.

ais à partir du moment où tu dois le confier à quelqu’un d’autre ou simplement si tu veux faire des stats ou des rapports un peu plus poussés, bah ça va être très compliqué, voire impossible.

## Bah alors, on fait quoi du coup ? À part avoir l’air con…

J’arrive mes petits bisous, j’arrive. En fait, j’ai tourné en rond sur ce problème pendant un bon moment. J’ai d’abord cherché à voir si je pouvais faire des corrélations un peu complexes dans ELK lui-même. Ça n’a pas vraiment donné les résultats que j’attendais (probablement pas impossible à faire, mais bien trop compliqué à mon goût). Il paraît que la version payant d’ELK sait faire pas mal de choses de ce point de vue là, mais je suis trop pauvre pour ça (pour un besoin pro, ça pourrait se justifier, pour un besoin perso, c’est quand même plus compliqué).

J’ai ensuite cherché comment faire du multiligne. C’est possible, et ça existe, il y a même des [plugins spéciaux](https://www.elastic.co/guide/en/logstash/current/plugins-codecs-multiline.html) pour ça. Il y a même [des gens qui l’ont déjà fait](https://github.com/whyscream/postfix-grok-patterns).

Le souci, c’est que tout cela date un peu (beaucoup de fonctions ont changé) et que je ne suis jamais parvenu à le faire fonctionner correctement. Avec un peu de temps et d’efforts, c’est peut-être possible de le faire fonctionner, mais sincèrement bon courage !

Bref, après avoir bien galéré sur le sujet pendant un moment, je me suis dit qu’il était peut-être possible d’enrichir les logs de Postfix avec d’autres données. Si on n’arrive pas à traiter en aval, il vaut mieux revenir sur les données en amont pour essayer de pousser plus de choses ou de rendre les choses un peu différemment.

Première chose à faire donc, dire à Postfix de journaliser d’autres informations sur les messages reçus. Par exemple, leur sujet : tous les messages ont un sujet, cela doit donc être possible de le journaliser. Et bien, oui et c’est même relativement simple. Dans la configuration de Postfix (`main.cf`), il suffit d’ajouter cette ligne :

~~~
header_checks = regexp:/etc/postfix/header_checks
~~~

Puis de créer le fichier de **regexp** correspondant :

~~~
/^Subject:/     WARN
~~~

Là, on dit à Postfix de journaliser tout message contenant l’entête **Suject** (donc tous les messages en gros) et de lui attribuer le niveau **WARNING**. On relance Postfix et là, voilà ce qu’on obtient :

~~~
Jun 25 16:32:57 smtp-1 postfix/cleanup[32674]: C9D27601B2: warning: header Subject: RE: I iz a subject from mail1.example.com[203.0.113.1]; from=<bidule@example.org> to=<truc@example.net> proto=ESMTP helo=<mail1.example.com>
~~~

\o/\

Non seulement Postfix a journalisé le sujet du message (ce qui est déjà très bien, ça nous permet de visualiser cela en une seule ligne), mais, coup de bol, il récupère aussi les autres informations du message en bonus. Et figure-toi que les filtres que tu as utilisé avant permettent de récupérer toutes ces informations directement dans ELK.

Dans Kibana, il suffit alors de mettre en place un petit filtre :

* `syslog_program: postfix`

* `postfix_message_level: warning`

* `postfix_to exists`

* `postfix_from exists`

Et tu vas récupérer exactement la liste de l’ensemble des messages qui sont passés par ton SMTP, avec le destinataire, l’expéditeur et le sujet du message :

![img](https://blog.libertus.eu/postfix_second_tri.png)

## Conclusage

Voilà, maintenant, tu as tout le nécessaire pour aller récupérer des données hyper précises sur tes SMTP et ça ne va pas être très compliqué de récupérer tous les messages dont machin est le destinataire ou tous les messages volumineux à destination de truc ou même faire des gros graphiques de ouf.
