2009-10-07 4 views
7

많은 TCP 패킷으로 분할 된 큰 HTTP 패킷이있는 경우 어떻게 단일 HTTP 패킷으로 다시 구성 할 수 있습니까? 기본적으로 패킷에서 HTTP 패킷이 시작/끝나는 시점을 알려줍니다. HTTP 헤더의 시작 또는 끝을 나타내는 TCP 헤더의 플래그/필드를 볼 수 없습니다.HTTP 패킷 재구성

편집 : 후속 회신. TCP가 스트림을 관리하는 경우 스트림 시작 및 종료 시점을 어떻게 알 수 있습니까? 그것은 소켓 열기 및 닫기에 의해 결정됩니까? 어떤 프로토콜은 어떤 레벨에서 HTTP 스트림/패킷이 언제 시작되고 끝나는지를 알 수 있어야합니다. 그것이 내가 알고 싶은 것입니다.

내가 처한 상황은 TCP 패킷을 읽는 C#에서 패킷 스니퍼를 사용하고 있으며 HTTP 요청/응답 /을 재구성 할 수 있기를 바랍니다. wireshark 및 다양한 다른 스니퍼가 관리하는 방식과 같은 인터페이스를 통해 진행됩니다. 또는 더 높은 수준의 HTTP 스트림을 활용할 수있는 C# 라이브러리가있어서 HTTP 스트림/패킷을 직접 재구성하지 않아도됩니까?

감사합니다.

답변

10

나는 이것을하는 방법을 연습했다. (dodgy하지만 일을 끝낸다.)

'원시'데이터 메시지를 남기는 이더넷, IP 및 TCP 헤더를 제거하는 것이 간단합니다. 메시지 안을 살펴보면 패킷 시작 부분에서 "HTTP/1.1 ..."을 찾아서 HTTP 패킷의 시작인지 여부를 쉽게 알 수 있습니다. 이는 패킷이 HTTP 스트림/큰 패킷/시작의 시작임을 나타냅니다. 간단한 구문 분석을 통해 전체 HTTP 패킷의 전체 길이 인 "Content-Length"필드를 읽을 수도 있습니다.

소스/대상 IP & 포트 번호를 사용하여 링크의 고유 ID를 구성 할 수도 있습니다. 따라서 헤더 패킷을받은 후에는 SRCIP, SRCPORT, DESTIP, DESTPORT의 4 가지 사항을 기록하십시오. 다음 번에이 포트/ip 콤보와 일치하는 패킷을 받으면 HTTP 패킷의 다음 부분인지 여부를 확인할 수 있습니다. 시퀀스 번호를 사용하여 유효성 검사 및 기타 작업을 수행 할 수 있지만 일반적으로 패킷은 순서대로되어 있으므로 정상입니다.스트림의 일부가 아닌 임의의 패킷을 수신해서는 안되기 때문에 각 HTTP 스트림마다 새 포트가 열렸지 만 오류가 발생하기 쉬운 영역 일 수 있습니다.

어쨌든,이 패킷을 받으면 헤더를 제거하고 원시 메시지를 얻습니다. 메시지의 이미 알려진 부분에 추가하십시오. 지금까지 수신 된 전체 메시지의 길이가 "Content-Length"필드에서 읽은 길이와 같으면 패킷이 완료됩니다!

이 방법은 분명히 엄청난 양의 오류가 발생하기 쉽지만, 매우 강력합니다. 나는 다른 누군가가 미래에이 같은 문제를 우연히 만났을 때 내 자신의 질문에 대답 할 것이라고 생각했습니다! 냄새를 맡으면서 행운을 빈다 : D

+2

을, 너무 길이를 해결하는 다른 방법이있다. 예 : http://www.httpwatch.com/httpgallery/chunked/ – mike

+2

조금 늦을 수도 있지만'Content-Length' 헤더는 총 패킷 길이를 지정하지 않습니다. 내용의 크기를 지정하기 만하므로 머리글 뒤에 오는 본문을 지정합니다. 머리글과 본문은'\ r \ n \ r \ n'으로 구분됩니다. –

7

HTTP 요청 경계를 결정하기 위해 TCP 수준의 정보를 사용해서는 안됩니다. TCP는 신뢰할 수있는 바이트 스트림 서비스를 제공합니다. 그들이 존재하지 않기 때문에 TCP를 사용하는 데 도움이되는 필드 나 플래그를 볼 수 없습니다.

HTTP 요청에서 경계가있는 곳을 확인하려면 RFC 2616을 따라야합니다. 경계는 잘 정의되어 있으며 수신 한 데이터를 구문 분석하여 경계를 결정할 수 있습니다.

2

TCP는 패킷 프로토콜이 아닌 스트림 프로토콜입니다. 애플리케이션 계층 (즉, 귀하)은 일련의 패킷이 아닌 일련의 데이터를 가져옵니다. 스트림에서 바이트를 계속 읽으면 TCP가 오류 확인, 재전송 등을 수행하는 동안 전체 http 페이로드를 가져옵니다.

4

각 TCP 패킷에서 페이로드 데이터의 시작 부분은 TCP 헤더 바로 뒤에 있고 페이로드 데이터의 끝 부분은 IP 패킷의 끝 부분입니다.

TCP 헤더의 끝은 쉽게 찾을 수 있습니다. Data Offset은 헤더의 길이가 32 비트 단어로 들어있는 4 비트 필드입니다 (따라서 8 비트 길이로 길이를 4로 곱하면됩니다) 비트 바이트).

Sequence 필드의 TCP 시퀀스 번호를 사용하여 페이로드를 올바른 순서로 끈으로 묶습니다. 재전송의 경우에는 중복이있을 수 있습니다.

1

우리는 같은 문제를 해결해야했다. 우리는 오픈 소스 프로젝트에서 몇 가지 핵심 기능을 추출 할 수있었습니다.

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

그것을 확인하고 당신을 도울 경우 알려 주시기 마십시오.

+0

코드 사용에 관심이 있습니다. 소스 코드를 너무 깊이 파지 않고 프로젝트가 a) 'Content-Encoding'헤더를 기반으로 압축 된 데이터를 압축 해제합니다. b) 'Content-Type' 파일의'charset '을 기반으로 일반적인 텍스트 인코딩으로 변환합니다. 헤더와 c)'Transfer-Encoding' 헤더가'chunked'로 설정되었을 때 청크 인코딩을 처리합니까? –

2

당신은 Xplico라는 오픈 소스 프로젝트의 코드를 사용할 수 있습니다 : 콘텐츠 길이 필드가 지정되지 않은 경우 http://www.xplico.org