如何在Python中使用原始套接字?

Avi*_*ion 34 python sockets raw-sockets

我正在编写一个应用程序来测试网络驱动程序以处理损坏的数据.我想使用原始套接字发送这些数据,因此发送机器的TCP-IP堆栈不会纠正它.

我只在Linux上编写这个应用程序.我有在系统调用中使用原始套接字的代码示例,但我真的希望尽可能保持测试的动态,并在Python中编写大部分(如果不是全部的话).

我在网上搜索了一些关于在python中使用原始套接字的解释和示例,但是没有找到任何真正有启发性的东西.只是一个非常古老的代码示例来演示这个想法,但绝不是有效的.

从我收集的内容来看,Python中的Raw Socket使用在语义上几乎与UNIX的原始套接字完全相同,但没有struct定义数据包结构的s.

我想知道在Python中编写测试的原始套接字部分是否更好,但在C中使用系统调用,并从主Python代码调用它?

bri*_*ice 44

你这样做:

首先禁用网卡的自动校验和:

sudo ethtool -K eth1 tx off
Run Code Online (Sandbox Code Playgroud)

然后从python 2发送你的狡猾的框架(你必须自己转换为Python 3):

#!/usr/bin/env python
from socket import socket, AF_PACKET, SOCK_RAW
s = socket(AF_PACKET, SOCK_RAW)
s.bind(("eth1", 0))

# We're putting together an ethernet frame here, 
# but you could have anything you want instead
# Have a look at the 'struct' module for more 
# flexible packing/unpacking of binary data
# and 'binascii' for 32 bit CRC
src_addr = "\x01\x02\x03\x04\x05\x06"
dst_addr = "\x01\x02\x03\x04\x05\x06"
payload = ("["*30)+"PAYLOAD"+("]"*30)
checksum = "\x1a\x2b\x3c\x4d"
ethertype = "\x08\x01"

s.send(dst_addr+src_addr+ethertype+payload+checksum)
Run Code Online (Sandbox Code Playgroud)

完成.

  • 我怀疑这是错误的;AF_PACKET 接口不会将校验和部分暴露给用户空间,因此它是由驱动程序/硬件自动生成和检查的,我们对此无能为力。Wireshark 说我发送的“校验和”是“数据”的一部分。 (2认同)
  • 这没有多大意义.在可以处理显式校验和的驱动程序中,如何知道最后的那4个空字节(或任何4个字节,对于那个重要)将被用作校验和?即使字节匹配正确的校验和,这也意味着驱动程序必须计算它,但只有当最后4个字节不是它计算的内容时才将其附加到帧:极不可能且容易出错的行为. (2认同)

Bas*_*ard 10

套接字系统调用(或Windows上的Winsocks)已经包含在标准模块中socket:intro,reference.

我从来没有使用过原始套接字,但看起来它们可以用于这个模块:

最后一个示例显示了如何在Windows上使用原始套接字编写非常简单的网络嗅探器.该示例需要管理员权限才能修改接口:

import socket

# the public network interface
HOST = socket.gethostbyname(socket.gethostname())

# create a raw socket and bind it to the public interface
s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_IP)
s.bind((HOST, 0))

# Include IP headers
s.setsockopt(socket.IPPROTO_IP, socket.IP_HDRINCL, 1)

# receive all packages
s.ioctl(socket.SIO_RCVALL, socket.RCVALL_ON)

# receive a package
print s.recvfrom(65565)

# disabled promiscuous mode
s.ioctl(socket.SIO_RCVALL, socket.RCVALL_OFF)
Run Code Online (Sandbox Code Playgroud)