2009-10-07 15 views
7

Si tengo un paquete HTTP grande que se ha dividido en varios paquetes TCP, ¿cómo puedo reconstruirlos de nuevo en un único paquete HTTP? Básicamente, ¿en qué parte del paquete busco saber cuándo está comenzando/finalizando un paquete HTTP? Parece que no veo banderas/campos en el encabezado TCP que indiquen el inicio o el final del paquete HTTP.Reconstrucción de paquete HTTP

EDITAR: En seguimiento de las respuestas. Si TCP administra la transmisión, ¿cómo sabe cuándo comienza y termina la transmisión? ¿Eso está determinado por la apertura y el cierre del socket? Algún protocolo, en algún nivel, debe ser capaz de saber cuándo el flujo/paquete HTTP ha comenzado y terminado. Eso es lo que me gustaría saber.

La situación en la que me encuentro es que estoy usando un analizador de paquetes en C# que lee en paquetes TCP, y me gustaría poder reconstruir las solicitudes HTTP/respuestas/etc. pasando por la interfaz, como cómo se las arregla wireshark y varios otros sniffers. Alternativamente, ¿hay alguna biblioteca C# que te permita acceder a las secuencias HTTP en el nivel superior, ahorrándome tener que reconstruir las secuencias/paquetes HTTP yo mismo?

Gracias.

Respuesta

10

OK He resuelto cómo hacer esto (poco fiable pero hace el trabajo).

Es simple quitar los encabezados de Ethernet, IP y TCP, dejándolo con el mensaje de datos 'en bruto'. Al mirar dentro del mensaje, es fácil detectar si es el inicio de un paquete HTTP al buscar el "HTTP/1.1 ..." al comienzo del paquete. Esto indica que el paquete es el inicio de una secuencia HTTP/paquete más grande/lo que sea. También puede hacer un análisis simple para leer el campo "Contenido-Longitud" que es la longitud total de todo el paquete HTTP.

También puede usar los números de puerto de origen/destino IP & para formar una identificación única para el enlace. Entonces, después de recibir el paquete de encabezado, tome nota de estas 4 cosas (SRCIP, SRCPORT, DESTIP, DESTPORT). La próxima vez que reciba un paquete que coincida con este puerto/combinación IP, puede verificar si es la siguiente parte del paquete HTTP. Puedes usar los números de secuencia para hacer algo de validación y probablemente otras cosas, pero generalmente los paquetes están en orden, así que está bien.Creo que se abre un nuevo puerto para cada flujo HTTP, por lo que no debería recibir paquetes aleatorios que no sean parte de la transmisión, pero podría ser un área propensa a errores.

De todos modos, una vez que recibiste este paquete, una vez más quita los encabezados y recibe el mensaje en bruto. Agréguelo a la parte ya conocida del mensaje. Si la longitud del mensaje total recibido hasta ahora es igual a la longitud leída del campo "Contenido-Longitud", ¡el paquete está completo!

Este método es obviamente propenso a una gran cantidad de errores, pero no me interesa una forma extremadamente robusta de hacerlo. ¡Pensé que respondería mi propia pregunta en caso de que alguien más se encuentre con este mismo problema en el futuro! Buena suerte con su olfateo: D

+2

Si no se especifica el campo Content-Length, hay otras maneras de calcular el tamaño también. p.ej. http://www.httpwatch.com/httpgallery/chunked/ – mike

+2

Podría ser un poco tarde, pero el encabezado 'Content-Length' NO especifica la longitud total del paquete. Simplemente especifica el tamaño del contenido, por lo tanto, el cuerpo, que viene después de los encabezados. Los encabezados y el cuerpo están separados por '\ r \ n \ r \ n'. –

7

No debe utilizar ninguna información del nivel TCP para determinar los límites de solicitud HTTP. TCP proporciona un servicio confiable de flujo de bytes; no puede ver ningún campo o indicador en TCP que ayude con esto porque no están allí.

Para determinar dónde están los límites en una solicitud HTTP, debe seguir RFC 2616. Los límites están bien definidos, y puede determinarlos analizando los datos que recibe.

2

TCP es un protocolo de corriente, no es un protocolo de paquete. La capa de aplicación (es decir, usted) obtiene una secuencia de datos, no un grupo de paquetes. Usted sigue leyendo bytes desde la transmisión y obtendrá toda su carga útil http, mientras que TCP verifica los errores, reenvía, etc. debajo.

4

En cada paquete TCP, el inicio de los datos de la carga útil es inmediatamente posterior al encabezado TCP, y el final de los datos de la carga útil es el final del paquete IP.

El final del encabezado TCP se encuentra fácilmente - el Data Offset es un campo de 4 bits en el encabezado que contiene la longitud del encabezado en palabras de 32 bits (así que multiplíquelo por 4 para obtener la longitud en 8- bit bytes).

Utilice los números de secuencia TCP del campo Sequence para encadenar las cargas útiles juntas en el orden correcto. Tenga en cuenta que puede haber duplicados, en el caso de las retransmisiones.

1

Tuvimos que trabajar para resolver el mismo problema. Pudimos extraer parte de la funcionalidad principal en un proyecto de código abierto.

http://code.google.com/p/pcap-reconst/

Por favor, compruebe hacia fuera y que me haga saber si ayudarte.

+0

Estoy interesado en usar su código. Sin tener que profundizar demasiado en la fuente, ¿maneja su proyecto a) descomprimir datos comprimidos basados ​​en el encabezado 'Content-Encoding', b) convertir a una codificación de texto común basada en' charset' en 'Content-Type' cabecera yc) se ocupa de la codificación fragmentada cuando el encabezado 'Transfer-Encoding' se establece en' chunked'? –

Cuestiones relacionadas