Ist es unter Linux iptables möglich, den Prozess- / Befehlsnamen zu protokollieren, der eine ausgehende Verbindung initiiert?

27

Ich möchte die Prozesse verfolgen, die ausgehende Verbindungen auf einem Linux-Desktop initiieren. Das Beste, was ich mir einfallen lassen kann, ist Folgendes:

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

Dies protokolliert die UID / GID, die die Verbindung initiiert, aber nicht den Prozess- / Befehlsnamen oder sogar die PID. Wenn ich nur die PID bekommen könnte, könnte ich wahrscheinlich ein Skript erstellen, das den Prozessnamen beim Schreiben des Protokolls abruft, aber es scheint, dass dies nicht einmal möglich ist.

Idealerweise möchte ich auch die Prozesse protokollieren, die auch eingehende Verbindungen akzeptieren.

Irgendwelche Ideen, wie dies mit iptables [oder irgendetwas anderem] auf einer Linux-Box möglich sein könnte?

Nack
quelle
Ich glaube (nicht ganz sicher), diese Frage wurde bei Serverfehler beantwortet, schauen Sie nach.
niXar
Persönlich würde ich sysdig für diesen Job verwenden.
Charles Duffy

Antworten:

7

Sie könnten ein Programm schreiben, um / proc / net / tcp zu überwachen, dessen Ausgabe so aussieht:

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

Sie können dann geöffnete Ports mit Inodes verknüpfen, die mit Prozessen und Dateideskriptoren verknüpft werden können, indem Sie für die für jeden Prozess aufgelisteten Dateideskriptoren einen Readlink ausführen:

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

Sehen Sie hier, dass Inode 4847458 dem ersten TCP-Socket in der obigen Liste entspricht. Die Ausgabe von netstat -tapn überprüft dies für mich (und erinnert daran, dass 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

Wenn das Überwachungsprogramm eine Änderung in / proc / net / tcp feststellt, analysieren Sie die Daten und stellen Sie fest, ob es sich bei der Änderung um einen neu geöffneten Socket handelt. Dann können Sie einfach alle Dateideskriptoren für jeden in / proc aufgelisteten Prozess auflisten und jeweils einen Readlink ausführen, um den passenden Inode zu finden. Sobald Sie dies gefunden haben, haben Sie die PID, von der Sie alles bekommen können, was Sie sich wünschen, besonders wenn Sie über eine Prozessabrechnung verfügen.

Wenn Sie nicht möchten, dass Ihre Benachrichtigung sofort angezeigt wird, kann Ihr Monitorprogramm eine langsame Abfrage verwenden (möglicherweise eine Zeitspanne von 50 ms oder 100 ms oder sogar 1000 ms).

Ben Collins
quelle
2
Vielen Dank für die Bereitstellung einer Option! Es ist jedoch nicht sehr robust und ineffizient, jeden geöffneten Dateideskriptor jedes Mal abzufragen und abzufragen. Ich hoffe immer noch, dass jemand eine bessere Lösung findet oder klärt, warum dies nicht mehr Teil von iptables ist und warum --cmd-owner als unfixble eingestuft wird.
Nealmcb
Wenn der Kernel nicht das Layout von / proc ändert oder wenn sich netstat und readlink oder ps nicht ändern (unwahrscheinlich), würde ich sagen, dass dies recht robust ist. Mit welcher Art von Effizienzproblemen beschäftigen Sie sich? Wenn Sie eine sofortige Verarbeitung wünschen, müssen Sie ein Kernelmodul für die Verwendung mit iptables schreiben.
Ben Collins
Wenn ich abgelehnte Verbindungen protokolliere, wird der Socket sofort vom Kernel zerstört, sodass ich kaum eine Chance habe, ihn in / proc zu sehen. Ändern Sie möglicherweise nur REJECT in DROP, damit die Verbindung
unterbrochen
In diesem Szenario hilft es nicht, das superkleine Zeitfenster zu nutzen, aber was die Fragilität von Parsing / Proc angeht, könnte man auch einfach "lsof -F -i" verwenden und einen schön abstrahierten Speicherauszug des Netzwerks erhalten Daten. Das kann auch gefiltert werden (zum Beispiel nur für einen bestimmten Port) und hat bereits alle Zuordnungen von Dateinamen / PID / Benutzer für Sie vorgenommen.
Dannysauer
9

Sie möchten das Eigentümer-Match-Modul, das nur in der OUTPUT-Kette funktioniert (und möglicherweise PREROUTING ...?). Lesen Sie die Dokumentation, aber es wird ungefähr so ​​funktionieren:

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

quelle
1
Kann ein iptables-Protokollbefehl eine Variable auf diese Weise setzen und interpolieren? Es scheint nicht für mich zu funktionieren. Es sieht auch so aus, als ob die Option --cmd-owner im Kernel> = 2.6.15 entfernt wurde. Das ist bedauerlich, denn es scheint eine nützliche Option zu sein.
4
Ja, --cmd-owner wurde entfernt: "unfixable broken"
guettli
1
Danke für die Info, @guettli. Es gibt weitere Einzelheiten unter permalink.gmane.org/…, die mehr aus dem Changelog zitieren : "[NETFILTER]: Missbrauch von tasklist_lock im ipt {, 6} -Eigentümer entfernen; cmd / sid / pid-Matching herausreißen, da es unfixable broken ist und in steht Die Art des Sperrens ändert sich in tasklist_lock. " Aber ich hätte gerne noch mehr Hintergrundinformationen oder bessere Alternativen.
Nealmcb
5

Nichts mit Iptables oder Protokollierung zu tun; Aber hier ist eine "top" -ähnliche Oberfläche, die das / proc / -Verzeichnis abfragt und die Bandbreite pro Programm / pid anzeigt:

http://sourceforge.net/projects/nethogs

"NetHogs ist ein kleines 'Net Top'-Tool. Anstatt wie die meisten Tools den Datenverkehr nach Protokollen oder Subnetzen aufzuteilen, wird die Bandbreite nach Prozessen gruppiert. NetHogs benötigt kein spezielles Kernel-Modul, das geladen werden soll."

Lokal
quelle
Ich habe herausgefunden, dass Nethogs unzuverlässige Werte liefern, aber Atop 2 (+ Netatop) macht dies gut.
Tobu
1

Als ich mich mit einer ähnlichen Frage befasse und versuche, Skype zu beschleunigen, habe ich herausgefunden

$ netstat -p | grep <mycmdname>

ist eine gute Möglichkeit, die Portnummer mit pid / cmd zu verknüpfen, da pid-owner / cmd-owner in iptables nicht mehr direkt unterstützt werden. Sie müssen dann das Ergebnis analysieren und die iptables-Regel entsprechend dem Port hinzufügen. Natürlich benötigen Sie einen Bereinigungscode nach dem Herunterfahren / Neustarten des Systems usw .; Speichern Sie die Port-Nummer (n) in einer Datei, um sie bei der Bereinigung zu referenzieren

in der Tat ist eine gute Antwort auf die Frage nach den Portnummern

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

Möglicherweise müssen Sie das grep tcp-Element an Ihre Bedürfnisse anpassen

dann war es für meine zwecke am einfachsten, tc u32-filter nach portnummern, iptables-einträge nach portnummern ähnlich hinzuzufügen

Kennzeichen
quelle