How to initialize raw socket for VLAN sniffing

后端 未结 2 1672
难免孤独
难免孤独 2021-01-21 02:33

I\'m trying to create software that sniffes DHCP-offers from diffrent VLAN\'s and my problem is that the packets recv\'ed by me contains no VLAN-tags. I\'m using raw sockets, an

相关标签:
2条回答
  • 2021-01-21 02:48

    If I understand the Linux code correctly, VLAN tags are stripped from packets' payload early and stored in a field that is not accessible through the raw sockets API. Instead, try to do what wireshark does, i.e., use the pcap API.

    0 讨论(0)
  • 2021-01-21 02:57

    This is old, but this still hasn't been solved:

    When VLAN offload is enabled on the NIC Linux will not deliver the VLAN tag in the data returned by recv. Instead, it delivers the VLAN TCI in a control message.

    To get the control fields, you need to use PACKET_AUXDATA, which will add the following to ancillary data:

     struct tpacket_auxdata {
          __u32 tp_status;
          __u32 tp_len;      /* packet length */
          __u32 tp_snaplen;  /* captured length */
          __u16 tp_mac;
          __u16 tp_net;
          __u16 tp_vlan_tci;
          __u16 tp_padding;
      };
    

    For instance

    sock.setsockopt(SOL_PACKET, PACKET_AUXDATA, 1)
    

    Once that is done, use recvmsg() and iterate through the ancillary data looking for PACKET_AUXDATA. Get tp_vlan_tci out of it, and inject this back into the packet data.

    Examples of code

    • C: libpcap

    https://github.com/the-tcpdump-group/libpcap/blob/3a7962215f4f3b13ac792ad0e0487a53c0f1178e/pcap-linux.c#L1756

    • Python
    import ctypes, socket
    
    # From bits/socket.h
    SOL_PACKET = 263
    # From asm/socket.h
    SO_ATTACH_FILTER = 26
    ETH_P_8021Q = 0x8100
    TP_STATUS_VLAN_VALID = 1 << 4
    
    class tpacket_auxdata(ctypes.Structure):
        _fields_ = [
            ("tp_status", ctypes.c_uint),
            ("tp_len", ctypes.c_uint),
            ("tp_snaplen", ctypes.c_uint),
            ("tp_mac", ctypes.c_ushort),
            ("tp_net", ctypes.c_ushort),
            ("tp_vlan_tci", ctypes.c_ushort),
            ("tp_padding", ctypes.c_ushort),
        ]
    
    def _recv_raw(sock, x=65535):
        """Internal function to receive a Packet,
        and process ancillary data.
        """
        flags_len = socket.CMSG_LEN(4096)
        pkt, ancdata, flags, sa_ll = sock.recvmsg(x, flags_len)
        if not pkt:
            return pkt, sa_ll
        for cmsg_lvl, cmsg_type, cmsg_data in ancdata:
            # Check available ancillary data
            if (cmsg_lvl == SOL_PACKET and cmsg_type == PACKET_AUXDATA):
                # Parse AUXDATA
                auxdata = tpacket_auxdata.from_buffer_copy(cmsg_data)
                if auxdata.tp_vlan_tci != 0 or \
                        auxdata.tp_status & TP_STATUS_VLAN_VALID:
                    # Insert VLAN tag
                    tag = struct.pack(
                        "!HH",
                        ETH_P_8021Q,
                        auxdata.tp_vlan_tci
                    )
                        pkt = pkt[:12] + tag + pkt[12:]
            return pkt
    

    (From https://github.com/secdev/scapy)

    0 讨论(0)
提交回复
热议问题