Python 套接字:在 Linux 中启用混杂模式 [英] Python Sockets: Enabling Promiscuous Mode in Linux
问题描述
我们知道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);
或通过,
setsockopt(sock, SOL_PACKET, PACKET_ADD_MEMBERSHIP, PACKET_MR_PROMISC)
python 套接字 API 中是否有任何选项允许我们在 Linux 中设置混杂模式?
使用 AF_NETLINK
套接字发出打开 IFF_PROMISC
的请求.Python 可以在 Linux 上构建 AF_NETLINK
套接字:
有关如何发出 netlink 请求的示例,请参阅 netlink(7) 手册页末尾的示例.您可以使用 ctypes
(甚至 struct
)来构造序列化的 nlmsghdr 消息以通过 netlink 套接字发送.您可能还需要它来调用 sendmsg
和 recvmsg
,因为 Python仍然没有公开这些 API.或者,有一些第三方模块可以公开这两个 API.
或者,您可以使用 ioctl
的老派路线,遗憾的是,结果证明它相当简单.
首先使用ctypes定义ifreq结构:
import ctypes类 ifreq(ctypes.Structure):_fields_ = [("ifr_ifrn", ctypes.c_char * 16),(ifr_flags",ctypes.c_short)]
然后创建一个套接字以与 ioctl
调用一起使用:
导入套接字s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
然后从/usr/include 复制几个常量值,因为它们没有被 Python 暴露:
IFF_PROMISC = 0x100SIOCGIFFLAGS = 0x8913SIOCSIFFLAGS = 0x8914
创建一个 ifreq 结构的实例并填充它以获得所需的效果:
ifr = ifreq()ifr.ifr_ifrn = "eth4"
使用 ioctl
调用填充 ifr_flags
字段,这样您就不会破坏界面上已经设置的任何标志:
import fcntlfcntl.ioctl(s.fileno(), SIOCGIFFLAGS, ifr) # G for Get
添加混杂标志:
ifr.ifr_flags |= IFF_PROMISC
并在界面上设置标志:
fcntl.ioctl(s.fileno(), SIOCSIFFLAGS, ifr) # S for Set
要移除标志,请将其屏蔽并重新设置:
ifr.ifr_flags &= ~IFF_PROMISCfcntl.ioctl(s.fileno(), SIOCSIFFLAGS, ifr)
We know that Python Allows enabling promiscuous mode under Windows through
s.ioctl(socket.SIO_RCVALL, socket.RCVALL_ON)
However, The RCVALL_* and SIO_* is only available in windows. Using C socket api, in Linux, one can use :
ethreq.ifr_flags |= IFF_PROMISC;
ioctl(sock, SIOCSIFFLAGS, ðreq);
or through,
setsockopt(sock, SOL_PACKET, PACKET_ADD_MEMBERSHIP, PACKET_MR_PROMISC)
Is there any option in python socket API that allows us to set promiscuous mode in Linux?
Use an AF_NETLINK
socket to issue a request to turn on IFF_PROMISC
. Python can construct AF_NETLINK
sockets on Linux:
>>> from socket import AF_NETLINK, SOCK_DGRAM, socket
>>> s = socket(AF_NETLINK, SOCK_DGRAM)
>>>
See the example at the end of the netlink(7) manual page for an example of how to issue a netlink request. You can use ctypes
(or even struct
) to construct the serialized nlmsghdr message to send over the netlink socket. You may also need it to call sendmsg
and recvmsg
, since Python still doesn't expose these APIs. Alternatively, there are some third-party modules available which expose these two APIs.
Alternatively, you can go the old school route of using ioctl
, which sadly turns out to be rather simpler.
First define the ifreq structure using ctypes:
import ctypes
class ifreq(ctypes.Structure):
_fields_ = [("ifr_ifrn", ctypes.c_char * 16),
("ifr_flags", ctypes.c_short)]
Then make a socket to use with the ioctl
call:
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
Then copy a couple constant values out of /usr/include since they're not exposed by Python:
IFF_PROMISC = 0x100
SIOCGIFFLAGS = 0x8913
SIOCSIFFLAGS = 0x8914
Create an instance of the ifreq struct and populate it to have the desired effect:
ifr = ifreq()
ifr.ifr_ifrn = "eth4"
Populate the ifr_flags
field with an ioctl
call so that you don't clobber whatever flags are already set on the interface:
import fcntl
fcntl.ioctl(s.fileno(), SIOCGIFFLAGS, ifr) # G for Get
Add the promiscuous flag:
ifr.ifr_flags |= IFF_PROMISC
And set the flags on the interface:
fcntl.ioctl(s.fileno(), SIOCSIFFLAGS, ifr) # S for Set
To remove the flag, mask it off and set again:
ifr.ifr_flags &= ~IFF_PROMISC
fcntl.ioctl(s.fileno(), SIOCSIFFLAGS, ifr)
这篇关于Python 套接字:在 Linux 中启用混杂模式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!