2011-05-20 21 views
9

Sabemos que Python permite activar el modo promiscuo en Windows a travésPython sockets: habilitar el modo promiscuo en Linux

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

Sin embargo, el RCVALL_ * * SIO_ y está disponible sólo en las ventanas. Usando C socket API, en Linux, se puede utilizar:

ethreq.ifr_flags |= IFF_PROMISC; 
ioctl(sock, SIOCSIFFLAGS, &ethreq); 

oa través de,

setsockopt(sock, SOL_PACKET, PACKET_ADD_MEMBERSHIP, PACKET_MR_PROMISC) 

¿Hay alguna opción en pitón socket API que nos permite establecer el modo promiscuo en Linux?

+0

Necesita permisos de raíz en Linux para usar el modo promiscuo. –

+0

Tenía permisos de root, pero gracias por recordar :) – TanB

Respuesta

13

Utilice un socket AF_NETLINK para emitir una solicitud para activar IFF_PROMISC. Python puede construir AF_NETLINK tomas en Linux:

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

Véase el ejemplo al final del enlace de red (7) del manual para un ejemplo de cómo emitir una solicitud de enlace de red. Puede usar ctypes (o incluso struct) para construir el mensaje nlmsghdr serializado para enviar a través del zócalo netlink. Es posible que también lo necesite para llamar al sendmsg y recvmsg, desde Python still doesn't expose these APIs. Alternativamente, hay algunos third-party modules disponibles que exponen estas dos API.

Alternativamente, puede ir a la ruta de la vieja escuela de usar ioctl, que tristemente resulta ser bastante más simple.

En primer lugar definir la estructura ifreq usando ctypes:

import ctypes 

class ifreq(ctypes.Structure): 
    _fields_ = [("ifr_ifrn", ctypes.c_char * 16), 
       ("ifr_flags", ctypes.c_short)] 

A continuación, hacer una toma de corriente para usar con el ioctl llamada:

import socket 

s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 

luego copiar un par de valores constantes de/usr/include desde no están expuestos por Python:

IFF_PROMISC = 0x100 
SIOCGIFFLAGS = 0x8913 
SIOCSIFFLAGS = 0x8914 

Crear un instan ce de la estructura ifreq y rellenarla tengan el efecto deseado:

ifr = ifreq() 
ifr.ifr_ifrn = "eth4" 

rellenar el campo ifr_flags con una llamada ioctl por lo que no Clobber lo banderas ya están establecido en la interfaz:

import fcntl 

fcntl.ioctl(s.fileno(), SIOCGIFFLAGS, ifr) # G for Get 

Añadir la bandera promiscua:

ifr.ifr_flags |= IFF_PROMISC 

y juego de las banderas en la interfaz:

fcntl.ioctl(s.fileno(), SIOCSIFFLAGS, ifr) # S for Set 

Para retirar la bandera, enmascararlo apagado y el nuevo:

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

Saludos por la respuesta detallada y proporcionar fragmentos de código útiles. – TanB

3

Hay otra manera pensé. Quizás no sea tan elegante, pero parece funcionar bien.

En Linux (con permisos de root), se puede utilizar:

# ifconfig eth0 promisc 
# ifconfig eth0 -promisc 

Para activar el modo/desactivar promisc en su interfaz (eth0 en este caso).

Así, en Python (con permisos de root) se podría usar:

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

Los comentarios son bienvenidos en esta forma de hacerlo.

+2

Un enfoque similar usando la nueva utilidad "ip" sería ejecutar "ip link set eth0 promisc on". Llamar a ifconfig en un subproceso probablemente hará las mismas ioctls que di en mi respuesta. Y al llamar a ip en un subproceso voy a hacer las cosas de AF_NETLINK a las que aludí pero que en realidad no deletrean (porque es más difícil :). –

Cuestiones relacionadas