如何找出数据包的HTTP头长度?

9

我知道如何通过查看十六进制转储来手动完成它。如何自动获得相同的结果?我需要使用API吗?我同时拥有Wireshark和Microsoft网络监视器。


你说的“自动化”是指从应用程序中吗?如果你只是想找出捕获数据中的HTTP头部等部分,Wireshark应该会自动解析数据包。找到任何HTTP数据包,右键单击并选择“跟随TCP流”,它将显示HTTP流量,并清晰可读地显示头部信息。 - Tim Sylvester
@Tim:我想知道HTTP头的字节长度。我可以看到HTTP对话,但是如何将HTTP头长度作为列放置呢? - Bruce
我不知道你所说的“作为一列”的意思。基本上,您需要从HTTP请求的开头到第一个双换行符(\n\n\r\n\r\n)搜索TCP流。找到该位置的索引即为标头的长度。如果您希望在Wireshark中显示此内容,则需要开发插件或类似工具。如果您正在将数据转储到Excel表格或其他地方,则需要按照我所描述的计算长度。 - Tim Sylvester
您可以选择要显示的列:编辑->首选项->用户界面(列)。我该如何开发一个在Wireshark中显示此内容的插件?您能指向一些教程或有用的链接吗? - Bruce
4个回答

10

使用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

非常感谢您的回复。我按照您的步骤走了,但是在数据包描述中找不到HTTP头长度。我正在Windows上工作。 - Bruce
@Bruce:1. 你使用的Wireshark版本是多少?2. 当你进入“工具”菜单时,是否看到了“Lua”子菜单?如果没有,那么Lua被禁用了(在标准安装中默认启用)。3. 只有当数据包包含HTTP头部时,才会在数据包描述中添加HTTP头部长度字段。你确认过了吗? - user568493
@Bruce:顺便说一下,我在Windows XP SP3上的Wireshark 1.4.6上测试了这个脚本。 - user568493
我有Wireshark 1.2.7。我没有看到Lua子菜单。我将重新安装并启用Lua。 - Bruce

2

用户568493发布的代码对我来说根本不起作用,所以我将其改为了后处理器,并且它没有正确计算字节数。它还在计算IP和以太网字节。

这是我修改后的版本,适用于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
不幸的是,尽管您可以创建自定义列,但该列中所需的数据当前并未由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
我发现通过这种方式调用链中的先前解剖者会以某种方式干扰针对“分块”传输编码完成的HTTP数据包重组。也就是说,如果您的响应具有“Transfer-Encoding: chunked”标头,则原始HTTP解剖器尝试重新组装数据,如果您使用此http_wrapper挂钩它,则重新组装失败。
例如,这也使得HTTP统计信息失败。统计/ HTTP /数据包计数器会给出6个请求和4个响应,但事实并非如此=)
人们应该通过“register_postdissector”API调用安装此类“附加值”解剖器,或者仔细测试重组逻辑。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接