我正在编写一个应用程序来测试网络驱动程序以处理损坏的数据。我想使用原始套接字发送这些数据,因此发送机器的TCP-IP堆栈不会纠正它。
我只在Linux上编写此应用程序。我有在系统调用中使用原始套接字的代码示例,但我真的希望尽可能保持测试的动态,并在Python中编写大部分(如果不是全部的话)。
我已经在网上搜索了一些关于python中原始套接字使用的解释和示例,但是没有找到任何真正具有启发性的东西。只是一个非常古老的代码示例,它演示了这个想法,但绝不是可行的。
从我收集的内容来看,Python中的Raw Socket使用在语义上几乎与UNIX的原始套接字完全相同,但没有定义数据包结构的struct
。
我想知道在Python中编写测试的原始套接字部分是否更好,但在C中使用系统调用,并从主Python代码中调用它? < / p>
答案 0 :(得分:42)
你这样做:
首先禁用网卡的自动校验和:
sudo ethtool -K eth1 tx off
然后从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)
完成。
答案 1 :(得分: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)
答案 2 :(得分:2)
你提到的旧代码this是否找到了?它对我来说很合理,但我自己没有测试过(或者使用了很多原始套接字)。文档中的This example显示了如何使用原始套接字来嗅探数据包,它看起来很相似。
答案 3 :(得分:2)
最终这个案例的最佳解决方案是用C语言编写整个内容,因为它不是一个很大的应用程序,因此用一种以上的语言编写这么小的东西会受到更大的惩罚。
经过多次使用C和python RAW套接字后,我最终选择了C RAW套接字。 RAW套接字需要少于8位组的位级修改才能写入包头。有时只写4位或更少。 python没有定义任何帮助,而Linux C有一个完整的API。
但是我绝对相信如果只是在python中方便地处理了这一点头文件初始化,我就不会在这里使用C.
答案 4 :(得分:1)
s = socket(AF_PACKET, SOCK_RAW)
s = socket(PF_PACKET, SOCK_RAW)
结果:
[root@localhost python]# tcpdump -i eth0
capture size 96 bytes
11:01:46.850438
01:02:03:04:05:06 (oui Unknown) > 01:02:03:04:05:06 (oui Unknown), ethertype Unknown (0x0801), length 85:
0x0000: 5b5b 5b5b 5b5b 5b5b 5b5b 5b5b 5b5b 5b5b [[[[[[[[[[[[[[[[
0x0010: 5b5b 5b5b 5b5b 5b5b 5b5b 5b5b 5b5b 5041 [[[[[[[[[[[[[[PA
0x0020: 594c 4f41 445d 5d5d 5d5d 5d5d 5d5d 5d5d YLOAD]]]]]]]]]]]
0x0030: 5d5d 5d5d 5d5d 5d5d 5d5d 5d5d 5d5d 5d5d ]]]]]]]]]]]]]]]]
0x0040: 5d5d 5d00 0000 00 ]]]....
答案 5 :(得分:0)
套接字类应该有帮助。如果不是,您需要在C中编写Python模块或只使用C.请参阅http://mail.python.org/pipermail/python-list/2001-April/077454.html。
基本的谷歌搜索发现了。
我实际上尝试过“unwind”指出的代码示例。 AF_PACKET在python 2.7.4中为我工作
答案 6 :(得分:0)
您可以使用以下Python库:rawsocketpy,它允许在第2层上使用原始套接字=>没有IP / TCP / UDP标头。
#!/usr/bin/env python
from rawsocketpy import RawSocket
sock = RawSocket("wlp2s0", 0xEEFA)
sock.send("some data")
sock.send("personal data", dest="\xAA\xBB\xCC\xDD\xEE\xFF")
或服务器形式:
#!/usr/bin/env python
from rawsocketpy import RawRequestHandler, RawAsyncServerCallback
import time
def callback(handler, server):
print("Testing")
handler.setup()
handler.handle()
handler.finish()
class LongTaskTest(RawRequestHandler):
def handle(self):
time.sleep(1)
print(self.packet)
def finish(self):
print("End")
def setup(self):
print("Begin")
def main():
rs = RawAsyncServerCallback("wlp2s0", 0xEEFA, LongTaskTest, callback)
rs.spin()
if __name__ == '__main__':
main()
答案 7 :(得分:0)
FTR,如果您想进行2级访问(以太网,RadioTap ...),则Windows本身将无法实现(截至今天)。
如果您想使用跨平台方法访问它们,则首选为libpcap
及其Python绑定(因为它将在Windows上使用Npcap/WinPcap
)。
您可以在libvcap的各种级别(非常高或非常低)使用各种Python绑定。
我的建议是使用同时实现本机和Libpcap调用的scapy
套接字(即使您不使用它进行剖析)也可以(请选择与conf.use_pcap = True
对抗他们
from scapy.all import conf
# conf.use_pcap = True (will be automatic if required)
socket = conf.L2socket(iface="eth0")
# On any platforms, you have `get_if_list()` in `scapy.all` available, to see the ifaces available. You could also ignore it to use the default one