在 Python 中的 tcp 套接字中提取接收到的数据 [英] Extract received data in a tcp socket in Python

查看:54
本文介绍了在 Python 中的 tcp 套接字中提取接收到的数据的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个客户端发送一个带有使用 Scapy 创建的自定义层Reservation"的数据包

I have a client sending a packet with a custom layer "Reservation" created with Scapy

Client.py

#!/usr/bin/env python

import socket
from scapy.all import *


class Reservation(Packet):
    name = "ReservationPacket"
    fields_desc=[ ShortField("id", 0),
            BitField("type",None, 0),
            X3BytesField("update", 0),
            ByteField("rssiap", 0)]


pkt = IP(len=16384, src='192.168.240.5', dst='192.168.240.198',
id=RandShort(), ttl=2)/TCP(sport=5005,
dport=5005, flags="S", window=200,
options=[('MSS', 1460), ('WScale',    2)])/Reservation(id=11)/"HELLO"

spkt = bytes(pkt)
spkt += '\x00'*20

s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_RAW)
s.setsockopt(socket.SOL_IP, socket.IP_HDRINCL, 1)

s.sendto(spkt, ('192.168.240.198', 5005))

s.close()

正确发送和接收数据包.

The packet is correctly sent and received.

如何访问数据包的特定字段?如何解释接收到的数据?我想使用类似于 spkt.id 的东西来检索该字段的值.有没有可能?

How can I access a specific field of the packet? How can I interpret the received data? I would like to use something similar to spkt.id in order to retrieve the value of that field. Is it possible somehow?

编辑我已经到了这一点:我正在通过 tcp 套接字发送 pcaket.它具有以下结构:

EDIT I've reached this point: I am sending a pcaket over a tcp socket. It has the following structure:

###[ IP ]###
  version   = 4
  ihl       = None
  tos       = 0x0
  len       = 16384
  id        = <RandShort>
  flags     = 
  frag      = 0
  ttl       = 2
  proto     = tcp
  chksum    = None
  src       = 192.168.240.5
  dst       = 192.168.240.1
  \options   \
###[ TCP ]###
     sport     = 5005
     dport     = 5005
     seq       = 0
     ack       = 0
     dataofs   = None
     reserved  = 0
     flags     = S
     window    = 200
     chksum    = None
     urgptr    = 0
     options   = [('MSS', 1460), ('WScale', 2)]
###[ ReservationPacket ]###
     id        = 9
     type      = None
     update    = 0x0
     rssiap    = 0 
###[ Raw ]###
      load      = 'PROVA'

其中 ReservationPacket 是自定义层.数据包被接收并带有

Where ReservationPacket is a custom layer. The packet is received and with

    data = conn.recv(BUFFER_SIZE)
    if not data: break
          print "received data:", data
          by = str.encode(data)             
          pkt_hex = by.encode('hex')
          hexdump(by)
          container = IP(data)
          container.show()

我填充了容器包,定义为

I fill the container packet, which is defined as

container = IP()/TCP()/Reservation()

输出

container.show()

###[ IP ]###
version   = 4L
ihl       = 5L
tos       = 0x0
len       = 16384
id        = 56856
flags     = 
frag      = 0L
ttl       = 2
proto     = tcp
chksum    = 0x3987
src       = 192.168.240.5
dst       = 192.168.240.1
\options   \
###[ TCP ]###
 sport     = 5005
 dport     = 5005
 seq       = 0
 ack       = 0
 dataofs   = 7L
 reserved  = 0L
 flags     = S
 window    = 200
 chksum    = 0xd962
 urgptr    = 0
 options   = [('MSS', 1460), ('WScale', 2), ('EOL', None)]
###[ Raw ]###
    load      = '\x00\t\x00\x00\x00\x00PROVA'

显然,Reservation 图层未被识别并解释为 RAW.如何构建与传输的数据包相同的数据包?

Apparently the Reservation layer is not recognized and interpreted as RAW. How can I build the same packet as the one transmitted?

推荐答案

您可以使用 s=str(packet) 在 scapy 2 和 packet=Layer(s) 中序列化一个数据包 强制将字节流反序列化为 Layer.

You can use s=str(packet) to serialize a packet in scapy 2 and packet=Layer(s) to force deserialization of a bytestream as Layer.

在你的情况下:

rdata = sock.recv(8192)
layer = Reservation(rdata)
layer.show()
print layer.id

请注意,您还可以使用 bind_layers() 为 scapys autodissect/payload 猜测绑定层,使其与 sniff() 或 tcp/Reservation 字节流的剖析一起使用(带有保留负载的 tcp 数据包).以下行将 TCP.dport=5005 绑定到 Reservation.

Note that you can also bind your layer for scapys autodissect/payload guessing with bind_layers() to make it work with sniff() or dissection of tcp/Reservation bytestreams (tcp packet with reservation payload). The following line binds TCP.dport=5005 to Reservation.

bind_layers(TCP, Reservation, dport=5005)

更新:您问题的具体答案.

您不必关心 IP/TCP 层,因为这一切都在套接字内处理.socket.recv 接收到的数据是 TCP 的有效载荷,因此你所要做的就是强制 scapy 反序列化接收到的 data作为预订.

You do not have to care about the IP/TCP layer as this is all handled within the socket. The data that is received by socket.recv is the payload to TCP therefore all you have to do is to force scapy to deserialize the received data as Reservation.

TCP 套接字:

data=[]
while True:
    chunk = conn.recv(BUFFER_SIZE)
    if not chunk: 
        break
    print "received data:", chunk
    data.append(chunk)
layer = Reservation(''.join(data))
layer.show()
print layer.id

此外,您可以指示 scapy 尝试根据简单规则自动剖析您的图层,例如TCP.dport==5005 调用 bind_layers().这样,它也适用于 sniff 或当您收到完整的 IP/TCP/Reservation/Raw 字节流时.

Additionally, you can instruct scapy to try to auto-dissect your layer based on a simple rule e.g. TCP.dport==5005 with a call to bind_layers(). This way it will also work with sniff or whenever you receive the full IP/TCP/Reservation/Raw bytestream.

原始套接字:

bind_layers(TCP, Reservation, dport=5005) # bind Reservation as nextlayer to TCP.dport=5005
# ...
data, peer = s.recvfrom(BUFFER_SIZE)
print "received data:", peer, repr(data)
layer = IP(data)                # dissection automagic based on rules registered with bind_layers
layer.show()
print layer[Reservation].id

这篇关于在 Python 中的 tcp 套接字中提取接收到的数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆