linux - 如何为 VLAN 嗅探初始化原始套接字

标签 linux sockets

我正在尝试创建从不同 VLAN 嗅探 DHCP 提议的软件,我的问题是我收到的数据包不包含 VLAN 标签。我正在使用原始套接字,并且尝试启用混杂模式,但无济于事。

问题是如何指示内核保持数据包中的所有数据完好无损?

当使用 wireshark 时,我可以看到 VLAN header 设置正常的回复数据包,但我收到的数据已删除所有 VLAN 信息。

提前致谢!

--劳里

最佳答案

这是旧的,但仍未解决:

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.

要获取控制字段,您需要使用PACKET_AUXDATA,这会将以下内容添加到辅助数据中:

 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;
  };

例如

sock.setsockopt(SOL_PACKET, PACKET_AUXDATA, 1)

完成后,使用 recvmsg() 并遍历辅助数据以查找 PACKET_AUXDATA。从中取出 tp_vlan_tci,并将其重新注入(inject)到数据包数据中。

代码示例

  • 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

(来自https://github.com/secdev/scapy)

关于linux - 如何为 VLAN 嗅探初始化原始套接字,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10947286/

相关文章:

C# Socket 打印有时没有反应?

java - Java 中使用 SSL 的 HTTP 代理

c++ - GCC 与 kerberos 链接以静态编译 CURL

c++ - 交叉编译库链接 (linux) (C++/C)

python - PyGTK 中的小部件透明度?

ios - iPad 之间的安全通信

json - 在 Linux 上将 chromeOptions args 传递给 .json 文件中的 selenium 节点

linux - Docker RUN groupadd && useradd 指令无效

sockets - 如何格式化 HTTP 响应

Python Socket - 处理客户端断开连接