Python原始套接字到以太网接口(Windows)
我正在尝试创建一个DHCP服务器,第一步是通过以太网端口发送数据包。我试图将数据包发送到我的以太网接口,但出现了一个错误 代码如下Python原始套接字到以太网接口(Windows),python,windows,python-2.7,sockets,dhcp,Python,Windows,Python 2.7,Sockets,Dhcp,我正在尝试创建一个DHCP服务器,第一步是通过以太网端口发送数据包。我试图将数据包发送到我的以太网接口,但出现了一个错误 代码如下 import socket def sendeth(src, dst, eth_type, payload, interface = "eth0"): """Send raw Ethernet packet on interface.""" assert(len(src) == len(dst) == 6) # 48-bit ethernet addre
import socket
def sendeth(src, dst, eth_type, payload, interface = "eth0"):
"""Send raw Ethernet packet on interface."""
assert(len(src) == len(dst) == 6) # 48-bit ethernet addresses
assert(len(eth_type) == 2) # 16-bit ethernet type
#s = socket.socket(socket.AF_PACKET, socket.SOCK_RAW)
s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_RAW)
# From the docs: "For raw packet
# sockets the address is a tuple (ifname, proto [,pkttype [,hatype]])"
s.bind((interface, 0))
return s.send(src + dst + eth_type + payload)
if __name__ == "__main__":
print("Sent %d-byte Ethernet packet on eth0" %
sendeth("\xFE\xED\xFA\xCE\xBE\xEF",
"\xFE\xED\xFA\xCE\xBE\xEF",
"\x7A\x05",
"hello"))
我对创建套接字的方式有问题。AF_数据包无法识别,所以我假设它只适用于Linux。我把它注释掉了,并在下面加了一行。我再次运行它,开始出现如下所示的错误
Traceback (most recent call last):
File "eth.py", line 27, in <module>
"hello"))
File "eth.py", line 19, in sendeth
s.bind((interface, 0))
File "C:\Python27\lib\socket.py", line 224, in meth
return getattr(self._sock,name)(*args)
socket.gaierror: [Errno 11001] getaddrinfo failed
回溯(最近一次呼叫最后一次):
文件“eth.py”,第27行,在
“你好”)
文件“eth.py”,第19行,在sendeth中
s、 绑定((接口,0))
文件“C:\Python27\lib\socket.py”,第224行,meth格式
返回getattr(self.\u sock,name)(*args)
socket.gaierror:[Errno 11001]getaddrinfo失败
有人知道为什么会发生这种情况吗?看起来您无法使用此套接字访问以太网:
s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_RAW)
socket.IPPROTO_RAW
允许您访问3级协议(IP),而以太网位于1级和2级。在第3级,已分析以太网帧,并丢弃其报头。你需要进入第二级,而且ETH\u P\u ALL
协议似乎是一个很好的起点。我不相信pythonsocket
模块在那个低级别上实现了它,但是您可以通过ctypes
模块与WinAPI交互。文档中的这个示例似乎很有启发性。
我认为关键是socket.gethostbyname(socket.gethostname())。Windows不支持示例中使用的“eth0”。DHCP是UDP协议。实现DHCP服务器不需要原始套接字
使用AF_INET/SOCK_DGRAM套接字,并绑定到地址255.255.255.255以实现您的服务器。从另一个方向回答您的问题:为什么您需要使用以太网?DHCP通常通过UDP实现
router(config)# interface ethernet 0/0
router(config-if)# ip helper-address 10.1.23.5
router(config-if)# end
router#
因此,我们配置路由器,以便它知道有一些有用的东西连接到IP 10.1.23.5的以太网0/0端口,需要广播() 如前所述,
ETH\u p\u ALL
由于Win32的限制,未在Windows上实现。
另一种方法称为Winpcap(最近的Npcap),它设置窗口来访问这些低级内容(它添加了一个额外的驱动程序)
然后,您可以使用基于Winpcap/Npcap的库来访问原始低级套接字。这需要在计算机上安装Npcap(或Winpcap)
然后,您可以按原样使用库(它有很多处理数据包的功能),或者如果您想访问原始数据
from scapy.all import *
IFACES.show() # let’s see what interfaces are available. Windows only
iface = <<"full iface name">> or <<IFACES.dev_from_index(12)>> or <<IFACES.dev_from_pcapname(r"\\Device_stuff")>>
socket = conf.L2socket(iface=iface)
# socket is now an Ethernet socket
### RECV
packet_raw = socket.recv_raw()[0] # Raw data
packet_decoded = socket.recv() # Using the library (also contains things like sent time...)
### SEND
socket.send(b"\x00......"). # send raw data
socket.send(Ether()/IP(dst="www.google.com")/TCP()/Raw(load=b"data")) # use library
从scapy.all导入*
IFACES.show()#让我们看看有哪些接口可用。仅限窗口
iface=或
socket=conf.L2socket(iface=iface)
#套接字现在是以太网套接字
###记录
packet_raw=socket.recv_raw()[0]#原始数据
packet_decoded=socket.recv()#使用库(还包含发送时间等内容)
###发送
socket.send(b“\x00……”)发送原始数据
socket.send(Ether()/IP(dst=“www.google.com”)/TCP()/Raw(load=b“data”)#使用库
您要为接口传递什么?“eth0”在Windows上不起作用。事实上,根据我对Windows套接字的经验,接口名称通常是不可理解的。甚至还有一个第三方模块来处理它们如果我有多个接口会发生什么?嗯。。。gethostbyname返回一个IP地址。也许可以尝试使用分配给您想要的物理接口的IP地址绑定?当我尝试使用ETH_P__-ALL时,我得到一个错误:AttributeError:“module”对象没有属性“ETH_-P_-ALL”@Sam是的,ETH_-P_-ALL没有在套接字中实现。您必须直接使用WinAPI。谢谢。这让我的生活轻松多了。在收到绑定到255.255.255.255的套接字上的消息后,我必须处理该消息并将信息发送回客户端以设置其IP。稍微超出了本线程的范围,您知道描述此交互的位置吗?还是我必须深入研究RFC2131文档?
from scapy.all import *
IFACES.show() # let’s see what interfaces are available. Windows only
iface = <<"full iface name">> or <<IFACES.dev_from_index(12)>> or <<IFACES.dev_from_pcapname(r"\\Device_stuff")>>
socket = conf.L2socket(iface=iface)
# socket is now an Ethernet socket
### RECV
packet_raw = socket.recv_raw()[0] # Raw data
packet_decoded = socket.recv() # Using the library (also contains things like sent time...)
### SEND
socket.send(b"\x00......"). # send raw data
socket.send(Ether()/IP(dst="www.google.com")/TCP()/Raw(load=b"data")) # use library