GNU/Linux >> LINUX-Kenntnisse >  >> Linux

Wie kann ich die Gesamtzahl der TCP-Verbindungen für einen bestimmten Port und Zeitraum nach IP ermitteln?

Schalten Sie iptables ein und setzen Sie es auf LOG für eingehende Verbindungen. Beispielregel:

 -A INPUT --state NEW -p tcp --dport 4711 -j LOG

(wobei 4711 der Port ist, den Sie verfolgen möchten).

Führen Sie dann das resultierende Protokoll durch ein beliebiges Skript, das die Zusammenfassung für Sie erledigen kann.


Sie können tcpdump verwenden, um alle SYN-Pakete (ohne ACK) zu protokollieren:

tcpdump "dst port 4711 and tcp[tcpflags] & (tcp-syn|tcp-ack) == tcp-syn"

oder alle SYN+ACK-Pakete (aufgebaute Verbindungen) protokollieren:

tcpdump "src port 4711 and tcp[tcpflags] & (tcp-syn|tcp-ack) == (tcp-syn|tcp-ack)"

Und dann kombiniere es mit einem wc -l um alle Zeilen zu zählen

Sie brauchen auch eine Möglichkeit, feste Zeiträume zu messen (Sie könnten einen Cron haben, der ihm in regelmäßigen Abständen einfach ein SIGINT sendet, tcpdump zählt Bytes und Pakete, protokolliert aber nur die Zeit)

Update:Unnötig zu sagen, schauen Sie sich die Manpage von tcpdump an und erwägen Sie die Verwendung einiger Optionen wie:-i (nur eine Schnittstelle hören), -p (Promiskuitiver Modus deaktivieren; weniger invasiv) oder einige Ausgabeoptionen. Tcpdump benötigt Root-Berechtigungen und Ihr Chef mag es vielleicht nicht, weil es eine Art Hacker-Tool ist. Andererseits müssen Sie nichts an Ihrem System anfassen, um es auszuführen (im Gegensatz zum iptables LOG Lösung)

Bitte beachten Sie auch den kleinen src/dsk-Unterschied im Filter. Wenn Sie SYN+ACK-Pakete abfangen und Verbindungen zu zählen möchten einen Server auf Port 4711 benötigen Sie src. Wenn Sie SYN+!ACK-Pakete für dasselbe Ergebnis abfangen, benötigen Sie dst. Wenn Sie Verbindungen auf dem Server selbst zählen, müssen Sie immer das Gegenteil verwenden.


SystemTap-Lösung

Vom Beispiel tcp_connections.stp inspiriertes Skript:

#!/usr/bin/env stap
# To monitor another TCP port run:
#     stap -G port=80 tcp_connections.stp
# or
#     ./tcp_connections.stp -G port=80
global port = 22
global connections

function report() {
  foreach (addr in connections) {
    printf("%s: %d\n", addr, @count(connections[addr]))
  }
}

probe end {
  printf("\n=== Summary ===\n")
  report()
}

probe kernel.function("tcp_accept").return?,
      kernel.function("inet_csk_accept").return? {
  sock = $return
  if (sock != 0) {
    local_port = inet_get_local_port(sock)
    if (local_port == port) {
      remote_addr = inet_get_ip_source(sock)
      connections[remote_addr] <<< 1
      printf("%s New connection from %s\n", ctime(gettimeofday_s()), remote_addr)
    }
  }
}

Ausgabe:

[[email protected] ~]# ./tcp_connections.stp -G port=80
Mon Mar 17 04:13:03 2014 New connection from 192.168.122.1
Mon Mar 17 04:13:04 2014 New connection from 192.168.122.1
Mon Mar 17 04:13:08 2014 New connection from 192.168.122.4
^C
=== Summary ===
192.168.122.1: 2
192.168.122.4: 1

Strace-Lösung

Starten Sie das Programm entweder unter strace:

strace -r -f -e trace=accept -o /tmp/strace ${PROGRAM} ${ARGS}

oder verfolgen Sie ein bereits laufendes Programm:

strace -r -f -e trace=accept -o /tmp/strace -p ${PID_OF_PROGRAM}

-r druckt einen relativen Zeitstempel beim Eintritt in jeden Systemaufruf, falls er später für eine zusätzliche Leistungsanalyse benötigt wird. -f verfolgt untergeordnete Prozesse und wird möglicherweise nicht benötigt.

Die Ausgabe sieht in etwa so aus:

999        0.000000 accept(3, {sa_family=AF_INET, sin_port=htons(34702), sin_addr=inet_addr("192.168.122.4")}, [16]) = 5
999        0.008079 --- SIGCHLD (Child exited) @ 0 (0) ---
999        1.029846 accept(3, {sa_family=AF_INET, sin_port=htons(34703), sin_addr=inet_addr("192.168.122.4")}, [16]) = 5
999        0.008276 --- SIGCHLD (Child exited) @ 0 (0) ---
999        3.580122 accept(3, {sa_family=AF_INET, sin_port=htons(50114), sin_addr=inet_addr("192.168.122.1")}, [16]) = 5

und kann gefiltert werden mit:

# gawk 'match($0, /^([0-9]+)[[:space:]]+([0-9.]+)[[:space:]]+accept\(.*htons\(([^)]+)\),.*inet_addr\("([^"]+)"\).*[[:space:]]+=[[:space:]]+([1-9][0-9]*)/, m) {connections[m[4]]++} END {for (addr in connections) printf("%s: %d\n", addr, connections[addr]); }' /tmp/strace
192.168.122.4: 3
192.168.122.1: 2

Kurze Erläuterung des AKW-Einzeilers:m[1] ist die PID, m[2] ist der Zeitstempel, m[3] ist der entfernte Port und m[4] ist die entfernte Adresse.

Der Vorteil dieser Lösung ist, dass root nicht erforderlich ist, wenn der Server unter demselben Benutzer läuft. Der Nachteil ist, dass alle Verbindungen gezählt werden, es gibt keine Filterung, also funktioniert es nicht, wenn die Anwendung auf mehreren Ports lauscht.


Linux
  1. So finden und löschen Sie Dateien, die älter als ein bestimmter Zeitraum in Linux sind

  2. Wie können Sie die Prozessornummer finden, auf der ein Thread läuft?

  3. Wo kann ich die Abhängigkeiten für Pygame finden und installieren?

  4. Wie kann ich den TCP-Port 16969 in Bash beenden?

  5. Wie kann ich das aktuelle Datum und die aktuelle Uhrzeit im Terminal abrufen und einen benutzerdefinierten Befehl im Terminal dafür festlegen?

So finden Sie die Portnummer eines Dienstes in Linux

So ermitteln Sie die Gesamtgröße eines Verzeichnisses in Linux

So finden Sie das Installationsdatum und die Uhrzeit des Linux-Betriebssystems

Wie finde ich das Kernel-Modul für ein bestimmtes Gerät?

Wie funktioniert der Mülleimer und wo finde ich die offizielle Dokumentation, Referenz oder Spezifikation dafür?

Wie kann ich den DIRECTORY_SEPARATOR sowohl für Windows- als auch für Linux-Plattformen definieren?