Introduction

Cette partie a pour objet de trouver le moyen d'obtenir le plus d'informations possible des logs issus de Bind. Ce serveur DNS peut être verbeux lorsqu'on a pris soin de configurer la partie des logs. On peut ainsi tracer toute demande de requête DNS sur le serveur et analyser en profondeur ces demandes.

Contenu des logs

Avant de commencer, étudtions un peu ce qu'on peut récupérer dans un log Bind (requests.log):

[[!format Erreur: Format de page non reconnu log]]

Voici ce qu'on peut récupérer dans l'ordre d'apparition:

  • La date et l'heure à la milliseconde près. Il est très important de récupérer cette information de manière complète.
  • L'adresse IP qui a fait la requête (le client DNS).
  • Le domaine requêté (entre parenthèse et après le mot query:).
  • Le type de la requête DNS (A pour IPv4, AAAA pour IPv6, MX, etc...).
  • Enfin, on trouve l'adresse IP du serveur qui répond.

Au final, cela fait quelques champs à gérer:

  • La date de la requête.
  • Qui a fait la requête ?
  • Quel domaine a été requêté ?
  • Quel type de requête DNS ?

Pour ma part, je n'ai qu'un seul DNS donc récupérer son adresse n'a pas trop d'intérêt.

Capturer l'information du log

Logstash vient sans filtre tout prêt. Cette fois, il va falloir expérimenter et pour cela, il nous faut définir nos propres motifs grok. Le plus simple consiste à copier le fichier ./vendor/bundle/jruby/1.9/gems/logstash-patterns-core-0.3.0/patterns/grok-patterns dans un répertoire ./patterns sous le nom que vous voulez. Ensuite, dans votre filtre grok, il faudra indiquer qu'on souhaite utiliser ce répertoire comme répertoire de motifs. Cela est possible grâce à la directive patterns_dir.

Etudions notre filtre grok...

D'abord, il nous faut récupérer la date et l'heure pour faire un timestamp. Si on regarde les filtres grok du fichier grok-patterns, on se rend compte qu'aucun ne correspond. Il faut l'exprimer en essayant d'utiliser les motifs déjà présent. Pour ma part, j'ai trouvé la forme suivante:

BINDTIMESTAMP %{MONTHDAY}-%{MONTH}-%{YEAR} %{TIME}

Rien de bien compliqué mais nous voilà équipé.

Ensuite, il n'y a rien pour les requêtes DNS. Ici, nous allons créer un motif simple:

DNSQUERY A|AAAA|MX|SRV|TXT

Pour le reste, on va pouvoir se débrouiller avec les motifs grok livrés avec Logstash. Donc, ajoutez les deux lignes mentionnées plus haut dans votre fichier ./patterns/extra.

Pour récupérer l'IP du client, il suffit d'utiliser le motif IP. Pour récupérer le domaine requêté, le motif HOST fait l'affaire.

L'ensemble donne le filtre grok suivant:

"%{BINDT:timestamp} info: client %{IP:ipaddress}#[0-9]{0,5} \(%{HOSTNAME}\): query: %{HOST:domain} IN %{DNSQUERY:query_type}"

Fichier de configuration de logstash

Voici les entrées et le filtre pour Logstash qui correspond à la configuration cible exposée ci-dessus. Nous allons ajouter un type nommé bind pour identifier les logs de bind des autres.

file {
  path => "/home/medspx/projects/ELK/data/bind/request*.log"
  start_position => beginning
  type => "bind"
}

filter {
  # Filtre pour les logs Bind
  if [type] == "bind" {
    # L'intégralité des données du log est récupérée via le motif étudié plus haut
    grok {
        patterns_dir => "./patterns"
        match => { "message" => "%{BINDT:timestamp} info: client %{IP:ipaddress}#[0-9]{5} \(%{HOSTNAME}\): query: %{HOST:domain} IN %{DNSQUERY:query_type}" }
    }
    date {
      match => [ "timestamp", "dd-MMM-YYYY HH:mm:ss.SSS" ]
    }
  }
}

Notez le timestamp pour récupérer la date de l'évènement. La forme dd-MMM-YYYY HH:mm:ss.SSS permet de récupérer l'information à la milliseconde.

Reporting

Introduction

Grâce au filtre logstash précédent, nous disposons de quelques variables que nous allons exploiter. Voici ce que j'ai imaginé:

  • Nombre de requêtes selon le temps.
  • Quels sont les 10 domaines les plus requêtés ?
  • Quels sont les 10 clients qui font le plus de requêtes ?
  • Quels sont les 10 domaines les plus requêtés sur les 10 clients principaux.
  • Ratio requêtes DNS A vs AAAA.
  • Ratio requêtes des principaux réseaux sociaux par rapport à l'ensemble des requêtes.

Comme d'habitude, n'oubliez pas de rafraîchir vos champs (Settings -> Logstash-* -> bouton Refresh).

Métrique: Nombre de requêtes selon le temps

[[!img Erreur: bad image filename]]

Ce métrique est très simple. Voici la recette pour le constituer:

  • Filtre: type:bind
  • Visualize: Aera chart.
  • Buckets: split slices.
  • X-Axis
  • Aggregation: Date Histogram
  • Field: @timestamp
  • Interval: Auto

Métrique: Les 10 domaines les plus requêtés

[[!img Erreur: bad image filename]]

Autre métrique assez simple qui travaille sur le champ domain que nous avons défini dans le filtre Logstash.

  • Filtre: type:bind
  • Visualize: New Pie Chart.
  • Buckets: split slices.
  • Aggregation: Terms
  • Field: domain.raw
  • Order:Top, Size: 10.
  • Order by: metric: Count

Métrique: Les 10 clients qui font le plus de requêtes

[[!img Erreur: bad image filename]]

Autre métrique assez simple qui travaille sur le champ ipaddress que nous avons défini dans le filtre Logstash.

  • Filtre: type:bind
  • Visualize: New Pie Chart.
  • Buckets: split slices.
  • Aggregation: Terms
  • Field: ipaddress.raw
  • Order:Top, Size: 10.
  • Order by: metric: Count

Métrique: Quels sont les 10 domaines les plus requêtés sur les 10 clients principaux

Pour cette mesure, nous allons utiliser une table et les deux champs visualisés précédemment.

  • Filtre: type:bind
  • Visualize: Data Table.
  • Buckets: split rows.
  • Aggregation: Terms
  • Field: ipaddress.raw
  • Order:Top, Size: 10.
  • Order by: metric: Count
  • Add sub-bucket: Split rows.
  • Aggregation: Terms
  • Field: domain.raw
  • Order:Top, Size: 10.
  • Order by: metric: Count
  • Options: Per page : 50.

Métrique: Ratio requêtes DNS A vs AAAA

Ici, nous allons utiliser des filtres...

  • Filtre: type:bind
  • Visualize: New Pie Chart.
  • Buckets: split slices.
  • Aggregation: Filters
  • Filtre 1: query_type:A
  • Filtre 2: query_type:AAAA

Et voilà ! Rien de bien complexe...

Métrique: * Ratio requêtes des principaux réseaux sociaux par rapport à l'ensemble des requêtes

Voici la recette à appliquer:

  • Filtre: type:bind
  • Visualize: New Pie Chart.
  • Buckets: split slices.
  • Aggregation: Filters
  • Filtre 1: domain:facebook OR domain:fb OR domain:twitter
  • Filtre 2: NOT (domain:facebook OR domain:fb OR domain:twitter)

Conclusion

On peut bien entendu ajouter d'autres mesures. En effet, les logs Bind sont une source précieuse pour savoir ce que vos client font sur votre réseau local. Quels sont les domaines les plus visités, quels sont les domaines non valides, quels sont les domaines locaux les plus requêtés, etc.

Avec un peu de réflexion et de fabrication de motifs, on peut tout mettre dans Elasticsearch et faire de beaux diagrammes avec Kibana, comme d'habitude. Attention, les logs Bind sont souvent très volumineux. Ils occasionneront sans doute une grosse charge sur l'instance Logstash qui sera chargée de les traiter. Bien entendu, votre instance Elasticsearch consommera sans doute beaucoup d'espace disque. Mais intégrer les logs Bind est souvent payant pour observer le comportement de vos clients, le jeu en vaut souvent la chandelle. A vous de voir si vous voulez exploiter cette manne !