简介

Monitor mode 与 promiscuous mode 比较

这是在网卡上的的两个特殊的模式,简而言之,都是将网卡的过滤器关闭。

  • Monitor mode

这是我们常常提到的sniffer mode。它用于无线网络中,无线网卡开启监听模式,监听空气中的所有数据包,其中它还可以切换channel。如果设置得当,可以同时监控所有信道的帧(切换式,或者同时多个网卡监听)。在这个模式下面,STA是没有连接到AP的。除了能够得到数据包之外,还可以得到控制帧和管理帧。对于debug 802.11的问题(omnipeek or wireshark in linux)或者攻击一个802.11的网络(aircrack、reaver),常常会使网卡进入到这个模式。此文重点在于promiscuous mode,802.11的monitor mode不再赘述。

  • Promiscuos mode

不处于promiscuous mode的网卡只会收取DA会自身的数据包或者BC/MC的数据包。在promiscuos mode下面,网卡会收到DA不是自身的包,在进入这个模式的时候,常常会开启一个raw socket,来接收网卡传递上来的数据。

打开promiscuous mode

翻阅libpcap的源码,可以整理出这两种方式,可以打开promiscuous mode:

(activate_new) – new way

1.Try to open a packet socket using the new kernel PF_PACKET interface
2.Select promiscuous mode on

struct packet_mreq  mr; memset(&mr, 0, sizeof(mr));
mr.mr_ifindex = handlep->ifindex;
mr.mr_type = PACKET_MR_PROMISC;
sock_fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
setsockopt(sock_fd, SOL_PACKET, PACKET_ADD_MEMBERSHIP, &mr, sizeof(mr))

setsockopt 原型如下:

int setsockopt(int sockfd, int level, int optname, const void *optval, socklen_t optlen);

对应于内核的 /include/net/sock.h

(setsockopt)(struct sock sk, int level, int optname, char __user *optval, unsigned int optlen);

net/packet/af_packet.c 里面有对应的操作:

static int
packet_setsockopt(struct socket *sock, int level, int optname, char __user *optval, unsigned int optlen)
{
struct sock *sk = sock->sk;
struct packet_sock *po = pkt_sk(sk);
int ret; if (level != SOL_PACKET)
return -ENOPROTOOPT; switch (optname) {
case PACKET_ADD_MEMBERSHIP:
case PACKET_DROP_MEMBERSHIP:
{
struct packet_mreq_max mreq;
int len = optlen;
memset(&mreq, 0, sizeof(mreq));
if (len sizeof(mreq))
len = sizeof(mreq);
if (copy_from_user(&mreq, optval, len))
return -EFAULT;
if (len < (mreq.mr_alen + offsetof(struct packet_mreq, mr_address)))
return -EINVAL;
if (optname == PACKET_ADD_MEMBERSHIP)
ret = packet_mc_add(sk, &mreq);
else
ret = packet_mc_drop(sk, &mreq);
return ret;
}

调用流程:

packet_mc_add -> packet_dev_mc -> dev_set_promiscuity(net/core/dev.c)

dev_set_promiscuity的定义如下:

int dev_set_promiscuity(struct net_device *dev, int inc)
{
unsigned int old_flags = dev->flags;
int err; err = __dev_set_promiscuity(dev, inc, true);
if (err <0 return err if dev->flags != old_flags)
dev_set_rx_mode(dev);
return err;
}
__dev_set_promiscuity =>
dev->flags |= IFF_PROMISC;
dev_change_rx_flags(dev, IFF_PROMISC);
ops(net_device_ops)->ndo_change_rx_flags(dev, flags);
dev_set_rx_mode(dev); ==>
ops(net_device_ops)->ndo_set_rx_mode(dev);

驱动基本上只实现了ndo_set_rx_mode

选择一个Ethernet驱动作为例子:

const struct net_device_ops ei_netdev_ops = {
....
.ndo_open = ei_open,
.ndo_stop = ei_close,
.ndo_start_xmit = ei_start_xmit,
.ndo_set_rx_mode = ei_set_multicast_list,
};
ei_set_multicast_list ->
__ei_set_multicast_list ->
do_set_multicast_list
static void do_set_multicast_list(struct net_device *dev)
{
....
if (dev->flags&IFF_PROMISC) {
memset(ei_local->mcfilter, 0xFF, 8);
ei_outb_p(E8390_RXCONFIG | 0x18, e8390_base + EN0_RXCR);
}
}

这边可以看到驱动设置了EN0_RXCR,含义猜测是RX config register,将RX的接收状态设置为accept all。所以说,设置设备进入promiscuous mode,实际上是设置硬件寄存器ndo_set_rx_mode,需要设备的驱动支持。

(activate_old) – old way

struct ifreq ifr;
ifr.ifr_flags |= IFF_PROMISC;
ioctl(handle->fd, SIOCSIFFLAGS, &ifr)

这种开启方法,多个开启混杂模式的程序可能会干扰,容易出问题,不推荐使用
在 net/core/dev_ioctl.c

=> dev_ifsioc
=> dev_change_flags
=> __dev_change_flags
=> dev_set_rx_mode

下面的路径就和上一种方法一样了,不再赘述。可以了解到,在底层的操作,两个做法都是一样的,都是关闭了网卡的过滤器。

如何判断一个机器位于promiscuous mode

既然网卡驱动放行了所有的数据包并且将数据包上传TCPIP协议栈,那么这里可以使用一个技巧。将进入promiscuous mode的主机设为A。从同一网段的B主机伪造一个目标MAC地址不是A,但是目标ip地址是A的包。当正常的主机收到这个包的时候,网卡驱动或者网卡的asic就会将它丢弃,当这个主机进入promiscuous mode之后,网卡驱动放行这个包,TCPIP协议栈检查这个包的目标地址是A,所以会产生一个回应到B主机。当然了,如果主机A特意将TCPIP协议栈的收发包路径关掉,那么就无法侦测到了。

另外,如果我伪造了一个不存在的mac地址,那么交换机就不知道这个mac地址是位于哪个端口,它也会帮忙转发到所有端口。

比如我从B主机伪造一个错误MAC地址的ICMP包给A主机,判断A主机是否回应,这样就可以判断出它是否处于promiscuous mode。

MAC IP Payload
局域网内没有出现过的mac地址 192.168.0.5 xxxxxxxx

做一个测试

测试环境: ubuntu 12.4 + win10
测试网卡:Ethernet 网卡
测试软件:wireshark,ICMP c语言测试程序
两端的ip:192.168.0.4,192.168.0.5
测试方式:直连,家用路由器LAN口转发

下面是测试的过程。首先我在目标机器上面(win10)开启了wireshark,并且监听本地连接。这时候我伪造了一个错误的MAC DA,但是其他参数,比如对方的ip地址是填写正确的。这时候本机的wireshark可以看到对方的ICMP回应。紧接着我关闭win10上面的wireshark,ICMP回应消失。随后我又开启wireshark,又可以得到ICMP回应了。测试的时候,两台机器使用网线直连或者通过家用路由器的LAN口转发都是成功的,但是使用无线网络的时候是失败的,可能是无线网卡不支持promiscuous mode。注意到,因为是要伪造MAC地址,所以需要使用PF_PACKET来操作RAW socket

下图是在ubuntu上面的wireshark截取的

另外,如果两个机器直连测试,需要在windows上面设置静态ip地址(192.168.0.5/24),在linux机器上面关闭界面上的网络连接,并且输入测试网络是否连通:

tanhangbo@ThinkPad:~$ sudo ifconfig eth0 up
tanhangbo@ThinkPad:~$ sudo ifconfig eth0 192.168.0.4
tanhangbo@ThinkPad:~$ ping 192.168.0.5
PING 192.168.0.5 (192.168.0.5) 56(84) bytes of data.
64 bytes from 192.168.0.5: icmp_req=1 ttl=128 time=0.312 ms
64 bytes from 192.168.0.5: icmp_req=2 ttl=128 time=0.384 ms
64 bytes from 192.168.0.5: icmp_req=3 ttl=128 time=0.408 ms

实际作用

一般来说,进入这个模式,就是为了多收一些包,进行网络诊断。一般开启wireshark的时候就会帮你打开promiscuous mode。底层操作在libpcap里面。

  • 参考资料:
  1. libpcap和linux kernel 源码
  2. http://stackoverflow.com/questions/6666257/what-is-the-purpose-of-net-device-uc-promisc-field

Promiscuous Mode的更多相关文章

  1. What Is The Promiscuous Mode

    What Is The Promiscuous Mode? Some Network Interface Cards (NICs) may not allow network traffic afte ...

  2. 嵌入式Linux驱动学习之路(二十六)DM9000C网卡驱动程序

    基于DM9000C的原厂代码修改dm9000c的驱动程序. 首先确认内存的基地址 iobase. 确定中断号码. 打开模块的初始化函数定义. 配置内存控制器的相应时序(结合DM9000C.C的手册). ...

  3. 使用SharpPCap在C#下进行网络抓包

    在做大学最后的毕业设计了,无线局域网络远程安全监控策略那么抓包是这个系统设计的基础以前一直都是知道用winpcap的,现在网上搜了一下,有用C#封装好了的,很好用下面是其中的几个用法这个类库作者的主页 ...

  4. Automated Memory Analysis

    catalogue . 静态分析.动态分析.内存镜像分析对比 . Memory Analysis Approach . volatility: An advanced memory forensics ...

  5. Window系统性能获取帮助类

    前言: 这个是获取Windows系统的一些性能的帮助类,其中有:系统内存.硬盘.CPU.网络(个人测试还是比较准的).Ping.单个进程的内存.Cpu.网络(不准).    最初在这个的时候在各种搜索 ...

  6. Python黑帽编程 4.1 Sniffer(嗅探器)之数据捕获(上)

    Python黑帽编程 4.1 Sniffer(嗅探器)之数据捕获(上) 网络嗅探,是监听流经本机网卡数据包的一种技术,嗅探器就是利用这种技术进行数据捕获和分析的软件. 编写嗅探器,捕获数据是前置功能, ...

  7. Netruon 理解(12):使用 Linux bridge 将 Linux network namespace 连接外网

    学习 Neutron 系列文章: (1)Neutron 所实现的虚拟化网络 (2)Neutron OpenvSwitch + VLAN 虚拟网络 (3)Neutron OpenvSwitch + GR ...

  8. SharpPcap网络包捕获框架的使用--实例代码在vs2005调试通过

    转自:http://hi.baidu.com/boyxgb/blog/item/89ac86fbdff5f82c4e4aea2e.html 由于项目的需要,要从终端与服务器的通讯数据中获取终端硬件状态 ...

  9. windows下使用C#获取特定进程网络流量

    最近老板接了一个中船重工的项目,需要做一个有关海军软件系统的组件评估项目,项目中有一个子项目需要获取特定进程的各种系统参数,项目使用.NET平台.在获取特定进程各种系统参数时,其它诸如进程ID,进程名 ...

随机推荐

  1. 天津政府应急系统之GIS一张图(arcgis api for flex)讲解(十一)路径导航模块

    config.xml文件的配置如下: <widget label="路径导航" icon="assets/images/lujingdaohang.png" ...

  2. arcgis for flex展示GIS基本功能

    1.地图框选搜索: 这是空间查询,在地图上框选一定的范围,然后搜索出在这个范围之内的所有信息,搜索到的详细信息在列表框显示出来 2.属性查询: 3.数据库展示: 4.绘制图形: 地图上绘制各种不同形状 ...

  3. Aircrack-ng: (1) 概述

    目录 一.概述 二.工具与命令介绍 Linux命令 (1) ifconfig (2) macchanger (3) iwconfig (4) iwlist Aircrack-ng 工具 (1) air ...

  4. CentOS桌面安装

    1.显示系统已经安装的组件,和可以安装的组件: #yum grouplist 2.如果系统安装之初采用最小化安装,没有安装xwindow,那么先安装: #yum groupinstall " ...

  5. eclipse配置tomcat 和JRE环境

    配置JRE环境,通俗点讲就是添加一个不同版本的jdk window——preferences——java——installed jres 点击add添加   选择standard VM 选择一个本机正 ...

  6. IOS开发基础知识--碎片30

    1:ios 相册操作 ALAssetsLibrary 知识点 a ALAssetsLibrary 实例为我们提供了获取相册(照片app)中的图片和视频的功能.在ios8 photos framewor ...

  7. ListView setOnItemClickListener无效原因分析

    前言 最近在做项目的过程中,在使用listview的时候遇到了设置item监听事件的时候在没有回调onItemClick 方法的问题.我的情况是在item中有一个Button按钮.所以不会回调.上百度 ...

  8. IOS 序列化与反序列化NSKeyedUnarchiver

    开篇 1到底这个序列化有何作用? 面向对象的程序在运行的时候会创建一个复杂的对象图,经常要以二进制的方法序列化这个对象图,这个过程叫做Archiving. 二进制流可以通过网络或写入文件中. 当你写的 ...

  9. 自定义 URL Scheme 完全指南(转载)

    iPhone / iOS SDK 最酷的特性之一就是应用将其自身”绑定”到一个自定义 URL scheme 上,该 scheme 用于从浏览器或其他应用中启动本应用. 注册自定义 URL Scheme ...

  10. mac osx vi 设置tab 四个空格

    如果想永久设置那么,vi ~/.vimrc,将以下内容加到文件中 :set tabstop=4 设定tab宽度为4个字符 :set shiftwidth=4 设定自动缩进为4个字符 :set expa ...