Avec Linux iptables, est-il possible d'enregistrer le nom du processus / commande qui initie une connexion sortante?

27

Je voudrais garder une trace des processus qui lancent des connexions sortantes sur un bureau Linux. Le mieux que je puisse trouver est le suivant:

iptables -A OUTPUT -m state --state NEW -j LOG --log-uid

Cela enregistre l'uid / gid qui initie la connexion, mais pas le nom du processus / commande ou même le pid. Si je pouvais simplement obtenir le pid, je pourrais probablement créer un script qui extrait le nom du processus lorsque le journal est écrit, mais il semble que ce ne soit même pas possible.

Idéalement, je voudrais également enregistrer les processus qui acceptent également les connexions entrantes.

Des idées sur la façon dont cela pourrait être possible avec iptables [ou autre chose] sur une boîte Linux?

Nack
la source
Je crois (pas tout à fait sûr) que cette question a été répondue sur serverfault, regardez-la.
niXar
Personnellement, j'utiliserais sysdig pour ce travail.
Charles Duffy

Réponses:

7

Vous pouvez écrire un programme pour surveiller / proc / net / tcp, dont la sortie ressemble à ceci:

obi-wan ~ # cat /proc/net/tcp
  sl  local_address rem_address   st tx_queue rx_queue tr tm->when retrnsmt   uid  timeout inode
   0: 00000000:0050 00000000:0000 0A 00000000:00000000 00:00000000 00000000     0        0 4847458 1 e6060560 300 0 0 2 -1
   1: 00000000:04D2 00000000:0000 0A 00000000:00000000 00:00000000 00000000     0        0 4847477 1 f2e64da0 300 0 0 2 -1
   2: 00000000:0016 00000000:0000 0A 00000000:00000000 00:00000000 00000000     0        0 7109 1 f2e65ac0 300 0 0 2 -1
   3: 0100007F:177A 00000000:0000 0A 00000000:00000000 00:00000000 00000000  1000        0 4864457 1 d2726540 300 0 0 2 -1
   4: 00000000:01BB 00000000:0000 0A 00000000:00000000 00:00000000 00000000     0        0 4847462 1 e60609c0 300 0 0 2 -1
   5: 6B00A8C0:0016 30F4B5CA:C3AB 01 00000044:00000000 01:00000031 00000000     0        0 4982752 3 f2e64940 55 4 0 2 -1
   6: 0100007F:B143 0100007F:BC5E 01 00000000:00000000 00:00000000 00000000  1000        0 2130283 1 d59cce40 21 4 1 2 -1
   7: 0100007F:BC5E 0100007F:B143 01 00000000:00000000 00:00000000 00000000  1000        0 2130285 1 d59cd2a0 21 4 0 2 -1
   8: 6B00A8C0:0016 3276C35B:8E11 01 00000000:00000000 02:000ADAB1 00000000     0        0 4982629 2 d2727260 40 4 8 2 2
   9: 6B00A8C0:0016 6500A8C0:DD5D 01 00000538:00000000 01:00000029 00000000     0        0 4864416 5 e6061b40 42 12 27 3 -1

Vous pouvez ensuite relier les ports ouverts aux inodes, qui peuvent être liés aux processus et aux descripteurs de fichiers en effectuant un lien de lecture sur les descripteurs de fichiers répertoriés pour chaque processus:

obi-wan ~ # readlink /proc/28850/fd/3
socket:[4847458]

Voir ici que l'inode 4847458 correspond au premier socket TCP dans la liste ci-dessus. La sortie de netstat -tapn le vérifie pour moi (et rappelez-vous que 0x50 == 80):

obi-wan ~ # netstat -tapn
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN     28850/cherokee-work

Lorsque le programme du moniteur remarque un changement dans / proc / net / tcp, analysez les données et déterminez si le changement est un socket nouvellement ouvert. Ensuite, vous pouvez simplement énumérer tous les descripteurs de fichiers pour chaque processus répertorié dans / proc, en effectuant un lien de lecture sur chacun pour trouver l'inode correspondant. Une fois que vous avez trouvé cela, vous disposez du pid propriétaire, à partir duquel vous pouvez obtenir tout ce que vous souhaitez, en particulier si vous avez un processus de comptabilité.

Si vous n'avez pas besoin que votre notification soit instantanée, alors votre programme de surveillance pourrait utiliser un sondage lent (peut-être une période de 50 ms ou 100 ms, voire 1000 ms).

Ben Collins
la source
2
Merci d'avoir fourni une option! Mais exiger l'interrogation et l'interrogation de chaque descripteur de fichier ouvert à chaque fois n'est pas très robuste et est très inefficace. J'espère toujours que quelqu'un trouvera une meilleure solution, ou clarifiera pourquoi cela ne fait plus partie d'iptables, et pourquoi --cmd-owner est considéré comme non fixe.
nealmcb
À moins que le noyau ne change sa disposition de / proc ou à moins que netstat et readlink ou ps ne changent (peu probable), je dirais que c'est assez robuste. De quel (s) problème (s) d'efficacité vous préoccupez-vous? Si vous voulez un traitement instantané, vous devrez écrire un module de noyau à utiliser avec iptables.
Ben Collins
Si j'enregistre des connexions rejetées, le socket est immédiatement détruit par le noyau, j'ai donc très peu de chance de le voir dans / proc. Peut-être seulement changer le REJECT en DROP pour que la connexion
expire
Cela n'aide pas dans ce scénario parce que la fenêtre de temps est très petite, mais en ce qui concerne la fragilité de l'analyse / proc, on pourrait également utiliser "lsof -F -i" et obtenir un vidage du réseau bien résumé Les données. Cela peut également être filtré (par exemple, sur un port spécifique), et a déjà fait tout le mappage nom de fichier / pid / utilisateur pour vous.
dannysauer
9

Vous voulez le module de correspondance propriétaire, qui ne fonctionne que sur la chaîne OUTPUT (et peut-être PREROUTING ...?). Lisez les documents, mais cela fonctionnera comme ceci:

iptables --append OUTPUT -m owner --cmd-owner "$app" \
--jump LOG --log-level DEBUG --log-prefix "OUTPUT $app packet died: "

la source
1
Une commande iptables log peut-elle définir et interpoler une variable de cette façon? Cela ne semble pas fonctionner pour moi. De plus, il semble que l'option --cmd-owner ait été supprimée dans le noyau> = 2.6.15. C'est regrettable, car cela semble être une option utile.
4
Oui, --cmd-owner a été supprimé: "unfixable broken"
guettli
1
Merci pour l'info, @guettli. Il y a plus de détails sur permalink.gmane.org/… qui cite plus du journal des modifications : "[NETFILTER]: Supprimez l'abus de tasklist_lock dans le propriétaire d'ipt {, 6}; Extrayez la correspondance cmd / sid / pid depuis qu'elle est cassée et se tient debout la façon de verrouiller les modifications apportées à tasklist_lock. " Mais j'aimerais quand même avoir plus de contexte ou de meilleures alternatives.
nealmcb
5

Rien à voir avec iptables ou la journalisation; mais voici une interface de type "top" qui interroge le répertoire / proc / et affiche la bande passante par programme / pid:

http://sourceforge.net/projects/nethogs

"NetHogs est un petit outil" net top ". Au lieu de répartir le trafic par protocole ou par sous-réseau, comme la plupart des outils, il regroupe la bande passante par processus. NetHogs ne dépend pas d'un module de noyau spécial à charger."

Lokal
la source
J'ai trouvé que nethogs donne des statistiques peu fiables, mais au sommet 2 (+ netatop) fait bien.
Tobu
1

Alors que j'examine une question similaire, en essayant de limiter la vitesse de skype, j'ai trouvé

$ netstat -p | grep <mycmdname>

est un bon moyen de lier le numéro de port à pid / cmd, maintenant que pid-owner / cmd-owner n'est plus directement pris en charge dans iptables; vous devrez ensuite analyser le résultat, puis ajouter la règle iptables en fonction du port; naturellement, vous aurez besoin d'un peu de code de nettoyage après / lors de l'arrêt / redémarrage du système, etc; enregistrer le ou les numéros de port dans un fichier pour référence au moment du nettoyage

en fait, une bonne réponse à la question des numéros de port est

$ sudo netstat -p | grep "tcp.*<mycmdname>" | sed -r "s/.*<MYCOMPUTER>:([0-9]+).*/\1/"`

vous devrez peut-être ajuster l'élément grep tcp en fonction de vos besoins

puis pour mes besoins, il était plus simple d'ajouter des filtres tc u32 en fonction des numéros de port, des entrées iptables en fonction des numéros de port similaires

marque
la source