web-dev-qa-db-fra.com

Comment puis-je identifier quel processus génère du trafic UDP sous Linux?

Ma machine fait continuellement une demande de trafic DNS udp. ce que je dois savoir, c'est le PID du processus générant ce trafic.

La manière normale dans la connexion TCP est d'utiliser netstat/lsof et d'obtenir le processus associé au pid.

Est UDP la connexion est stateles, donc, quand j'appelle netastat/lsof, je ne peux le voir que si le socket UDP est ouvert et qu'il envoie du trafic.

J'ai essayé avec lsof -i UDP et avec nestat -anpue, mais je ne trouve pas quel processus fait cette demande car j'ai besoin d'appeler lsof/netstat exactement quand le trafic udp est envoyé, si j'appelle lsof/netstat avant/après l'envoi du datagramme udp, il est impossible de voir le ouvert socket UDP.

Appel netstat/lsof exactement quand 3/4 paquet udp est envoyé est IMPOSSIBLE.

Comment puis-je identifier le processus infâme? J'ai déjà inspecté le trafic pour essayer d'identifier le PID envoyé à partir du contenu du paquet, mais il n'est pas possible de l'identifier à partir du contexte du trafic.

Est-ce que quelqu'un peut m'aider ?

Je suis root sur cette machine Fedora 12 Linux noise.company.lan 2.6.32.16-141.fc12.x86_64 # 1 SMP mer 7 juil 04:49:59 UTC 2010 x86_64 x86_64 x86_64 GNU/Linux

39
boos

L'audit Linux peut vous aider. Il localisera au moins les utilisateurs et les processus établissant des connexions réseau de datagrammes. Les paquets UDP sont des datagrammes.

Tout d'abord, installez le framework auditd sur votre plate-forme et assurez-vous que auditctl -l Renvoie quelque chose, même s'il indique qu'aucune règle n'est définie.

Ensuite, ajoutez une règle pour surveiller l'appel système socket() et étiquetez-la pour une recherche facile plus tard (-k). Je dois supposer que vous êtes sur une architecture 64 bits, mais vous pouvez remplacer b32 À la place de b64 Si vous ne l'êtes pas.

auditctl -a exit,always -F Arch=b64 -F a0=2 -F a1\&=2 -S socket -k SOCKET

Vous devez parcourir les pages de manuel et les fichiers d'en-tête pour le créer, mais ce qu'il capture est essentiellement cet appel système: socket(PF_INET, SOCK_DGRAM|X, Y), où le troisième paramètre n'est pas spécifié mais souvent zéro. PF_INET Vaut 2 et SOCK_DGRAM Vaut 2. TCP utiliseraient SOCK_STREAM Qui définirait a1=1. (SOCK_DGRAM Dans le deuxième paramètre peut être OR avec SOCK_NONBLOCK Ou SOCK_CLOEXEC, D'où la comparaison &=.) Le -k SOCKET Est notre mot-clé que nous voulons utiliser lors de la recherche de pistes d'audit plus tard. Cela peut être n'importe quoi, mais j'aime rester simple.

Laissez quelques instants passer en revue les pistes d'audit. Vous pouvez éventuellement forcer quelques paquets en envoyant une requête ping à un hôte sur le net, ce qui entraînera une recherche DNS, qui utilise UDP, ce qui devrait déclencher notre alerte d'audit.

ausearch -i -ts today -k SOCKET

Et une sortie similaire à la section ci-dessous apparaîtra. Je l'abrège pour mettre en évidence les parties importantes

type=SYSCALL ... Arch=x86_64 syscall=socket success=yes exit=1 a0=2 a1=2 ... pid=14510 ... auid=zlagtime uid=zlagtime ... euid=zlagtime ... comm=ping exe=/usr/bin/ping key=SOCKET

Dans la sortie ci-dessus, nous pouvons voir que la commande ping a provoqué l'ouverture du socket. Je pourrais alors exécuter strace -p 14510 Sur le processus, s'il était toujours en cours d'exécution. Le ppid (ID de processus parent) est également répertorié au cas où il s'agirait d'un script qui engendre beaucoup le problème enfant.

Maintenant, si vous avez beaucoup de trafic UDP, cela ne sera pas suffisant et vous devrez recourir à OProfile ou SystemTap , les deux étant actuellement au-delà de mon expertise.

Cela devrait aider à réduire les choses dans le cas général.

Lorsque vous avez terminé, supprimez la règle d'audit en utilisant la même ligne que celle utilisée pour la créer, remplacez uniquement -a Par -d.

auditctl -d exit,always -F Arch=b64 -F a0=2 -F a1\&=2 -S socket -k SOCKET
50
zerolagtime

Vous pouvez utiliser netstat, mais vous avez besoin des bons indicateurs, et cela ne fonctionne que si le processus qui envoie les données est toujours vivant. Il ne trouvera pas les traces de quelque chose qui est venu brièvement à la vie, a envoyé du trafic UDP, puis s'est envolé. Il nécessite également des privilèges root locaux. Cela dit:

Voici moi qui démarre un ncat sur mon hôte local, en envoyant du trafic UDP vers le port 2345 sur une machine (inexistante) 10.11.12.13:

[madhatta@risby]$ ncat -u 10.11.12.13 2345 < /dev/urandom

Voici une sortie tcpdump prouvant que le trafic va:

[root@risby ~]# tcpdump -n -n port 2345
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
12:41:32.391750 IP 192.168.3.11.57550 > 10.11.12.13.2345: UDP, length 8192
12:41:32.399723 IP 192.168.3.11.57550 > 10.11.12.13.2345: UDP, length 8192
12:41:32.401817 IP 192.168.3.11.57550 > 10.11.12.13.2345: UDP, length 8192
12:41:32.407051 IP 192.168.3.11.57550 > 10.11.12.13.2345: UDP, length 8192
12:41:32.413492 IP 192.168.3.11.57550 > 10.11.12.13.2345: UDP, length 8192
12:41:32.417417 IP 192.168.3.11.57550 > 10.11.12.13.2345: UDP, length 8192

Voici le bit utile, en utilisant netstat avec le drapeau -a (pour voir les détails du port) et le drapeau -p pour voir les détails de l'ID de processus. C'est l'indicateur -p qui nécessite des privilèges root:

[root@risby ~]# netstat -apn|grep -w 2345
udp        0      0 192.168.3.11:57550          10.11.12.13:2345            ESTABLISHED 9152/ncat     

Comme vous pouvez le voir, le pid 9152 est considéré comme ayant une connexion ouverte au port 2345 sur l'hôte distant spécifié. Netstat exécute également cela via ps et me dit que le nom du processus est ncat.

J'espère que cela vous sera utile.

23
MadHatter

J'ai eu exactement le même problème et malheureusement auditd n'a pas fait grand chose pour moi.

J'ai eu du trafic provenant de certains de mes serveurs vers des adresses DNS Google, 8.8.8.8 et 8.8.4.4. Maintenant, mon administrateur réseau a un trouble obsessionnel-compulsif léger et il voulait nettoyer tout le trafic inutile puisque nous avons nos caches DNS internes. Il voulait désactiver le port sortant 53 pour tout le monde, à l'exception des serveurs de cache.

Donc, après avoir échoué avec auditctl, je creuse dans systemtap . Je viens avec le script suivant:

# cat >> udp_detect_domain.stp <<EOF
probe udp.sendmsg {
  if ( dport == 53 && daddr == "8.8.8.8" ) {
    printf ("PID %5d (%s) sent UDP to %15s 53\n", pid(), execname(), daddr)
  }
}
EOF

Exécutez ensuite simplement:

stap -v udp_detect_domain.stp

Voici la sortie que j'ai obtenue:

PID  3501 (python) sent UDP to  8.8.8.8 53
PID  3501 (python) sent UDP to  8.8.8.8 53
PID  3506 (python) sent UDP to  8.8.8.8 53

C'est ça! Après avoir changé resolv.conf ces PID n'ont pas détecté les modifications.


J'espère que cela t'aides :)

19
Jakov Sosic

Voici une option systemtap, utilisant les sondes netfilter disponibles dans stap verson 1.8 et versions ultérieures. Voir également man probe::netfilter.ip.local_out.

# stap -e 'probe netfilter.ip.local_out {
  if (dport == 53) # or parametrize
      printf("%s[%d] %s:%d\n", execname(), pid(), daddr, dport)
}'
ping[24738] 192.168.1.10:53
ping[24738] 192.168.1.10:53
^C
5
fche

J'utiliserais un net-sniffer comme tcpdump ou cableshark pour afficher les requêtes DNS. Le contenu de la requête peut donner une idée du programme qui les émet.

4
RedGrittyBrick

Sachez que lorsque vous utilisez autitctl, nscd par exemple utilise un paramètre légèrement différent dans l'appel système de socket, lors d'une requête DNS:

socket(AF_INET, SOCK_DGRAM|SOCK_NONBLOCK, IPPROTO_IP)

Donc, pour vous assurer que vous interceptez ces requêtes en plus de celles qui ont été mentionnées ci-dessus, vous pouvez ajouter un filtre supplémentaire, avec le même nom si vous le souhaitez:

auditctl -a exit,always -F Arch=b64 -F a0=2  -F a1=2050 -S socket -k SOCKET

Ici 2050 est un bit OR de SOCK_DGRAM (2) et SOCK_NONBLOCK (2048).

Ensuite, la recherche trouvera ces deux filtres avec la même clé, SOCKET:

ausearch -i -ts today -k SOCKET

Les valeurs hexadécimales pour les constantes de socket que j'ai trouvées ici: https://golang.org/pkg/syscall/#pkg-constants

Comme je n'ai pas de points de réputation à commenter, j'ai ajouté ceci.

3
Silverfibre