【问题标题】:Python Sockets: Enabling Promiscuous Mode in LinuxPython 套接字:在 Linux 中启用混杂模式
【发布时间】:2011-08-29 08:56:13
【问题描述】:

我们知道 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 socket API 中是否有任何选项可以让我们在 Linux 中设置混杂模式

【问题讨论】:

  • 您需要 Linux 上的 root 权限才能使用混杂模式。
  • 我有root权限但感谢提醒:)

标签: python sockets networking


【解决方案1】:

使用AF_NETLINK 套接字发出打开IFF_PROMISC 的请求。 Python 可以在 Linux 上构造AF_NETLINK 套接字:

>>> from socket import AF_NETLINK, SOCK_DGRAM, socket 
>>> s = socket(AF_NETLINK, SOCK_DGRAM)
>>>

有关如何发出 netlink 请求的示例,请参见 netlink(7) 手册页末尾的示例。您可以使用ctypes(甚至struct)来构造序列化的nlmsghdr 消息以通过netlink 套接字发送。您可能还需要调用sendmsgrecvmsg,因为Python still doesn't expose these APIs。或者,有一些 third-party modules 可以公开这两个 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_flags 字段,这样您就不会破坏接口上已经设置的任何标志:

import fcntl

fcntl.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_PROMISC
fcntl.ioctl(s.fileno(), SIOCSIFFLAGS, ifr)

【讨论】:

  • 为详细的答案和提供有用的代码 sn-ps 干杯。
【解决方案2】:

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

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

# ifconfig eth0 promisc
# ifconfig eth0 -promisc

在您的界面上启用/禁用 promisc 模式(在本例中为 eth0)。

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

import os
ret =  os.system("ifconfig eth0 promisc")
if ret == 0:
     <Do something>

欢迎对这种方式发表评论。

【讨论】:

  • 使用较新的“ip”实用程序的类似方法是运行“ip link set eth0 promisc on”。在子进程中调用 ifconfig 可能会执行与我在回答中给出的相同的 ioctls。在子进程中调用 ip 将执行我提到但实际上没有拼写出来的 AF_NETLINK 内容(因为它更难:)。
猜你喜欢
  • 1970-01-01
  • 2019-04-09
  • 2013-09-06
  • 2010-11-22
  • 2012-08-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-12-18
相关资源
最近更新 更多