Python Sockets: Включение неразборчивого режима в Linux - PullRequest
10 голосов
/ 20 мая 2011

Мы знаем, что Python позволяет включить смешанный режим в Windows через

s.ioctl(socket.SIO_RCVALL, socket.RCVALL_ON)

Однако RCVALL_ * и SIO_ * доступны только в окнах.Используя 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 API, которая позволяет нам устанавливать случайныережим в Linux ?

Ответы [ 2 ]

15 голосов
/ 20 мая 2011

Используйте сокет AF_NETLINK для выдачи запроса на включение IFF_PROMISC. Python может создавать AF_NETLINK сокеты в Linux:

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

См. Пример в конце справочной страницы netlink (7) для примера того, как выполнить запрос netlink. Вы можете использовать ctypes (или даже struct) для создания сериализованного сообщения nlmsghdr для отправки через сокет netlink. Вам также может понадобиться вызывать sendmsg и recvmsg, поскольку Python по-прежнему не предоставляет эти API . Кроме того, есть несколько сторонних модулей , которые предоставляют эти два API.

В качестве альтернативы, вы можете пойти по старому школьному пути, используя ioctl, который, к сожалению, оказывается гораздо проще.

Сначала определите структуру ifreq, используя ctypes:

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"

Заполните поле ifr_flags с помощью вызова ioctl, чтобы не прерывать какие-либо флаги, уже установленные на интерфейсе:

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)
3 голосов
/ 23 мая 2011

Есть еще один способ, о котором я подумал.Может быть, не так элегантно, но, кажется, работает нормально.

В Linux (с правами root) можно использовать:

# ifconfig eth0 promisc
# ifconfig eth0 -promisc

Чтобы включить / отключить режим Promisc на вашем интерфейсе (в нашем случае eth0).

Такв python (с правами суперпользователя) можно использовать:

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

Приветствуются комментарии по этому способу.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...