Python简单UDP服务器无法接收带有IP选项的消息

时间:2019-01-09 17:35:09

标签: sockets udp

我有一个简单的udp服务器/客户端设置,我从客户端发送消息并将其打印在服务器上。这对于常规IP数据包来说效果很好,但是即使我可以使用scapy嗅探数据包,也无法在将IP选项标头添加到数据包时收到该消息。 这是没有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 :(得分:0)

刚刚玩过,下面的代码作为OSX和Linux上的Python 3.7.1的一个独立/最小的工作示例

生成一组有效的IP选项:

spread

(如果您没有Scapy,则上面的代码应生成:fill

客户代码:

from scapy.all import IPOption, raw

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

服务器代码:

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))

在命令行中,或者在Scapy中:

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

由于某种原因,我实际上没有收到OSX下包含IP选项的辅助数据,但是数据显示在数据包嗅探器中。

答案 1 :(得分:0)

问题是由于IPv4校验和不正确所致。我没有在问题中提到我是在具有自定义开关的mininet环境中运行它的。 IP选项通过交换机在传输中添加,但是校验和没有更新。一旦我解决了问题,数据包便将其发送到服务器。

感谢大家的帮助和指点!