【问题标题】:Reading from a promiscuous network device从混杂的网络设备中读取
【发布时间】:2010-09-12 00:05:08
【问题描述】:

我想写一个无线流量的实时分析工具。

有谁知道如何从 C 中的混杂(或嗅探)设备中读取数据?

我知道您需要具有 root 访问权限才能执行此操作。我想知道是否有人知道执行此操作需要哪些功能。普通套接字在这里似乎没有意义。

【问题讨论】:

  • 在 Linux 中?您的帖子未指明操作系统,但我们是否应该假设您使用“root”是指 linux?

标签: c linux sockets wireless promiscuous-mode


【解决方案1】:

你为什么不使用WireShark之类的东西?

它是开源的,所以如果你不想仅仅使用它,至少你可以从中学到一些东西。

【讨论】:

  • 我不确定 WireShark 是否可以捕获完整的无线数据包。我认为它配置为常规 MAC 而不是无线 MAC。我需要能够查看来自多个 essid 的流量。
  • 再次,我将从查看wireshark源代码开始。
  • WireShark 不适用于 Windows 上的无线网卡(句号)。
【解决方案2】:

您可以使用 tcpdump 和 Wireshark 也使用的 pcap 库(请参阅 http://www.tcpdump.org/pcap.htm)。

【讨论】:

    【解决方案3】:

    在 Linux 上,您使用 PF_PACKET 套接字从原始设备读取数据,例如以混杂模式运行的以太网接口:

    s = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL))
    

    这会将收到的每个数据包的副本发送到您的套接字。不过,您很可能并不真正想要每个数据包。内核可以使用 BPF Berkeley Packet Filter 执行第一级过滤。 BPF 本质上是一个基于堆栈的虚拟机:它处理一小组指令,例如:

    ldh = load halfword (from packet)  
    jeq = jump if equal  
    ret = return with exit code  
    

    BPF 的退出代码告诉内核是否将数据包复制到套接字。可以使用 setsockopt(s, SOL_SOCKET, SO_ATTACH_FILTER, ) 直接编写相对较小的 BPF 程序。 (警告:内核采用 struct sock_fprog,而不是 struct bpf_program,不要将它们混在一起,否则您的程序将无法在某些平台上运行)。

    对于任何相当复杂的东西,你真的想使用 libpcap。 BPF 的功能受到限制,特别是每个数据包可以执行的指令数量。 libpcap 将负责将复杂的过滤器分成两部分,内核执行第一级过滤,而功能更强大的用户空间代码会丢弃它实际上不想看到的数据包。

    libpcap 还从您的应用程序代码中抽象出内核接口。 Linux 和 BSD 使用类似的 API,但 Solaris 需要 DLPI,而 Windows 使用其他东西。

    【讨论】:

    • 实际上,不,libpcap 不会将过滤器分成两部分。但是,是的,libpcap 是您想要使用的 - 它知道如何在不同平台上将接口置于混杂模式(例如,在 Linux 上仅使用 ETH_P_ALL 是不够的;那是“SAP 混杂”,因为您无论协议类型如何,都获取所有数据包,但它不是“物理混杂”,因为适配器不会将未发送到主机的单播数据包传递给主机。
    【解决方案4】:

    我曾经不得不监听原始以太网帧并最终为此创建了一个包装器。通过使用设备名称调用函数,例如eth0,我得到了一个处于混杂模式的套接字作为回报。 您需要做的是创建一个原始套接字,然后将其置于混杂模式。这是我的做法。

    int raw_init (const char *device)
    {
        struct ifreq ifr;
        int raw_socket;
    
        memset (&ifr, 0, sizeof (struct ifreq));
    
        /* Open A Raw Socket */
        if ((raw_socket = socket (PF_PACKET, SOCK_RAW, htons (ETH_P_ALL))) < 1)
        {
            printf ("ERROR: Could not open socket, Got #?\n");
            exit (1);
        }
    
        /* Set the device to use */
        strcpy (ifr.ifr_name, device);
    
        /* Get the current flags that the device might have */
        if (ioctl (raw_socket, SIOCGIFFLAGS, &ifr) == -1)
        {
            perror ("Error: Could not retrive the flags from the device.\n");
            exit (1);
        }
    
        /* Set the old flags plus the IFF_PROMISC flag */
        ifr.ifr_flags |= IFF_PROMISC;
        if (ioctl (raw_socket, SIOCSIFFLAGS, &ifr) == -1)
        {
            perror ("Error: Could not set flag IFF_PROMISC");
            exit (1);
        }
        printf ("Entering promiscuous mode\n");
    
        /* Configure the device */
    
        if (ioctl (raw_socket, SIOCGIFINDEX, &ifr) < 0)
        {
            perror ("Error: Error getting the device index.\n");
            exit (1);
        }
    
        return raw_socket;
    }
    

    然后,当您拥有套接字时,您可以使用 select 在数据包到达时对其进行处理。

    【讨论】:

      【解决方案5】:

      Linux 上的 WireShark 具有捕获 PLCP(物理层汇聚协议)头信息的能力。

      【讨论】:

        猜你喜欢
        • 2010-12-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-08-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多