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?
In an Ethernet local area network (LAN), promiscuous mode ensures that every data packet that is transmitted is received and read by a network adapter. This means the adapter does not filter packets. Instead, it passes each packet on to the operating system (OS) or any monitoring application installed on the network.
recvfrom(data, address) − This method receives data from the socket. Two pair (data, address) value is returned by this method. Data defines the received data and address specifies the address of socket sending the data.
DESCRIPTION. The setsockopt() function shall set the option specified by the option_name argument, at the protocol level specified by the level argument, to the value pointed to by the option_value argument for the socket associated with the file descriptor specified by the socket argument.
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)
There is another way I thought of. Maybe not as elegant but seems to work fine.
In linux (with root permissions), one can use :
# ifconfig eth0 promisc
# ifconfig eth0 -promisc
To enable/ disable promisc mode on your interface (eth0 in this case).
So, in python (with root permissions) one could use :
import os
ret = os.system("ifconfig eth0 promisc")
if ret == 0:
<Do something>
Comments are welcome on this way of doing it.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With