Python 简单的 UDP 服务器不接收带有 IP 选项的消息
Python simple UDP server does not receive message with IP options
我有一个简单的 udp server/client 设置,我从客户端发送消息并将其打印在服务器上。这适用于常规 IP 数据包,但当我向数据包添加 IP 选项 header 时未收到消息,即使我可以使用 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 选项的数据包 header:
###[ 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
我已经坚持了几天,如果有人能解决这个问题我会很高兴。
谢谢
刚刚玩过,下面的作品作为我的 self-contained/minimal 工作示例 Python 3.7.1 在 OSX 和 Linux[=17= 下]
正在生成一组有效的 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))
这应该导致 "server" 显示如下行:
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())
出于某种原因,我实际上没有收到 OSX 下包含 IP 选项的辅助数据,但数据显示在数据包嗅探器中。
问题是由于 IPv4 校验和不正确造成的。我没有在问题中提到我 运行 在带有自定义开关的 mininet 环境中。 IP 选项通过交换机在传输过程中添加,但校验和未更新。一旦我解决了这个问题,数据包就会到达服务器。
感谢大家的帮助和指点!
我有一个简单的 udp server/client 设置,我从客户端发送消息并将其打印在服务器上。这适用于常规 IP 数据包,但当我向数据包添加 IP 选项 header 时未收到消息,即使我可以使用 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 选项的数据包 header:
###[ 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
我已经坚持了几天,如果有人能解决这个问题我会很高兴。
谢谢
刚刚玩过,下面的作品作为我的 self-contained/minimal 工作示例 Python 3.7.1 在 OSX 和 Linux[=17= 下]
正在生成一组有效的 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))
这应该导致 "server" 显示如下行:
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())
出于某种原因,我实际上没有收到 OSX 下包含 IP 选项的辅助数据,但数据显示在数据包嗅探器中。
问题是由于 IPv4 校验和不正确造成的。我没有在问题中提到我 运行 在带有自定义开关的 mininet 环境中。 IP 选项通过交换机在传输过程中添加,但校验和未更新。一旦我解决了这个问题,数据包就会到达服务器。
感谢大家的帮助和指点!