You are on page 1of 4

Is the network device in promiscuous mode?

May 8, 2017

Wikipedia defines promiscuous mode as a mode for a wired network interface controller (NIC)
or wireless network interface controller (WNIC) that causes the controller to pass all traffic it
receives to the central processing unit (CPU)rather than passing only the frames that the
controller is intended to receive.

How do I tell if a device is in promiscuous


mode?
tl;dr: Kernel tracks promiscuous mode using flags on the device. For promiscuous mode,
IFF_PROMISC, 0x100 should be set.

For a given interface, check the flags to see if the promiscuous bit is set.

$ cat /sys/devices/virtual/net/veth0/flags
0x1303 # 0001 001[1] 0000 0011 # device is in promiscuous mode.

$ cat /sys/devices/virtual/net/br0/flags
0x1003 # 0001 000[0] 0000 0011 # device is not in promiscuous mode.

Heres a quick python script to test promiscuous mode for all interfaces:

# This script goes through all the network devices on the system
# and determines if the device in promiscuous mode.
#
# More information at: http://goyalankit.com/blog/promiscuous-mode-detection
#
# Usage: python is_promiscuous.py
# Author: Ankit Goyal (http://github.com/goyalankit)

import os

NET_DEVICE_PATH = '/sys/devices/virtual/net/'
IFF_PROMISC = 0x100

def print_results(table):
header = [('Device', 'Promisc Mode'), ('------', '---------------')]
table = header + table
col_width = [max(len(x) for x in col) for col in zip(*table)]
for line in table:
print "| " + " | ".join("{0:{1}}".format(x, col_width[i])
for i, x in enumerate(line)) + " |"

def iterate_and_determine_promisc():
device_promisc = []
for device in os.listdir(NET_DEVICE_PATH):
with open(os.path.join(NET_DEVICE_PATH, device, 'flags')) as f:
device_flags = f.read()
if device_flags:
if int(hex(int(device_flags, 16) & IFF_PROMISC), 16):
device_promisc.append((device, 'ON'))
else:
device_promisc.append((device, 'OFF'))
else:
device_promisc.append((device, 'UNKNOWN'))

print_results(device_promisc)

iterate_and_determine_promisc()
view raw is_promiscuous.py hosted with by GitHub

Problem with existing tools


Figuring out if a given network device is in promiscuous mode using tools like iproute2 or
netstat can be trickier than youd think.

At first glance, youd think iproute2 or netstat -i command should tell you if the device is in
promiscuous mode but thats not always the case.

Well consider two examples here, first to show the case where it works as expected and second
to show where it doesnt.
A word on netstat:

In netstat command, flag P is used to display if the interface is in promiscuous mode. However, P
is also used for point to point connection. You can verify from the net-tools code here

Example 1: When it works


Following example, sets the promiscuous mode on using the iproute2 and netstat -i
command. You can verify it using the iproute2 command and kernel logs.

Verify that promiscuous mode is not enabled.

vagrant@precise64:~$ sudo ip link show eth0


2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500
qdisc pfifo_fast state UP qlen 1000
link/ether 08:00:27:88:0c:a6 brd ff:ff:ff:ff:ff:ff

vagrant@precise64:~$ sudo netstat -i eth0


Kernel Interface table
Iface MTU Met RX-OK RX-ERR RX-DRP RX-OVR TX-OK TX-ERR TX-DRP TX-OVR Flg
eth0 1500 0 28880 0 0 0 17050 0 0 0 BMRU

Enable the promiscuous mode.

vagrant@precise64:~$ sudo ip link set eth0 promisc on

Check if promiscuous mode is enabled (see PROMISC) using iproute2

vagrant@precise64:~$ sudo ip link show eth0


2: eth0: <BROADCAST,MULTICAST,PROMISC,UP,LOWER_UP> mtu 1500 \
qdisc pfifo_fast state UP qlen 1000
link/ether 08:00:27:88:0c:a6 brd ff:ff:ff:ff:ff:ff

vagrant@precise64:~$ sudo netstat -i eth0


Kernel Interface table
Iface MTU Met RX-OK RX-ERR RX-DRP RX-OVR TX-OK TX-ERR TX-DRP TX-OVR Flg
eth0 1500 0 28880 0 0 0 17050 0 0 0
BMPRU

Lets check the kernel log messages, as logged in __dev_set_promiscuity whenever a device is
added/removed to/from promiscuous mode.

vagrant@precise64:~$ grep -r 'promiscuous' /var/log/kern.log


precise64 kernel: [44441.470885] device eth0 entered promiscuous mode

Example 2: When it doesnt work


Consider this for example, adding an interface to bridge; set the promiscuous mode on for that
interface. Check out the post Linux Bridge - how it works to learn more about bridge.
Following example creates a bridge, a veth pair and adds one end of the veth pair to bridge.
According to br_add_if, promiscuous mode is turned on for the interface.

Create a new interface and add it to a bridge

vagrant@precise64:~$ sudo brctl addbr br0


vagrant@precise64:~$ sudo ip link add veth0 type veth peer name vpeer0
vagrant@precise64:~$ sudo brctl addif br0 veth0

Check if promiscuous mode is enabled using iproute2

vagrant@precise64:~$ sudo ip -d link show veth0


9: veth0: <BROADCAST,MULTICAST> mtu 1500 qdisc noop master \
br0 state DOWN qlen 1000
link/ether 12:30:e3:6b:42:2d brd ff:ff:ff:ff:ff:ff
veth

vagrant@precise64:~$ sudo netstat -ian veth0


Kernel Interface table
Iface MTU Met RX-OK RX-ERR RX-DRP RX-OVR TX-OK TX-ERR TX-DRP TX-OVR Flg
veth0 1500 0 0 0 0 0 0 0 0 0 BM
vpeer0 1500 0 0 0 0 0 0 0 0 0 BM

It doesnt show the device to be in promiscuous mode as PROMISC is not set and the flag P is not
present in netstat

Lets check kernel logs and see if the device was actually put into promiscuous mode.

vagrant@precise64:~$ grep -r 'promiscuous' /var/log/kern.log


precise64 kernel: [43656.288050] device veth0 entered promiscuous mode

As expected, the device was in fact moved to promiscuous mode but iproute2 doesnt show
it in promiscuous mode.

References
1. https://lists.gt.net/linux/kernel/178148