<-- home

Is the network device in promiscuous mode?

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.

Here’s a quick python script to test promiscuous mode for all interfaces:


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 you’d think.

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

We’ll consider two examples here, first to show the case where it works as expected and second to show where it doesn’t.

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

Let’s 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 doesn’t 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 doesn’t show the device to be in promiscuous mode as PROMISC is not set and the flag P is not present in netstat

Let’s 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 doesn’t show it in promiscuous mode.

References

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