
Estoy usando "tcpdump" para capturar el tráfico y quiero filtrar por métodos HTTP. Cuando tengo paquetes IPv4, estoy usando: tcpdump -s 0 -A 'tcp[((tcp[12:1] & 0xf0) >> 2):4] = 0x47455420'
Para filtrar paquetes HTTP GET.
Lamentablemente, el tcp[]
filtro no funciona en paquetes IPv6. Según los documentos
La expresión aritmética contra encabezados de capa de transporte, como
tcp[0]
, no funciona con paquetes IPv6.
Entonces estoy buscando otra forma de filtrar solo métodos HTTP para el tráfico IPv6 usando tcpdump.
Intenté buscar una solución, pero parece que incluyen un uso de grep que no es adecuado para mis necesidades, ya que quiero enviar todo el tráfico filtrado directamente a un archivo pcap.
Respuesta1
Limitaciones de tcpdump
IPv6 a partir de las versiones 4.99.x
Para IPv4, para obtener el desplazamiento de la carga útil en el paquete, se puede calcular más o menos el desplazamiento de la carga útil utilizandoEl DIH de IPv4+ Compensación de datos de TCPpara tener en cuenta también las opciones de IPv4 y las opciones de TCP. Esto es lo suficientemente simple como para incluirlo entcpdumpdirectamente cuando genera el filtro de código de bytes BPF (alguna documentación de BPF disponible, por ejemplo)allá).
Para IPv6, en cambio, puede haber un número variable (posiblemente entre 0 y 9) de encabezado de extensión entre el encabezado fijo y el encabezado superior. Eso significaría incluir código para posiblemente 10 casos (0, 1, 2, ... 9 encabezados de extensión) para encontrar el desplazamiento de carga útil en un paquete, asumiendo que no hay peculiaridades adicionales para ciertos casos ni siquiera intentar tener protección contra paquetes con formato incorrecto. (lo que podría dar lugar a una coincidencia falsa positiva): solo puedo asumir que esto no se implementó debido a la complejidad y la falta de voluntad para proporcionar una implementación defectuosa ignorando dichos encabezados.
Incluso una prueba simple como la que ip6 and tcp dst port 80
no considera los encabezados de extensión como se ve en el código BPF generado a continuación:
$ tcpdump --version
tcpdump version 4.99.3
libpcap version 1.10.3 (with TPACKET_V3)
OpenSSL 3.0.9 30 May 2023
$ tcpdump -y EN10MB -d ip6 and tcp dst port 80
(000) ldh [12]
(001) jeq #0x86dd jt 2 jf 7
(002) ldb [20]
(003) jeq #0x6 jt 4 jf 7
(004) ldh [56]
(005) jeq #0x50 jt 6 jf 7
(006) ret #262144
(007) ret #0
entonces puede perder el tráfico.
Parece que a partir de tcpdump 4.99.x, el único lugar donde existe un manejo adecuado de los encabezados de extensión IPv6 está documentado al final de la página de manual:
ip6 proto
Debería perseguir la cadena del encabezado, pero en este momento no lo hace.ip6 protochain
se proporciona para este comportamiento.
De hecho, actualmente a partir de tcpdump 4.99.x ip6 and tcp
es equivalente a ip6 proto 6
(producen el mismo código de bytes):
$ tcpdump -y EN10MB -d ip6 and tcp
(000) ldh [12]
(001) jeq #0x86dd jt 2 jf 8
(002) ldb [20]
(003) jeq #0x6 jt 7 jf 4
(004) jeq #0x2c jt 5 jf 8
(005) ldb [54]
(006) jeq #0x6 jt 7 jf 8
(007) ret #262144
(008) ret #0
while ip6 protochain 6
realiza una verificación mucho más exhaustiva y sería lo que se debería esperar en cualquier prueba que involucre una capa superior (encabezado de transporte final) como TCP:
$ tcpdump -y EN10MB -d ip6 protochain 6
(000) ldh [12]
(001) jeq #0x86dd jt 2 jf 35
(002) ldb [20]
(003) ldx #0x28
(004) jeq #0x6 jt 32 jf 5
(005) jeq #0x3b jt 32 jf 6
(006) jeq #0x0 jt 10 jf 7
(007) jeq #0x3c jt 10 jf 8
(008) jeq #0x2b jt 10 jf 9
(009) jeq #0x2c jt 10 jf 19
(010) ldb [x + 14]
(011) st M[0]
(012) ldb [x + 15]
(013) add #1
(014) mul #8
(015) add x
(016) tax
(017) ld M[0]
(018) ja 4
(019) jeq #0x33 jt 20 jf 32
(020) txa
(021) ldb [x + 14]
(022) st M[0]
(023) txa
(024) add #1
(025) tax
(026) ldb [x + 14]
(027) add #2
(028) mul #4
(029) tax
(030) ld M[0]
(031) ja 4
(032) add #0
(033) jeq #0x6 jt 34 jf 35
(034) ret #262144
(035) ret #0
Arriba de las 4 pruebas que incluyen jt 10
y líneas entre (10
) y (018) ja 4
recorra 4 de los encabezados de extensión IPv6 específicos para omitirlos, mientras (19)
se (31)
ocupa de IPSec AH. No sabría cómo generar ese código en otro lugar con eltcpdumplenguaje (en lugar de, digamos, directoBPFcódigo). El uso ip6 protochain 6 and ip6 and tcp dst port 80
simplemente comienza desde cero, o algo peor, en lugar de aprovechar el encabezado TCP recién obtenido.
El mismo tipo de problema se describe en varias instalaciones y herramientas de red para Linux. Ejemplo:tc u32
dice:
icmp_code
VAL_MASK_8Suponga un protocolo de encabezado siguiente de icmp o ipv6-icmp y haga coincidir los valores del campo Tipo o Código.Esto es peligroso, como supone el código.tamaño mínimo de encabezado para IPv4 yfalta de encabezados de extensión para IPv6.
Todo esto ni siquiera considera que específicamente para HTTP, cuando se reutiliza la conexión, la siguiente consulta HTTP podría ni siquiera estar en el inicio de un límite de paquete, o también que dicha consulta incrustada como datos en lugar de consulta podría coincidir si dichos datos Aparece al inicio del límite del paquete.
Pruebe el caso de encabezado de extensión 0 usando tcpdump
la versión 4.99.x
Aquí está la prueba con 0 encabezados de extensión, es decir, al mismo nivel de lo quetcpdumpactualmente lo hace, con una verificación mínima realizada:
tcpdump -n -s 0 -A 'ip6[6] == 6 and ( ip6[4:2] - ((ip6[52] & 0xf0) >> 2) >= 4 ) and ip6[40 + ((ip6[52] & 0xf0) >> 2) :4] == 0x47455420'
que se puede documentar así (aún solo para el caso de encabezado de extensión 0, donde el encabezado TCP siempre comienza en la posición 40):
El siguiente encabezado es TCP
ip6[6] == 6
IPv6longitud de carga útil:
ip6[4:2]
tcpdesplazamiento de datos (tamaño de IPv6 fijo de 40 + 12 = 52) (y ajuste adecuado para obtener bytes)
(ip6[52] & 0xf0) >> 2
Longitud de la carga útil TCP = longitud de la carga útil IPv6 - desplazamiento de datos TCP
Pruebe que haya al menos 4 bytes de carga útil TCP para al menos la longitud de "GET"
ip6[4:2] - ((ip6[52] & 0xf0) >> 2) >= 4
la cadena de 4 bytes "GET" codificada en ASCII/UTF-8 se puede representar con el valor de 4 bytes 0x47455420
El desplazamiento de la carga útil de TCP es la longitud fija del encabezado IPv6 (40) + el desplazamiento de datos de TCP
40 + ((ip6[52] & 0xf0) >> 2)
Pruebe que la primera palabra de 4 bytes que comienza en la longitud fija del encabezado IPv6 (40) + desplazamiento de datos sea igual al valor de la cadena "GET"
ip6[40 + ((ip6[52] & 0xf0) >> 2) :4] = 0x47455420
nftablescon kernel Linux >= 5.15.54 +tcpdump
Propongo un método alternativo simple solo para Linux usandonftablesy requiere un kernel lo suficientemente reciente (versión del kernel de Linux>= 5.15.54respaldado desde5.16) así comonftables>= 1.0.1para apoyar el@ih
(encabezado interno/carga útil) carga útil sin procesar, en lugar de solo @th
(encabezado de transporte) porquenftablesen sí mismo es demasiado limitado para realizar un procesamiento arbitrario de @th
manera útil.
El datagrama IPv6 ya ha sido analizado, incluido cualquier encabezado de extensión IPv6, y los punteros @th y @in ya están disponibles paranftables: no es necesario ningún procesamiento adicional para obtener todos los casos. confío ennftablesfallar una verificación si el paquete es demasiado corto sin tener que calcular el tamaño de carga útil TCP real (al contrario detcpdumpy BPF,nftablesNo puedo hacer restas, por lo que no hay forma de comprobar el tamaño correctamente).
ElnftablesEl siguiente ejemplo intenta imitar el ejemplo preciso de OP, pero no siempre puede hacerlo en todos los detalles sin alguna adaptación. Sin dirección ni puerto, captura los paquetes entrantes antes de NAT y los paquetes salientes después de NAT (de ahí los enlaces y prioridades elegidos). El paquete seleccionado finalmente esenviado alnfloginstalación:
En la segunda forma de invocación (sigrupo_nflogse especifica), el kernel de Linux pasará el paquete a nfnetlink_log, que enviará el registro a través de un socket netlink al grupo especificado. Un proceso de espacio de usuario puede suscribirse al grupo para recibir los registros [...]
table ip6 special_log
delete table ip6 special_log
table ip6 special_log {
chain log_to_nflog {
log group 4242
}
chain ih_filter {
meta l4proto tcp @ih,0,32 0x47455420 counter jump log_to_nflog
}
chain c_ingress {
type filter hook prerouting priority -150; policy accept;
jump ih_filter
}
chain c_egress {
type filter hook postrouting priority 150; policy accept;
jump ih_filter
}
}
En Linux, elnflogLa instalación está disponible como una pseudointerfaz para (libcapy)tcpdump:
# tcpdump -D |grep nflog
12.nflog (Linux netfilter log (NFLOG) interface) [none]
Los paquetes seleccionados pornftablesPor lo tanto, se puede mostrar con (reutilizando el mismo grupo NFLLOG: 4242):
tcpdump -n -s 0 -A -i nflog:4242
Advertencia: hay más latencia que con una captura directa.
Nota: manejo correcto pornftablesde un caso que tenía un encabezado de extensión en realidad se probó con UDP (en lugar de TCP) y paquetes fragmentados (manejados por elencabezado de fragmento) usando socat
(en un espacio de nombres de red separado para evitar nf_defrag_ipv6
que se active) porque es mucho más fácil generar un paquete fragmentado con UDP que con TCP y no encontré otro método para tener un encabezado de extensión en alguna parte.