Comment identifier le processus générant du trafic UDP sous Linux?


39

Ma machine fait continuellement des demandes de trafic udp dns. Ce que j'ai besoin de savoir, c'est le PID du processus générant ce trafic.

Dans la connexion TCP, la méthode normale consiste à utiliser netstat / lsof et à associer le processus au pid.

UDP est la connexion est stateles, donc, lorsque 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 UDPet avec nestat -anpue, mais je ne trouve pas quel processus fait cette demande parce que je dois appeler lsof / netstat exactement quand le trafic udp est envoyé, si j'appelle lsof / netstat avant / après le datagramme udp est envoyé est impossible de voir le socket UDP ouvert.

Appeler netstat / lsof exactement quand 3/4 udp paquet 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 contenu 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 Wed 7 Juillet 04:49:59 UTC 2010 x86_64 x86_64 x86_64 GNU / Linux

Réponses:


48

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

Commencez par installer le auditdframework sur votre plate-forme et assurez-vous qu’il auditctl -lrenvoie quelque chose, même s’il indique qu’aucune règle n’est définie.

Ensuite, ajoutez une règle pour regarder l'appel système socket()et marquez-la pour faciliter la recherche plus tard ( -k). Je dois supposer que vous utilisez une architecture 64 bits, mais vous pouvez le remplacer b32par un autre b64si vous ne l'êtes pas.

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

Vous devez choisir parmi les pages de manuel et les fichiers d’entête pour le construire, mais cela capture essentiellement l’appel système suivant:, socket(PF_INET, SOCK_DGRAM|X, Y)où le troisième paramètre est non spécifié mais souvent nul. PF_INETest 2 et SOCK_DGRAMest 2. Les connexions TCP utiliseraient SOCK_STREAMce qui définirait a1=1. ( SOCK_DGRAMdans le deuxième paramètre, OR peut être associé à SOCK_NONBLOCKou SOCK_CLOEXEC, d’où la &=comparaison). C'est -k SOCKETle mot clé que nous souhaitons utiliser lors de la recherche ultérieure de pistes d'audit. Cela peut être n'importe quoi, mais j'aime rester simple.

Laissez passer quelques instants et passez en revue les pistes d'audit. Vous pouvez éventuellement forcer deux ou trois paquets en envoyant une requête ping à un hôte sur le réseau, ce qui provoquera 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évie 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 pingcommande a provoqué l'ouverture du socket. Je pourrais alors exécuter strace -p 14510le processus s'il fonctionnait toujours. Le ppidcode (ID de processus parent) est également indiqué dans le cas où il s'agirait d'un script qui engendrerait beaucoup l'enfant problématique.

Maintenant, si vous avez beaucoup de trafic UDP, cela ne sera pas suffisant et vous devrez recourir à OProfile ou SystemTap , deux domaines qui dépassent actuellement mon expertise.

Cela devrait aider à préciser 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 -apar -d.

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

Je vais l'essayer, mais je pense que c'est la bonne réponse.
boos

Cela ne capte pas le trafic laissé par iptables, du moins pour moi.
2rs2ts

1
+1 pour la simplicité par rapport à la méthode systemtap (qui est plus analytique, mais nécessite des paquetages de développement du noyau)
basos

23

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 actif. Il ne trouvera pas les traces de quelque chose qui est brièvement apparu, qui a envoyé du trafic UDP, puis est parti. Il nécessite également des privilèges root locaux. Cela dit:

Voici comment démarrer un ncat sur mon hôte local et envoyer du trafic UDP au port 2345 sur une machine (non existante) 10.11.12.13:

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

Voici une sortie de tcpdump prouvant que le trafic est en cours:

[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 l'indicateur -a (pour afficher les détails du port) et l'indicateur -p pour afficher les détails de l'ID de processus. C'est l'indicateur -p qui nécessite les 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 constater, l’identifiant de connexion du pid 9152 est ouvert sur le port 2345 de l’hôte distant spécifié. Netstat gère également cela par le biais de ps et me dit que le nom du processus est ncat.

J'espère que c'est utile.


vraiment sympa fait! : thumbup:
ThorstenS

2
Il y a un piège cependant. Si le problème est causé par un script shell générant un sous-processus qui effectue la recherche DNS et que ce processus se termine rapidement, le port source (57550 ci-dessus) est modifié en permanence. Dans ce cas, la technique ne fonctionnera pas et vous devrez prendre des mesures plus drastiques. En outre, votre netstat aurait dû effectuer une opération grep -w 57550car plusieurs processus pourraient effectuer des recherches DNS sur le même serveur. Votre méthode ne les distinguerait pas.
Zerolagtime

1
Je suis d’accord avec vos deux objections, zerolagtime (mais merci pour vos aimables paroles, ThorstenS!).
MadHatter soutient Monica

17

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

Le trafic de certains de mes serveurs me dirigeait vers des adresses DNS Google 8.8.8.8et 8.8.4.4. Maintenant, mon administrateur réseau a un OCD léger et il voulait nettoyer tout le trafic inutile depuis que nous avons nos caches DNS internes. Il voulait désactiver le port sortant 53 pour tout le monde, sauf pour les 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

Ensuite, lancez simplement:

stap -v udp_detect_domain.stp

Voici le résultat obtenu:

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.confces PID, les changements n'ont pas été repris.


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


5

Voici une option systemap, utilisant les sondes Netfilter disponibles dans les versions 1.8 et supérieures de stap. Voir aussi 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

4

Je voudrais utiliser un net-sniffer comme tcpdump ou Wireshark pour afficher les requêtes DNS. Le contenu de la requête peut donner une idée du programme qui les publie.


aucune information dans le trafic reniflé je viens de voir déjà.
boos

Pas d'information? Des paquets vides? Ce que je voulais dire, c’est que si quelque chose tente de résoudre updates.java.sun.com ou rss.cnn.com, vous pouvez en déduire quelque chose.
RedGrittyBrick

Requête DNS à la recherche du proxy interne. En ce moment, j'ai trouvé quel processus, mais la question reste vive pour une technique générale de résolution de problèmes
boos

lsof -i | awk '/ UDP /'
c4f4t0r

3

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

socket(AF_INET, SOCK_DGRAM|SOCK_NONBLOCK, IPPROTO_IP)

Vous pouvez donc ajouter un filtre supplémentaire, portant le même nom si vous le souhaitez, pour que vous puissiez détecter ces requêtes en plus de celles mentionnées ci-dessus:

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

Ici, 2050 est un OU au niveau des bits 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 aucun point de réputation à commenter, j'ai ajouté ceci.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.