INTRODUCCIÓN
Ya comenté en el primer capítulo que Windump / TCPDump tiene filtros para su mejor manejo. Estos filtros pueden llegar a ser tan sofisticados como queramos y extraer cualquier tipo de datos de los datagramas, paquetes, etc que circulen a través de nuestra red.
Como la mejor manera de explicar el funcionamiento de los filtros es la práctica, vamos a analizar una combinación y encadenamiento de filtros con un ejemplo muy simple.
Ejemplo
Tenemos el servidor de correos un tanto colapsado, este servidor no aguanta demasiadas conexiones, o el tráfico es mayor de lo previsto. Analicemos entonces qué es lo que pasa.
Vamos a crear un filtro para averiguar las conexiones al puerto 110 de nuestro servidor de correos.
-
C:\scan>windump -qn -X -s 0 tcp[13] = 2 and port 110
Aquí vemos algunas opciones ya comentadas y otras nuevas:
-
–q establecemos el indicador de salida rápida que hará que nos devuelva menos información y que las líneas sean más cortas. Esto es así, porque, en realidad, sólo nos interesa los host/IP y las marcas de tiempo, ya que, como veremos más adelante, estamos filtrando establecimientos de conexión TCP al puerto 110.
-
-n no resolver nombres de host
-
-X vuelca en la consola los datos.
-
-s 0 es el snaplen. A cero estamos cogiendo los paquetes completos. Si hubiéramos puesto -s 512 se capturarían sólo los primeros 512 bytes del paquete tcp.
-
tcp[13] = 2 esta es la parte interesante. Con este filtro estamos diciendo a windump que queremos escoger los paquetes TCP cuyo indicador, bandera o flag sea SYN "S". Para entender esto hay que tener en cuenta cómo es el formato de una cabecera TCP, que los indicadores o flags se encuentran en el octeto 13.
-
and port 110, unido a lo anterior, analizará el puerto 110. Podriamos añadir que lo hiciera sólo para un determinado host:and port 110 and host ALFON.
Vamos a echarle un ojo al octeto 13 y simulemos que el flag SYN está activo, pero antes, recordemos el Formato de la cabecera del TCP.
Formato de la cabecera (header) del TCP:

-
Puerto origen (16 bits). Puerto de la máquina origen. Al igual que el puerto destino es necesario para identificar la conexión actual.
-
Puerto destino (16 bits). Puerto de la máquina destino.
-
Número de secuencia (32 bits). Indica el número de secuencia del primer byte que trasporta el segmento.
-
Número de acuse de recibo (32 bits). Indica el número de secuencia del siguiente byte que se espera recibir. Con este campo se indica al otro extremo de la conexión que los bytes anteriores se han recibido correctamente.
-
Posición de los datos (4 bits). Longitud de la cabecera medida en múltiplos de 32 bits (4 bytes). El valor mínimo de este campo es 5, que corresponde a un segmento sin datos (20 bytes).
-
Reservado (6 bits). Bits reservados para un posible uso futuro.
-
Bits de código o indicadores (6 bits). Los bits de código determinan el propósito y contenido del segmento. A continuación se explica el significado de cada uno de estos bits (mostrados de izquierda a derecha) si está a 1:
URG. El campo Puntero de urgencia contiene información válida.
ACK. El campo Número de acuse de recibo contiene información válida, es decir, el segmento actual lleva un ACK. Observemos que un mismo segmento puede transportar los datos de un sentido y las confirmaciones del otro sentido de la comunicación.
PSH. La aplicación ha solicitado una operación push (enviar los datos existentes en la memoria temporal sin esperar a completar el segmento).
RST. Interrupción de la conexión actual.
SYN. Sincronización de los números de secuencia. Se utiliza al crear una conexión para indicar al otro extremo cual va a ser el primer número de secuencia con el que va a comenzar a transmitir (veremos que no tiene porqué ser el cero).
FIN. Indica al otro extremo que la aplicación ya no tiene más datos para enviar. Se utiliza para solicitar el cierre de la conexión actual.
-
Ventana (16 bits). Número de bytes que el emisor del segmento está dispuesto a aceptar por parte del destino.
-
Suma de verificación (24 bits). Suma de comprobación de errores del segmento actual. Para su cálculo se utiliza una pseudo-cabecera que también incluye las direcciones IP origen y destino.
-
Puntero de urgencia (8 bits). Se utiliza cuando se están enviando datos urgentes que tienen preferencia sobre todos los demás e indica el siguiente byte del campo Datos que sigue a los datos urgentes. Esto le permite al destino identificar donde terminan los datos urgentes. Nótese que un mismo segmento puede contener tanto datos urgentes (al principio) como normales (después de los urgentes).
-
Opciones (variable). Si está presente únicamente se define una opción: el tamaño máximo de segmento que será aceptado.
-
Relleno. Se utiliza para que la longitud de la cabecera sea múltiplo de 32 bits.
-
Datos. Información que envía la aplicación.
|
¿Qué significa realmente tcp[13] = 2?
En el flag SYN, que es utilizado para la sincronización de los números de la secuencia tendremos:
U A P R S F
------------------
0 0 0 0 0 0 1 0 (en binario)
------------------
7 6 5 4 3 2 1 0
vemos que el byte 7 y 6 están reservados, el 5 es para URGENT, el 4 es para ACK, el 3 es para PUSH, el 2 es para RESET y el byte 0 para FIN. Tenemos entonces el octeto completo.
En binario quedaría como acabamos de ver: 0 0 0 0 0 0 1 0, que pasado a base decimal, vemos que es el 2, de ahí viene tcp[13] = 2.
*Es fácil deducir entonces que para detectar un SYN/ACK: 0 0 0 1 0 0 1 0, el 18 en base decimal, entonces tcp[13] = 18.
Lo vemos más claramente en las siguientes líneas.
La teoría
Antes que nada, decir que TCPDump usa el formato: proto[x:y] = valor para leer datos en cabeceras de los protocolos involucrados.
-
proto (protocolo) puede ser ip, arp, rarp, tcp, udp, icmp, etc
-
[x:y] x es el octeto ó byte de comienzo e y significa: "leer" y bytes a partir del byte x
-
Si sólo aparece [x] es lo mismo que decir [x:1], es decir leer sólo el byte x, esto lo hace TCPDump por defecto.
Ya sabemos que significa cada uno de los valores. Vamos entonces a averiguar de dónde sacamos el 13 de la expresión tcp[13] = 2
*por maty: la escala que está encima del dibujo está mal.

Vamos a analizar la cabecera por filas:
-
puerto origen = 2 bytes u octetos o 16 bits
-
puerto destino = 2 bytes u octetos. La cuenta siempre empieza por el 0, con lo cual los octetos van del 0 al 3
-
número secuencia = 4 bytes u octetos, es decir del 4 al 7
-
número acuse recibo = 4 bytes u octetos del 8 al 11
OJO: Tenemos doce octetos (0,1, ...11) Hemos de tener en cuenta que se empieza a contar desde cero, es decir, el primer byte es el octeto 0.
El siguiente octeto es el 12 (el décimo tercero) va desde el bits 0 al 7 que corresponden a posición de datos u offset -4 bits- y a Reservado -4+2-; dos bits de Reservado pertenecen ya al siguiente octeto el 13, que tiene los 2 bits reservados anteriores y 6 que son los flags (UAPRSF). 6 + 2 = 8 bits que es el octeto o byte 13 (o décimo cuarto).
|
Vamos a analizar ahora de dónde viene el valor 2 de la expresión tcp[13] = 2
Esta es la representación de octeto ó byte 13. Si ponemos el flag SYN activado y el resto NO activados, resulta que SYN lo ponemos a 1 y el resto a 0:
Queda entonces: 0 0 0 0 0 0 1 0 (los dos primeros bits dijimos que eran reservados y siempre están a 0)
U A P R S F
------------------
0 0 0 0 0 0 1 0 (en binario)
------------------
7 6 5 4 3 2 1 0
Si pasamos este número (0 0 0 0 0 0 1 0 ), que es binario, a decimal nos queda el número decimal 2 (2 elevado a 1), que es el valor que debemos de introducir para que la expresión quede así:
tcp[13] = 2
Esto le dice a windump o TCPDump que busque en la cabecera TCP el valor 2 que se encuentra en el byte u octeto 13. Y ya sabemos que corresponde al flag SYN activado (y los otros flags/banderas estarán desactivados).
Usando esta técnica, con windump o tcpdump, podríamos detectar escaneos y otras intrusiones en nuestros sistemas.
Siguiendo con el ejemplo práctico y quitando la opción -X que ahora es irrelevante:
-
C:\scan>windump -qn -s 0 tcp[13] = 2 and port 110
windump: listening on\Device\Packet_{604C8AE3-5FAC-45A5-BFAA-81175A8C32BF}
19:11:20.914698 192.168.2.71.1117 > 192.168.4.15.110: tcp 0 (DF)
19:11:22.442635 192.168.4.10.3531 > 192.168.4.15.110: tcp 0 (DF)
19:11:29.321747 192.168.2.90.2310 > 192.168.4.15.110: tcp 0 (DF)
19:11:29.350083 192.168.4.9.1392 > 192.168.4.15.110: tcp 0 (DF)
19:11:30.167786 192.168.2.9.1118 > 192.168.4.15.110: tcp 0 (DF)
19:11:40.848757 192.168.2.90.2311 > 192.168.4.15.110: tcp 0 (DF)
19:11:47.603914 192.168.2.70.1400 > 192.168.4.15.110: tcp 0 (DF)
19:11:48.692990 192.168.4.2.2349 > 192.168.4.15.110: tcp 0 (DF)
19:11:48.946846 192.168.4.2.2350 > 192.168.4.15.110: tcp 0 (DF)
19:11:49.167414 192.168.4.2.2351 > 192.168.4.15.110: tcp 0 (DF)
19:11:53.689934 192.168.4.11.2360 > 192.168.4.15.110: tcp 0 (DF)
19:12:21.576147 192.168.2.71.1118 > 192.168.4.15.110: tcp 0 (DF)
19:12:22.885469 192.168.4.10.3532 > 192.168.4.15.110: tcp 0 (DF)
19:12:29.776688 192.168.2.90.2312 > 192.168.4.15.110: tcp 0 (DF)
19:12:29.799274 192.168.4.9.1393 > 192.168.4.15.110: tcp 0 (DF)
19:12:41.142773 192.168.2.90.2313 > 192.168.4.15.110: tcp 0 (DF)
19:12:42.594882 192.168.4.2.2352 > 192.168.4.15.110: tcp 0 (DF)
19:12:42.828622 192.168.4.2.2353 > 192.168.4.15.110: tcp 0 (DF)
19:12:43.060723 192.168.4.2.2354 > 192.168.4.15.110: tcp 0 (DF)
19:12:47.896352 192.168.2.70.1401 > 192.168.4.15.110: tcp 0 (DF)
Faltan muchas líneas, pero podemos observar en éstas que algunos host tenían sus clientes de correo configurados para "mirar" el correo cada minuto. En la realidad fueron casi todos, con lo cual tenían el servidor bastante atareadillo.
| NOTA: Como nota final decir, para los que me comentan por mail, que el Ethereal es mejor en algunos aspectos por ser gráfico y más intuitivo, pero que tanto Ethereal como TCPDUMP / WINDUMP se basan en la misma librería de captura de paquetes y por tanto para filtrar usan la MISMA sintaxis. Es decir, todo esto que os escribo es válido también para Ethereal. |