Wie kann ich feststellen, welcher Prozess UDP-Verkehr unter Linux verursacht?

39

Mein Rechner stellt ständig udp dns Verkehrsanfragen. Was ich wissen muss, ist die PID des Prozesses, der diesen Verkehr erzeugt.

Der normale Weg bei einer TCP-Verbindung besteht darin, netstat / lsof zu verwenden und den Prozess an der pid zuzuordnen.

Ist UDP die Verbindung ist stateles, also, wenn ich netastat / lsof anrufe, kann ich es nur sehen, wenn das UDP-Socket geöffnet ist und es Verkehr sendet.

Ich habe mit lsof -i UDPund mit versucht nestat -anpue, aber ich kann nicht finden, welcher Prozess diese Anfrage tut, weil ich lsof / netstat genau dann aufrufen muss, wenn der udp-Verkehr gesendet wird, wenn ich lsof / netstat vor / nach dem Senden des udp-Datagramms aufrufe Der geöffnete UDP-Socket kann nicht angezeigt werden.

Rufen Sie netstat / lsof genau dann auf, wenn ein 3/4 udp-Paket gesendet wird. Dies ist UNMÖGLICH.

Wie kann ich den berüchtigten Prozess identifizieren? Ich habe den Verkehr bereits untersucht, um zu versuchen, die gesendete PID anhand des Inhalts des Pakets zu identifizieren, kann ihn jedoch nicht anhand des Verkehrskontexts identifizieren.

Kann mir jemand helfen?

Ich bin root auf diesem Rechner FEDORA 12 Linux noise.company.lan 2.6.32.16-141.fc12.x86_64 # 1 SMP Mi Jul 7 04:49:59 UTC 2010 x86_64 x86_64 x86_64 GNU / Linux

boos
quelle

Antworten:

48

Linux-Auditing kann helfen. Zumindest werden Benutzer und Prozesse lokalisiert, die Datagramm-Netzwerkverbindungen herstellen. UDP-Pakete sind Datagramme.

Installieren Sie zunächst das auditdFramework auf Ihrer Plattform und stellen Sie sicher, dass auditctl -letwas zurückgegeben wird, auch wenn darin angegeben ist, dass keine Regeln definiert sind.

Fügen Sie dann eine Regel hinzu, um den Systemaufruf zu beobachten, socket()und markieren Sie ihn, um ihn später leichter zu finden ( -k). Ich muss davon ausgehen, dass Sie auf einer 64-Bit-Architektur sind, aber Sie können b32anstelle der ersetzen, b64wenn Sie nicht sind.

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

Sie müssen Manpages und Header-Dateien durchsehen, um dies zu erstellen, aber was es erfasst, ist im Wesentlichen dieser Systemaufruf:, socket(PF_INET, SOCK_DGRAM|X, Y)bei dem der dritte Parameter nicht spezifiziert ist, aber häufig Null. PF_INETist 2 und SOCK_DGRAMist 2. TCP-Verbindungen würden verwenden, SOCK_STREAMdie gesetzt würden a1=1. ( SOCK_DGRAMIm zweiten Parameter kann ODER mit SOCK_NONBLOCKoder angegeben werden SOCK_CLOEXEC, daher der &=Vergleich.) Dies -k SOCKETist unser Schlüsselwort, das wir später bei der Suche nach Prüfpfaden verwenden möchten. Es kann alles sein, aber ich halte es gerne einfach.

Lassen Sie einige Momente verstreichen und überprüfen Sie die Audit-Trails. Optional können Sie ein paar Pakete erzwingen, indem Sie einen Host über das Internet anpingen. Dadurch wird eine DNS-Suche durchgeführt, die UDP verwendet und unsere Überwachungswarnung auslösen sollte.

ausearch -i -ts today -k SOCKET

Die Ausgabe ähnelt dem folgenden Abschnitt. Ich kürze es ab, um die wichtigen Teile hervorzuheben

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

In der obigen Ausgabe können wir sehen, dass der pingBefehl das Öffnen des Sockets verursachte. Ich könnte dann strace -p 14510den Prozess ausführen , wenn er noch läuft. Die ppid(übergeordnete Prozess-ID) wird auch aufgeführt, wenn es sich um ein Skript handelt, das das Problemkind häufig hervorbringt.

Wenn Sie viel UDP-Verkehr haben, wird dies nicht gut genug sein und Sie müssen auf OProfile oder SystemTap zurückgreifen , die beide derzeit außerhalb meines Fachwissens liegen.

Dies sollte helfen, die Situation im Allgemeinen einzugrenzen.

Wenn Sie fertig sind, entfernen Sie die Überwachungsregel, indem Sie dieselbe Zeile verwenden, mit der Sie sie erstellt haben, und ersetzen Sie sie nur -adurch -d.

auditctl -d exit,always -F arch=b64 -F a0=2 -F a1\&=2 -S socket -k SOCKET
Nullzeit
quelle
Ich werde es versuchen, aber ich denke, das ist die richtige Antwort.
Boos
Zumindest für mich nimmt dies keinen Verkehr auf, der von iptables abgeworfen wird.
2. Februar,
1
+1 für die Einfachheit im Vergleich zu der Systemtap-Methode (die analytischer ist, aber Kernel-Entwicklungspakete benötigt)
Basos
23

Sie können netstat verwenden, aber Sie benötigen die richtigen Flags und es funktioniert nur, wenn der Prozess, der die Daten sendet, noch aktiv ist. Es werden keine Spuren von etwas gefunden, das kurz zum Leben erweckt wurde, UDP-Verkehr gesendet hat und dann verschwunden ist. Es erfordert auch lokale Root-Rechte. Das gesagt:

Hier ist, wie ich eine ncat auf meinem lokalen Host starte und UDP-Datenverkehr an Port 2345 auf einem (nicht vorhandenen) Computer 10.11.12.13 schicke:

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

Hier einige tcpdump-Ausgaben, die beweisen, dass der Datenverkehr läuft:

[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

Hier ist das nützliche Bit , das netstat mit dem Flag -a (um Portdetails anzuzeigen) und dem Flag -p verwendet, um Prozess-ID-Details anzuzeigen. Es ist das -p-Flag, für das Root-Rechte erforderlich sind:

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

Wie Sie sehen, hat PID 9152 eine Verbindung zu Port 2345 auf dem angegebenen Remote-Host. Netstat führt dies auch mithilfe von ps aus und teilt mir mit, dass der Prozessname lautet ncat.

Hoffentlich ist das von Nutzen.

MadHatter unterstützt Monica
quelle
Wirklich schön gemacht! : thumbup:
ThorstenS
2
Es gibt jedoch einen Haken. Wenn das Problem durch ein Shell-Skript verursacht wird, das einen Unterprozess erzeugt, der die DNS-Suche durchführt, und dieser Prozess schnell beendet wird, ändert sich der Quellport (57550 oben) ständig. In diesem Fall funktioniert die Technik nicht und Sie müssen drastischere Maßnahmen ergreifen. Darüber hinaus sollte Ihr netstat eine ausgeführt haben, grep -w 57550da mehrere Prozesse DNS-Suchvorgänge auf demselben Server ausführen können. Ihre Methode würde sie nicht unterscheiden.
Zerolagtime
1
Ich bin mit beiden Ihrer Einwände einverstanden, zerolagtime (aber trotzdem danke für Ihre freundlichen Worte, ThorstenS!).
MadHatter unterstützt Monica
17

Ich hatte genau das gleiche Problem und habe leider auditdnicht viel für mich getan.

Ich hatte Datenverkehr von einigen meiner Server in Richtung Google DNS-Adressen 8.8.8.8und 8.8.4.4. Jetzt hat mein Netzwerkadministrator eine leichte Zwangsstörung und wollte den gesamten unnötigen Datenverkehr bereinigen, da wir unsere internen DNS-Caches haben. Er wollte den ausgehenden Port 53 für alle außer diesen Cache-Servern deaktivieren.

Also, nachdem auditctlich versagt habe , beschäftige ich mich mit systemtap. Ich habe folgendes Skript erstellt:

# 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

Dann einfach ausführen:

stap -v udp_detect_domain.stp

Dies ist die Ausgabe, die ich bekam:

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

Das ist es! Nach dem Ändern resolv.confdieser PIDs wurden die Änderungen nicht übernommen.


Hoffe das hilft :)

Jakov Sosic
quelle
5

Hier ist eine Systemtap-Option, die die in Stap Verson 1.8 und höher verfügbaren Netfilter-Probes verwendet. Siehe auch 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
fche
quelle
4

Ich würde einen Net-Sniffer wie tcpdump oder wireshark verwenden, um die DNS-Anforderungen anzuzeigen. Der Inhalt der Abfrage kann eine Vorstellung davon geben, welches Programm sie ausgibt.

RedGrittyBrick
quelle
Keine Informationen im Verkehr schnüffelten ich gerade schon.
Boos
Keine Informationen? Pakete leeren? Was ich meinte war, wenn etwas versucht, updates.java.sun.com oder rss.cnn.com aufzulösen, könnten Sie möglicherweise etwas daraus schließen.
RedGrittyBrick
DNS-Abfrage für die Suche nach dem internen Proxy. im Moment habe ich festgestellt, welcher Prozess ist, aber die Frage ist noch am Leben für eine allgemeine Problemlösungstechnik
Boos
lsof -i | awk '/ UDP /'
c4f4t0r
3

Beachten Sie, dass nscd bei Verwendung von autitctl beispielsweise bei einer DNS-Abfrage einen etwas anderen Parameter im Socket-Systemaufruf verwendet:

socket(AF_INET, SOCK_DGRAM|SOCK_NONBLOCK, IPPROTO_IP)

Um sicherzustellen, dass Sie diese Abfragen zusätzlich zu den oben genannten abfangen, können Sie einen zusätzlichen Filter mit demselben Namen hinzufügen, wenn Sie möchten:

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

Hier ist 2050 ein bitweises ODER von SOCK_DGRAM (2) und SOCK_NONBLOCK (2048).

Die Suche findet dann beide Filter mit demselben Schlüssel SOCKET:

ausearch -i -ts today -k SOCKET

Die Hex-Werte für die Socket-Konstanten habe ich hier gefunden: https://golang.org/pkg/syscall/#pkg-constants

Da ich keine zu kommentierenden Reputationspunkte habe, habe ich dies hinzugefügt.

Silberfaser
quelle