Recherche du processus de propriétaire de connexions TCP de courte durée

15

Fonctionnant tcpdumpsur des connexions locales à un serveur apache, j'ai trouvé des connexions TCP établies et fermées immédiatement toutes les 2 secondes. Comment savoir quel processus en est responsable? netstat -ctpn'a pas aidé, les connexions étaient trop rapides et l'identifiant du processus n'est pas affiché pour TIME_WAIT.

Ils se sont avérés être des sondes haproxy, que j'ai pu vérifier strace, mais je ne connais toujours aucun moyen de localiser haproxy en premier lieu.

pmezard
la source

Réponses:

20

Vous pouvez utiliser le framework auditd pour ce genre de choses. Ils ne sont pas très "conviviaux" ou intuitifs, donc nécessitent un peu de fouille de votre part.

Assurez-vous d'abord que auditd est installé, en cours d'exécution et que votre noyau le prend en charge.
Pour Ubuntu, vous pouvez l'installer avec apt-get install auditdpar exemple.

Ensuite, vous ajoutez une stratégie d'audit pour surveiller tous les connectappels système comme celui-ci:

auditctl -a exit,always -F arch=b64 -S connect -k MYCONNECT

Si vous utilisez une installation 32 bits de Linux, vous devez remplacer b64 par b32.

Cette commande insérera une stratégie dans la structure d'audit et tous les appels système connect () seront désormais enregistrés dans vos fichiers journaux d'audit (généralement /var/log/audit/audit.log) pour que vous puissiez les consulter.

Par exemple, une connexion avec netcat au port 80 de news.ycombinator.com entraînera quelque chose comme ceci:

type=SYSCALL msg=audit(1326872512.453:12752): arch=c000003e syscall=42 success=no exit=-115 a0=3 a1=24e8fa0 a2=10 a3=7fff07a44cd0 items=0 ppid=5675 pid=7270 auid=4294967295 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=pts4 ses=4294967295 comm="nc" exe="/bin/nc.openbsd" key="MYCONNECT"
type=SOCKADDR msg=audit(1326872512.453:12752): saddr=02000050AE84E16A0000000000000000

Ici, vous pouvez voir que l'application /bin/nc.openbsd a initié un appel connect (), si vous recevez beaucoup d'appels de connexion et que vous souhaitez uniquement récupérer un certain ip ou port, vous devez effectuer une conversion. La ligne SOCKADDR contient un argument saddr, il commence par 0200 suivi du numéro de port en hexadécimal (0050) qui signifie 80, puis de l'IP en hexadécimal (AE84E16A) qui est l'IP 174.132.225.106 de news.ycombinator.com.

Le cadre d'audit peut générer de nombreux journaux, alors n'oubliez pas de le désactiver lorsque vous avez accompli votre mission. Pour désactiver la politique ci-dessus, remplacez simplement -a par -d comme tel:

auditctl -d exit,always -F arch=b64 -S connect -k MYCONNECT

Bonne documentation sur le cadre d'auditd:
http://doc.opensuse.org/products/draft/SLES/SLES-security_sd_draft/part.audit.html

Convertissez les adresses IP en hexadécimal, déc, binaire, etc. sur:
http://www.kloth.net/services/iplocate.php

Convertisseur hex / dec général:
http://www.statman.info/conversions/hexadecimal.html

Une brève introduction à auditd, de l'IT Security Stack Exchange. http://security.blogoverflow.com/2013/01/a-brief-introduction-to-auditd/

Edit 1 :
Une autre façon rapide de faire (suédois: fulhack) est de créer une boucle rapide qui vous envoie les données de connexion, comme ceci:

while true;do
  ss -ntap -o state established '( dport = :80 )'
  sleep 1
done

Cette commande utilise la sscommande (statistiques de socket) pour vider les connexions établies actuelles vers le port 80, y compris le processus qui l'a initiée. Si c'est beaucoup de données, vous pouvez ajouter une | tee /tmp/outputfois terminé pour afficher la sortie à l'écran et l'écrire dans / tmp / output pour un traitement / creusage ultérieur. S'il n'attrape pas la connexion haproxy rapide, veuillez essayer de le supprimer, sleep 1mais faites attention à la journalisation extensive s'il s'agit d'une machine très utilisée. Modifiez au besoin!

Mattias Ahnberg
la source
Merci pour la réponse détaillée. Je prendrai votre parole pour la solution auditd car le noyau hôte ne la prend pas en charge et je n'ai pas le temps maintenant d'en trouver une appropriée pour l'expérimentation, mais je garderai cela à l'esprit. En ce qui concerne la solution d'interrogation, j'ai commencé à faire quelque chose de similaire avec lsof mais j'ai arrêté assez rapidement car ce n'était pas ... satisfaisant.
pmezard
2
Vous pouvez également utiliser ausearch -ipour que ces saddrchaînes hexadécimales soient décodées automatiquement pour votre.
sch
ss est plus satisfaisant que lsof car il est plus rapide et il a de bonnes règles de filtrage - pas besoin de grep. Je peux comprendre les problèmes de support: Systemtap est un autre outil qui est superbe mais le faire fonctionner sur un serveur de production peut être ... pas satisfaisant.
Max Murphy
1

Vous pouvez également récupérer les énormes journaux que vous obtenez de "ausearch -i" pour voir uniquement les sockets qui ont réussi à se connecter à un autre hôte sur Internet. J'ai écrit un script simpliste pour obtenir chaque processus et commande qui a créé un socket pour se connecter à un hôte sur Internet avec l'adresse de connexion de cet hôte cible et l'heure actuelle de création du socket. C'est ici:

#!/bin/bash

if [[ $EUID -ne 0 ]]; then

    echo "You must run this script as root boy!"
    exit 1  

fi

> proccessConnections.dat

connections=`ausearch -i | grep host: | awk -F "msg=audit" '{print $2}' | awk -F ": saddr" '{print $1}'`

connectionsNumber=`echo "$connections" | wc -l`

echo "Number of connections: $connectionsNumber"

echo "$connections" > conTemp.dat

let counter=1
while read connectInfo; do

    success=`ausearch -i | grep "$connectInfo" | grep "type=SYSCALL" | grep success=yes`    
    addressInfo=`ausearch -i | grep "$connectInfo" | grep type=SOCKADDR | awk -F ': ' '{print $2}'`
    processInfo=`ausearch -i | grep "$connectInfo" | grep "type=SYSCALL" | awk -F 'comm=' '{print $2}' | awk -F 'key' '{print $1}'` 

    if [[ $success != "" ]]
    then    
        echo "[$counter - $connectionsNumber] (success)     comm=$processInfo - $addressInfo - $connectInfo"
        echo "[$counter - $connectionsNumber] (success)     comm=$processInfo - $addressInfo - $connectInfo" >> proccessConnections.dat
    else
        echo "[$counter - $connectionsNumber] (no success)  comm=$processInfo - $addressInfo - $connectInfo"
        echo "[$counter - $connectionsNumber] (no success)  comm=$processInfo - $addressInfo - $connectInfo" >> proccessConnections.dat
    fi

    let counter++


done < conTemp.dat
Marcelo Silva
la source