Как узнать длину HTTP-заголовка пакета? - PullRequest
8 голосов
/ 18 апреля 2011

Я знаю, как это сделать вручную (глядя на шестнадцатеричный дамп). Как я могу получить то же самое автоматически? Нужно ли использовать API? У меня есть и Wireshark, и сетевой монитор Microsoft.

Ответы [ 4 ]

8 голосов
/ 26 апреля 2011

Этого можно достичь просто с помощью диссектора Lua , который добавляет поле заголовка HTTP в дерево пакетов, позволяя фильтровать его, как показано на снимке экрана:

enter image description here

Скопируйте этот скрипт Lua в каталог плагинов (например, ${WIRESHARK_HOME}/plugins/1.4.6/http_extra.lua) и перезапустите Wireshark (если он уже запущен).

do
        local http_wrapper_proto = Proto("http_extra", "Extra analysis of the HTTP protocol");
        http_wrapper_proto.fields.hdr_len = ProtoField.uint32("http.hdr_len", "Header length (bytes)")

        -- HTTP frames that contain a header usually include the HTTP
        -- request method or HTTP response code, so declare those here
        -- so we can check for them later in the dissector.
        local f_req_meth    = Field.new("http.request.method")
        local f_resp_code   = Field.new("http.response.code")

        local original_http_dissector
        function http_wrapper_proto.dissector(tvbuffer, pinfo, treeitem)
                -- We've replaced the original http dissector in the dissector table,
                -- but we still want the original to run, especially because we need 
                -- to read its data. Let's wrap the call in a pcall in order to catch
                -- any unhandled exceptions. We'll ignore those errors.
                pcall(
                    function()
                        original_http_dissector:call(tvbuffer, pinfo, treeitem)
                    end
                )

                -- if the request method or response code is present,
                -- the header must be in this frame
                if f_req_meth() or f_resp_code() then

                        -- find the position of the header terminator (two new lines),
                        -- which indicates the length of the HTTP header, and then add
                        -- the field to the tree (allowing us to filter for it)
                        local hdr_str = tvbuffer():string()
                        local hdr_len = string.find(hdr_str, "\r\n\r\n") or string.find(hdr_str, "\n\n\n\n")
                        if hdr_len ~= nil then
                            treeitem:add(http_wrapper_proto.fields.hdr_len, hdr_len):set_generated()
                        end
                end
        end

        local tcp_dissector_table = DissectorTable.get("tcp.port")
        original_http_dissector = tcp_dissector_table:get_dissector(80) -- save the original dissector so we can still get to it
        tcp_dissector_table:add(80, http_wrapper_proto)                 -- and take its place in the dissector table
end
2 голосов
/ 17 июля 2014

Код, опубликованный user568493, вообще не работал для меня, поэтому я изменил его на почтовый диссектор, а также не правильно подсчитал количество байтов.Он также считал байты IP и Ethernet.

Это моя версия, которая работает на 1.8.2:

local http_wrapper_proto = Proto("http_extra", "Extra analysis of the HTTP protocol");
http_wrapper_proto.fields.hdr_len = ProtoField.uint32("http.hdr_len", "HTTP Header length (bytes)")

-- HTTP frames that contain a header usually include the HTTP
-- request method or HTTP response code, so declare those here
-- so we can check for them later in the dissector.
local f_req_meth    = Field.new("http.request.method")
local f_resp_code   = Field.new("http.response.code")

local original_http_dissector
function http_wrapper_proto.dissector(tvbuffer, pinfo, treeitem)
        -- if the request method or response code is present,
        -- the header must be in this frame
        if f_req_meth() or f_resp_code() then
                local start_offset = 0
                local end_offset = 0
                -- find the position of the header terminator (two new lines),
                -- which indicates the length of the HTTP header, and then add
                -- the field to the tree (allowing us to filter for it)
                local hdr_str = tvbuffer():string()
                if f_req_meth() then
                    start_offset = string.find(hdr_str, "GET")
                    end_offset = string.find(hdr_str, "\r\n\r\n")
                end
                if f_resp_code() then
                    start_offset = string.find(hdr_str, "HTTP")
                    end_offset = string.find(hdr_str, "\r\n\r\n")
                end
                local hdr_len = end_offset - start_offset + 4
                -- 4 Bytes because the \r\n\r\n are not part of the HTTP Payload, hence should be counted in the header length.
                if hdr_len ~= nil then
                    treeitem:add(http_wrapper_proto.fields.hdr_len, hdr_len):set_generated()
                end
        end
end

register_postdissector(http_wrapper_proto)
2 голосов
/ 19 апреля 2011

К сожалению, хотя вы можете создавать пользовательские столбцы, данные, которые вы хотите в этом столбце, в настоящее время не генерируются декодером протокола HTTP.Конечно, могут быть другие инструменты, с которыми я не знаком, которые могут сделать это сегодня, но что касается Wireshark, вам придется добавить эту функциональность.

Есть несколько хороших ресурсов по созданию Wiresharkплагины, например:

http://simeonpilgrim.com/blog/2008/04/29/how-to-build-a-wireshark-plug-in/

http://www.wireshark.org/docs/wsdg_html_chunked/ChDissectAdd.html

http://www.codeproject.com/KB/IP/custom_dissector.aspx

А вот видео, описывающее, как добавить поле, отображаемоедекодер протокола в виде пользовательского столбца:

http://www.youtube.com/watch?v=XpUNXDkfkQg

Дело в том, что вы не хотите повторно реализовывать декодер протокола HTTP.

Что бы я хотелсделать, это найти исходный код для встроенного HTTP-декодера и посмотреть на добавление нового поля, такого как http.header_length так же, как существующее http.content_length:

img

У меня естьЯ не смотрел на код, но я думаю, что это довольно легко добавить.Если вы отправите патч в команду Wireshark, он, вероятно, также включит ваше новое поле в следующую версию.

0 голосов
/ 09 ноября 2011

Я обнаружил, что этот способ вызова предыдущего диссектора в цепочке каким-то образом мешает повторной сборке HTTP-пакета, выполненного для кодирования передачи по частям.То есть, если ваш ответ имеет заголовок «Transfer-Encoding: chunked», оригинальный диссектор HTTP пытается пересобрать данные, и если вы перехватываете его с таким http_wrapper, то повторная сборка завершается неудачно.

Например, это также приводит к сбою статистики http.Статистика / HTTP / Счетчик пакетов даст вам, скажем, 6 запросов и 4 ответа, а это не так =)

Лучше установить такого рода диссекторы с «добавленной стоимостью» с помощью вызова или теста API «register_postdissector»для тщательной сборки логики.

...