Простой UDP-сервер Python не получает сообщения с параметрами IP - PullRequest
0 голосов
/ 09 января 2019

У меня есть простая настройка сервера / клиента udp, когда я отправляю сообщение от клиента и печатаю его на сервере. Это хорошо работает для обычного IP-пакета, но сообщение не получено, когда я добавляю к пакету заголовок параметров IP, хотя я могу прослушать пакет, используя scapy. Вот пакет без опций IP

###[ Ethernet ]###
dst       = 00:04:00:00:04:01
src       = 00:aa:00:02:00:04
type      = 0x800
###[ IP ]###
 version   = 4L
 ihl       = 5L
 tos       = 0x0
 len       = 47
 id        = 1
 flags     =
 frag      = 0L
 ttl       = 61
 proto     = udp
 chksum    = 0x62f4
 src       = 10.0.2.101
 dst       = 10.0.4.101
 \options   \
###[ UDP ]###
    sport     = 10001
    dport     = 3478
    len       = 27
    chksum    = 0x2bd1
###[ Raw ]###
       load      = 'message from a game'

А вот пакет с заголовком параметров IP:

###[ Ethernet ]###
dst       = 00:04:00:00:04:01
src       = 00:aa:00:02:00:04
type      = 0x800
###[ IP ]###
 version   = 4L
 ihl       = 8L
 tos       = 0x0
 len       = 59
 id        = 1
 flags     =
 frag      = 0L
 ttl       = 61
 proto     = udp
 chksum    = 0x5fe8
 src       = 10.0.2.101
 dst       = 10.0.4.101
 \options   \
  |###[ IPOption ]###
  |  copy_flag = 1L
  |  optclass  = control
  |  option    = 31L
  |  length    = 12
  |  value     = '\x00\x01\x00\x00RTGAME'
###[ UDP ]###
    sport     = 10001
    dport     = 3478
    len       = 27
    chksum    = 0x2bd1
###[ Raw ]###
    load      = 'message from a game'

А вот сервер UDP:

sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.bind(('', args.port))

while True:
    try:
        data, addr = sock.recvfrom(1024)
        print("received: %s" % data)
    except KeyboardInterrupt:
        sock.close()
        break

Я застрял на этом в течение нескольких дней и был бы рад, если бы кто-то мог понять это.

Спасибо

Ответы [ 2 ]

0 голосов
/ 10 января 2019

Проблема связана с неверной контрольной суммой IPv4. Я не упомянул в вопросе, что я запускаю это в среде mininet с пользовательскими переключателями. Параметры IP добавляются при передаче коммутатором, но контрольная сумма не обновлялась. Как только я это исправил, пакет попал на сервер.

Спасибо за помощь и всем указателям!

0 голосов
/ 10 января 2019

только что играл, и следующее работает как самостоятельный / минимальный рабочий пример для меня с Python 3.7.1 под OSX и Linux

создание правильного набора параметров IP:

from scapy.all import IPOption, raw

ipopts = raw(IPOption(
    copy_flag=1, optclass='control', option=31,
    value='\x00\x01\x00\x00RTGAME'))

(если у вас нет Scapy, выше должно сгенерироваться: b'\x9f\x0c\x00\x01\x00\x00RTGAME')

код клиента:

import socket
from time import sleep

with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as s:
    s.connect(('127.0.0.1', 3478))
    s.setsockopt(socket.IPPROTO_IP, socket.IP_OPTIONS, ipopts)

    while True:
        s.send(b'message from a game')
        sleep(1)

код сервера:

import socket

with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as s:
    s.bind(('', 3478))
    s.setsockopt(socket.IPPROTO_IP, socket.IP_RECVOPTS, 1)

    while True:
        print(*s.recvmsg(4096, 1024))

это должно привести к тому, что "сервер" отобразит такие строки, как:

b'message from a game\n' [(0, 6, b'\x9f\x0c\x00\x01\x00\x00RTGAME')] 0 ('127.0.0.1', 46047)

Более того, я могу наблюдать за перемещением пакетов по сети, выполнив:

sudo tcpdump -i lo0 -vvv -n 'udp and port 3478'

в командной строке или это в Scapy:

sniff(iface='lo0', filter='udp and port 3478', prn=lambda x: x.show())

по какой-то причине я фактически не получаю вспомогательные данные, содержащие параметры IP в OSX, но эти данные отображаются в анализаторах пакетов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...