gpt4 book ai didi

linux - netfilter 钩子(Hook)没有检索完整的数据包

转载 作者:太空宇宙 更新时间:2023-11-04 09:58:06 27 4
gpt4 key购买 nike

我正在编写一个 netfilter 模块,用于深入检查数据包。然而,在测试过程中,我发现 netfilter 模块没有接收到完整的数据包。

为了验证这一点,我编写了以下代码来转储在端口 80 上检索到的数据包并将结果写入 dmesg 缓冲区:

const struct iphdr *ip_header = ip_hdr(skb);
if (ip_header->protocol == IPPROTO_TCP)
{
const struct tcphdr *tcp_header = tcp_hdr(skb);
if (ntohs(tcp_header->dest) != 80)
{
return NF_ACCEPT;
}

buff = (char *)kzalloc(skb->len * 10, GFP_KERNEL);
if (buff != NULL)
{
int pos = 0, i = 0;
for (i = 0; i < skb->len; i ++)
{
pos += sprintf(buff + pos, "%02X", skb->data[i] & 0xFF);
}

pr_info("(%pI4):%d --> (%pI4):%d, len=%d, data=%s\n",
&ip_header->saddr,
ntohs(tcp_header->source),
&ip_header->daddr,
ntohs(tcp_header->dest),
skb->len,
buff
);
kfree (buff);
}
}

在本地运行的虚拟机中,我可以检索完整的 HTTP 请求;在阿里云和其他一些基于 OpenStack 的 VPS 提供商上,数据包在中间被切断。

为了验证这一点,我在另一个 VPS 上执行 curl http://VPS_IP,我在 dmesg 缓冲区中得到以下输出:

[ 1163.370483] (XXXX):5007 --> (XXXX):80, len=237, data=451600ED000040003106E3983D87A950AC11D273138F00505A468086B44CE19E80180804269300000101080A1D07500A000D2D90474554202F20485454502F312E310D0A486F73743A2033392E3130372E32342E37370D0A4163636570743A202A2F2A0D0A557365722D4167656E743A204D012000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000001E798090F5FFFF8C0000007B00000000E0678090F5FFFF823000003E00000040AE798090F5FFFF8C0000003E000000000000000000000000000000000000000000000000000000000000

解码后的结果是这样的

enter image description here

这很奇怪,User-Agent: M 之后的所有内容都“消失”或归零。虽然skb->len是237,但是少了一半数据包。

有什么想法吗? PRE_ROUTING 和 LOCAL_IN 都试过了,没有变化。

最佳答案

看起来有时您得到的是线性 skb,有时您的 skb 不是线性的。在后一种情况下,您没有读取 skb 的完整数据内容。

如果 skb->data_len 为零,那么你的 skb 是线性的并且 skb 的完整数据内容在 skb->data 中。如果 skb->data_len 不为零,则您的 skb 不是线性的,并且 skb->data 仅包含数据的第一(线性)部分。这个区域的长度是skb->len - skb->data_lenskb_headlen() 辅助函数计算方便。 skb_is_nonlinear() 辅助函数告诉 skb 是否是线性的。

其余数据可以按此顺序位于分页片段和 skb 片段中。

skb_shinfo(skb)->nr_frags 告诉分页片段的数量。每个分页片段由结构数组 skb_shinfo(skb)->frags[0..skb_shinfo(skb)->nr_frags] 中的数据结构描述。 skb_frag_size()skb_frag_address() 辅助函数有助于处理这些数据。它们接受描述分页片段的结构地址。根据您的内核版本,还有其他有用的辅助函数。

如果分页片段中的数据总大小小于skb->data_len,则其余数据在skb 片段中。它是附加到此 skb 的 skb 列表,位于 skb_shinfo(skb)->frag_list(请参阅内核中的 skb_walk_frags())。

请注意,线性部分可能没有数据和/或分页片段中没有数据。您只需要按照刚才描述的顺序逐条处理数据即可。

关于linux - netfilter 钩子(Hook)没有检索完整的数据包,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58500522/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com