Ayant récemment déployé une infrastructure DNS, j'ai été confronté à quelques serveurs Solaris réalisant des requêtes inattendues, et surtout en grand nombre. Malheureusement, obtenir l'identité des processus réalisant ces requêtes n'est pas simple, et il faut donc ruser quelque peu.

DTrace est d'une aide certaine sur ce sujet, mais même avec cet outil, il n'y a pas de solution directe : la résolution de noms n'est pas un appel système que l'on peut tracer simplement, mais est composée d'appel(s) à des librairies, qui sont nettement plus difficiles à tracer, et surtout actuellement impossibles à tracer en dehors du contexte d'un processus. On ne peut donc pas décider simplement de tracer tous les appels à la libresolv du système, par exemple ...

Pour tracer les appels DNS, j'ai donc utilisé une combinaison de deux outils :

  • udpsnoop.d, un script DTrace de Brendan Gregg, l'un des maîtres incontestés de la discipline
  • snoop, pour tracer en parallèle les requêtes DNS

L'outil udpsnoop est censé fournir directement la liste des requêtes UDP émises ou reçues par le serveur, en indiquant le processus concerné, ainsi que les machines sources et destinations avec les ports associés.

Hélas, j'ai rapidement découvert que dans le cas des requêtes DNS, les IP ne sont pas correctement identifiées :

# ./udpsnoop.d UID PID LADDR LPORT DR RADDR RPORT SIZE CMD 0 23291 4.0.0.0 0 -> 255.255.0.0 9 18446744073709551608 nscd 0 23291 4.0.0.0 0 -> 255.255.0.0 9 18446744073709551608 nscd 0 23291 4.0.0.0 0 -> 255.255.0.0 9 18446744073709551608 nscd

C'est donc pour cela que j'utilise snoop en parallèle, avec un filtre permettant de n'afficher que les requêtes m'intéressant, du type :

# snoop -rd e1000g0 host 1.2.3.4 and port 53 1.2.3.100 -> 1.2.3.4 DNS C toto.mondomaine. Internet Addr ? 1.2.3.4 -> 1.2.3.100 DNS R toto.mondomaine. Internet Addr 1.2.3.101

Dans cet exemple, e1000g0 est l'interface de sortie vers le serveur DNS, dont l'IP est 1.2.3.4.

Je peux donc maintenant voir s'afficher de manière synchrone à la fois les requêtes DNS circulant sur le réseau, et les processus générant du trafic UDP. Avec un peu de chance, et surtout s'il n'y a pas trop de trafic, on peut rapidement identifier les processus réalisant ces appels. Notez simplement qu'il y a généralement un petit décalage, chez moi les paquets s'affichent dans snoop avec presque une demi-seconde d'avance sur udpsnoop.

Sauf que ... sauf que dans l'exemple ci-dessus, le seul processus à réaliser des requêtes est le nscd, le cache des services de noms, ce qui est très logique : quand il est actif, la fonctionnalité de requête aux services de noms l'interroge et priorité, et s'il n'a pas l'information, c'est lui qui se charge d'interroger les services concernés. Il nous faut donc le désactiver temporairement :

# svcadm disable name-service-cache

Ceci fait, on peut utiliser udpsnoop correctement et visualiser les noms des processus qui sont réellement à l'origine des demandes, en notant au passage que l'adresse RADDR a ses digits affichés dans l'ordre inverse :

# ./udpsnoop.d UID PID LADDR LPORT DR RADDR RPORT SIZE CMD 2099 13973 4.0.0.0 0 -> 255.255.0.0 9 18446744073709551608 emagent 0 6864 0.0.0.0 32802 -> 100.3.2.1 3207 71 vxpal 0 6935 0.0.0.0 32817 -> 100.3.2.1 3207 71 vxpal 2099 13973 4.0.0.0 0 -> 255.255.0.0 9 18446744073709551608 emagent 0 4970 4.0.0.0 0 -> 255.255.0.0 9 18446744073709551608 vmd 0 4970 4.0.0.0 0 -> 255.255.0.0 9 18446744073709551608 vmd

Et bien entendu, on n'oublie pas à la fin de réactiver le nscd :

# svcadm enable name-service-cache