Я пишу модуль сетевого фильтра, который глубоко проверяет пакет. Однако во время тестов я обнаружил, что модуль 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-запрос;В облаке Alibaba и некоторых других VPS-провайдерах на основе OpenStack пакет обрезается посередине.
Чтобы проверить это, я выполняю curl http://VPS_IP
на другом VPS и получаю следующий вывод в буфере dmesg:
[ 1163.370483] (XXXX):5007 --> (XXXX):80, len=237, data=451600ED000040003106E3983D87A950AC11D273138F00505A468086B44CE19E80180804269300000101080A1D07500A000D2D90474554202F20485454502F312E310D0A486F73743A2033392E3130372E32342E37370D0A4163636570743A202A2F2A0D0A557365722D4167656E743A204D012000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000001E798090F5FFFF8C0000007B00000000E0678090F5FFFF823000003E00000040AE798090F5FFFF8C0000003E000000000000000000000000000000000000000000000000000000000000
При декодировании результат выглядит примерно так:
![enter image description here](https://i.stack.imgur.com/JKv7m.jpg)
Это совершенно странно, все после User-Agent: M
"пропало"или ноль ред. Хотя skb-> len равен 237, но половина пакета отсутствует.
Есть идеи? Пробовал оба PRE_ROUTING и LOCAL_IN, без изменений.