Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python套接字:在Linux中启用混杂模式_Python_Sockets_Networking - Fatal编程技术网

Python套接字:在Linux中启用混杂模式

Python套接字:在Linux中启用混杂模式,python,sockets,networking,Python,Sockets,Networking,我们知道Python允许在Windows下通过 s.ioctl(socket.SIO_RCVALL, socket.RCVALL_ON) 但是,RCVALL_*和SIO_*仅在windows中可用。 使用C socket api,在Linux中,可以使用: ethreq.ifr_flags |= IFF_PROMISC; ioctl(sock, SIOCSIFFLAGS, &ethreq); # ifconfig eth0 promisc # ifconfig eth0 -promi

我们知道Python允许在Windows下通过

s.ioctl(socket.SIO_RCVALL, socket.RCVALL_ON)
但是,RCVALL_*和SIO_*仅在windows中可用。 使用C socket api,在Linux中,可以使用:

ethreq.ifr_flags |= IFF_PROMISC;
ioctl(sock, SIOCSIFFLAGS, &ethreq);
# ifconfig eth0 promisc
# ifconfig eth0 -promisc
或者通过

setsockopt(sock, SOL_PACKET, PACKET_ADD_MEMBERSHIP, PACKET_MR_PROMISC)

pythonsocketapi中是否有允许我们在Linux中设置混杂模式的选项

使用
AF\u NETLINK
套接字发出打开
IFF\u PROMISC
的请求。Python可以在Linux上构造
AF_NETLINK
套接字:

>>> from socket import AF_NETLINK, SOCK_DGRAM, socket 
>>> s = socket(AF_NETLINK, SOCK_DGRAM)
>>>
有关如何发出netlink请求的示例,请参见netlink(7)手册页面末尾的示例。您可以使用
ctypes
(甚至
struct
)构造要通过netlink套接字发送的序列化nlmsghdr消息。您可能还需要它来调用
sendmsg
recvmsg
,因为。或者,有一些可用的方法公开这两个API

或者,您也可以采用传统的方法使用
ioctl
,遗憾的是,这种方法更加简单

首先使用ctypes定义ifreq结构:

import ctypes

class ifreq(ctypes.Structure):
    _fields_ = [("ifr_ifrn", ctypes.c_char * 16),
                ("ifr_flags", ctypes.c_short)]
然后制作一个套接字,用于
ioctl
调用:

import socket

s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
然后从/usr/include中复制两个常量值,因为Python没有公开它们:

IFF_PROMISC = 0x100
SIOCGIFFLAGS = 0x8913
SIOCSIFFLAGS = 0x8914
创建ifreq结构的实例并填充它以获得所需的效果:

ifr = ifreq()
ifr.ifr_ifrn = "eth4"
使用
ioctl
调用填充
ifr\u flags
字段,这样就不会破坏界面上已设置的任何标志:

import fcntl

fcntl.ioctl(s.fileno(), SIOCGIFFLAGS, ifr) # G for Get
fcntl.ioctl(s.fileno(), SIOCSIFFLAGS, ifr) # S for Set
添加混杂标志:

ifr.ifr_flags |= IFF_PROMISC
并在界面上设置标志:

import fcntl

fcntl.ioctl(s.fileno(), SIOCGIFFLAGS, ifr) # G for Get
fcntl.ioctl(s.fileno(), SIOCSIFFLAGS, ifr) # S for Set
要删除该标志,请将其屏蔽并重新设置:

ifr.ifr_flags &= ~IFF_PROMISC
fcntl.ioctl(s.fileno(), SIOCSIFFLAGS, ifr)

我想到了另一种方法。也许没有那么优雅,但似乎工作得很好

在linux(具有根权限)中,可以使用:

ethreq.ifr_flags |= IFF_PROMISC;
ioctl(sock, SIOCSIFFLAGS, &ethreq);
# ifconfig eth0 promisc
# ifconfig eth0 -promisc
在界面上启用/禁用promisc模式(本例中为eth0)

因此,在python(具有根权限)中,可以使用:

import os
ret =  os.system("ifconfig eth0 promisc")
if ret == 0:
     <Do something>
导入操作系统
ret=os.system(“ifconfig eth0 promisc”)
如果ret==0:

欢迎对这种做法提出意见

要使用混杂模式,您需要Linux上的根权限。我有根权限,但感谢您提醒:)为详细的答案干杯,并提供有用的代码片段。使用较新的“ip”实用程序的类似方法是运行“ip链接集eth0 promisc on”。在子流程中调用ifconfig可能会执行与我在回答中给出的相同的ioctl。在子进程中调用ip将完成我提到的AF_NETLINK功能,但实际上并没有详细说明(因为它更难:)。