libnet создает пакеты UDP с неверными контрольными суммами

Я использую pylibnet для создания и отправки пакетов UDP. Все UDP-пакеты, которые я создаю таким образом, имеют неверные контрольные суммы. Пример:

# python
Python 2.4.3 (#1, Sep  3 2009, 15:37:12)
[GCC 4.1.2 20080704 (Red Hat 4.1.2-46)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> 
>>> import libnet
>>> from libnet.constants import *
>>> 
>>> net = libnet.context(RAW4, 'venet0:0')
>>> ip = net.name2addr4('www.stackoverflow.com', RESOLVE)
>>> data = 'This is my payload.'
>>> udptag = net.build_udp(sp=54321, dp=54321, payload=data)
>>> packetlen = IPV4_H + UDP_H + len(data)
>>> iptag = net.autobuild_ipv4(len=packetlen, prot=IPPROTO_UDP, dst=ip)
>>> 
>>> net.write() 

Захват вышеуказанного пакета на хосте-отправителе показывает неверную контрольную сумму:

# tcpdump -i venet0:0 -n -v -v port 54321
tcpdump: WARNING: arptype 65535 not supported by libpcap - falling back to cooked socket
tcpdump: listening on venet0:0, link-type LINUX_SLL (Linux cooked), capture size 96 bytes
08:16:10.303719 IP (tos 0x0, ttl  64, id 1, offset 0, flags [none], proto: UDP (17), length: 47) 192.168.55.10.54321 > 69.59.196.211.54321: [bad udp cksum 50c3!] UDP, length 0

Я делаю что-то не так здесь?


person Mox    schedule 14.12.2009    source источник


Ответы (3)


Это не связано с ошибками tcpdump или разгрузкой контрольной суммы. Libnet вычисляет контрольную сумму и в пользовательском режиме (к вашему сведению). Проблема связана с тем, что вы не указали длину заголовка UDP. Это не рассчитывается автоматически в pylibnet или libnet, поэтому вам нужно указать это на данный момент. Ниже приведена исправленная версия вашего кода. Я применю патч к pylibnet для автоматического определения длины заголовка в rc6. Следите за обновлениями на http://sourceforge.net/projects/pylibnet. Я буду продвигать новый релиз, исправляющий эту проблему. Кстати, не стесняйтесь обращаться ко мне через страницу pylibnet на sourceforge, если у вас есть вопросы об ошибках или функциях. Мне нравится слышать от разработчиков, использующих мое программное обеспечение :)


import libnet
from libnet.constants import *

net = libnet.context(RAW4, 'venet0:0')
ip = net.name2addr4('www.stackoverflow.com', RESOLVE)
data = 'This is my payload.'
udptag = net.build_udp(len=UDP_H+len(data), sp=54321, dp=54321, payload=data)
packetlen = IPV4_H + UDP_H + len(data)
iptag = net.autobuild_ipv4(len=packetlen, prot=IPPROTO_UDP, dst=ip)

net.write()
person Nadeem Douba    schedule 15.01.2010

Работа по вычислению контрольных сумм обычно выполняется не в пользовательской библиотеке, а в драйвере устройства или аппаратно. Я полагаю, вы видите результат «разгрузки контрольной суммы», когда физическое устройство вычисляет контрольные суммы для исходящих пакетов, экономя циклы ЦП на хосте. Многие (если не все) современные Ethernet-адаптеры так делают, а драйверы не считают контрольную сумму. Так как tcpdump перехватывает пакеты в драйвере, прежде чем они попадут на физическое устройство, он просто получает мусор в поле контрольной суммы (вероятно то, что осталось в буфере) и жалуется.

В период с 2005 по 2008 год сообщалось о нескольких «ошибках» в Wireshark, охватывающих это, и Wireshark (который представляет собой просто оболочку с графическим интерфейсом для tcpdump или его эквивалента Windoze) теперь имеет возможность отключить проверку контрольной суммы для случая разгрузки.

http://wiki.wireshark.org/TCP_Checksum_Verification

В любом случае я бы не ожидал, что pylibnet (или libnet) будет отвечать за контрольные суммы.

См. также http://www.wireshark.org/docs/wsug_html_chunked/ChAdvChecksums.html#id4744523

person Jim Garrison    schedule 14.12.2009
comment
Спасибо. Я только что исследовал это, перехватив эти пакеты на принимающем хосте. Контрольная сумма также неверна на хосте-получателе (и это то же значение, которое наблюдается при перехвате на хосте-отправителе). Таким образом, не похоже, что разгрузка контрольной суммы является ответом здесь. - person Mox; 15.12.2009
comment
Если принимающий хост реализует стандартный стек протоколов или между двумя хостами есть хотя бы один маршрутизатор, пакеты никогда не должны были быть видны на принимающем хосте. Происходит что-то еще. - person Jim Garrison; 16.12.2009

Я обновил pylibnet, чтобы включить автоматическое определение размера полей длины в большинстве заголовков. Таким образом, если вы забудете указать длину заголовка для любого из заголовков, для которых она требуется, он попытается определить ее автоматически. Избавляет вас от головной боли при выяснении, почему ваша контрольная сумма неверна;)

person Nadeem Douba    schedule 22.01.2010
comment
Замечательно. Спасибо за помощь! - person Mox; 22.01.2010