GNU/Linux >> Tutoriales Linux >  >> Linux

¿Cómo puedo encontrar el número total de conexiones TCP para un puerto determinado y un período de tiempo por IP?

Encienda iptables y configúrelo en LOG para conexiones entrantes. Regla de ejemplo:

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

(donde 4711 es el puerto que desea rastrear).

Luego ejecute el registro resultante a través de cualquier secuencia de comandos que desee que pueda hacer el resumen por usted.


Puede usar tcpdump para registrar todos los paquetes SYN (sin ACK):

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

o registrar todos los paquetes SYN+ACK (conexiones establecidas):

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

Y luego combínalo con un wc -l para contar todas las líneas

También necesitaría una forma de medir períodos de tiempo fijos (podría hacer que un cron simplemente le envíe un SIGINT a intervalos regulares, tcpdump contará bytes y paquetes pero solo registrará el tiempo)

Actualización:no es necesario decirlo, eche un vistazo a la página de manual de tcpdump y considere usar algunas opciones como:-i (escucha solo una interfaz), -p (deshabilitar el modo promiscuo; menos invasivo), o algunas opciones de salida. Tcpdump necesita permisos de root y es posible que a su jefe no le guste porque es una especie de herramienta de hacker. Por otro lado, no necesita tocar nada en su sistema para ejecutarlo (a diferencia del iptables LOG solución)

Tenga en cuenta también la pequeña diferencia src/dsk en el filtro. Si captura paquetes SYN+ACK y desea contar las conexiones a un servidor en el puerto 4711 necesita src. Si está capturando paquetes SYN+!ACK para obtener el mismo resultado, necesita dst. Si cuentas las conexiones en el propio servidor, siempre tienes que usar el reverso.


Solución SystemTap

Script inspirado en el ejemplo tcp_connections.stp:

#!/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)
    }
  }
}

Salida:

[[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

solución de traza

Inicie el programa bajo strace:

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

o rastrear un programa ya en ejecución:

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

-r imprime una marca de tiempo relativa al ingresar a cada llamada del sistema en caso de que se necesite más tarde para un análisis de rendimiento adicional. -f rastrea los procesos secundarios y es posible que no sea necesario.

La salida se parece a esto:

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

y se puede filtrar con:

# 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

Breve explicación del one-liner de AKW:m[1] es el PID, m[2] es la marca de tiempo, m[3] es el puerto remoto y m[4] es la dirección remota.

La ventaja de esta solución es que no se requiere root si el servidor se ejecuta bajo el mismo usuario. La desventaja es que se cuentan todas las conexiones, no hay filtrado, por lo que no funcionará si la aplicación escucha en varios puertos.


Linux
  1. ¿Cómo encontrar el módulo del kernel para un dispositivo dado?

  2. Cómo encontrar y eliminar archivos anteriores a un período de tiempo particular en Linux

  3. ¿Cómo puede encontrar el número de procesador en el que se está ejecutando un subproceso?

  4. ¿Cómo puedo definir DIRECTORY_SEPARATOR para las plataformas Windows y Linux?

  5. ¿Cómo puedo eliminar el puerto TCP 16969 en Bash?

Cómo encontrar el número de archivos en un directorio y subdirectorios

Cómo encontrar el número de puerto de un servicio en Linux

Cómo encontrar el tamaño total de un directorio en Linux

Cómo encontrar la fecha y hora de instalación del sistema operativo Linux

¿Cómo puedo contar la cantidad de carpetas en una unidad usando Linux?

¿Cómo encuentro los archivos y totalizo sus tamaños?