Python原始套接字到以太网接口(Windows)

我试图创build一个DHCP服务器,第一步是我通过我的以太网端口发送数据包。 我试图发送数据包到我的以太网接口,并popup一个错误。

代码如下。

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")) 

我正在创build套接字的方式有问题。 AF_PACKET无法识别,所以我假设只适用于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 

有谁知道这是为什么发生?

看起来你不能通过这个套接字访问以太网:

 s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_RAW) 

socket.IPPROTO_RAW允许您访问级别3协议(IP),而以太网在级别1和级别2上。在级别3,以太网帧已经被分析并且报头被丢弃。 您需要达到2级和ETH_P_ALL协议似乎是一个不错的地方开始。 我不相信python socket模块在这个低级别实现它,但你可以通过ctypes模块与WinAPI交互。

这个来自文档的例子似乎有启发性。 https://docs.python.org/2/library/socket.html

 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) 

我认为关键是socket.gethostbyname(socket.gethostname())。 在您的示例中使用的“eth0”在Windows上将不受支持。

DHCP是一个UDP协议。 您不应该需要原始套接字来实现DHCP服务器。

使用AF_INET / SOCK_DGRAM套接字,并绑定到地址255.255.255.255为了实现您的服务器。

从另一个方向接近你的问题:为什么你需要使用以太网呢? DHCP通常通过UDP实现。

  1. DHCP服务器总是有一些IP地址(和它可以租用的地址池)。
  2. 如果一个客户想要和IP(DHCP实际上可以做的不仅仅是分配IP,而且现在停止在这个用例上),它将发送一个广播DHCPREQUEST,源IP为0.0.0.0,目的IP为255.255.255.255。 服务器也通过UDP广播回答他,但用他自己的源IP。

如果你想创建一个DHCP的实现,从OSI 2级(以太网)开始只会让你头痛的维护3级(IP)和4(UDP)。 我没有看到任何好处。

如果您想要创建一个基于以太网的类DHCP协议,请准备好解决以下问题:路由器不要转发广播数据包,除非被要求这样做。 例如,对于思科路由器,它看起来像这样:

 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端口。