python - 在Python中读取原始以太网数据包的VLAN字段

标签 python sockets packet-sniffers vlan raw-ethernet

我使用以太网数据包(2 层,没有 UDP/IP 也没有 TCP/IP)在两个节点之间进行低级通信。这些数据包内部有 VLAN 字段,我的接口(interface)配置为混杂模式,并且能够完全读取它们,因为我可以在 Ubuntu 系统的 Wireshark 中看到 VLAN 标记。

使用 python,我可以读取除 VLAN 字段之外的整个数据包。该字段消失,在源 MAC 字段之后,以太网类型出现。

import socket

sock = socket.socket(socket.AF_PACKET, socket.SOCK_RAW, socket.htons(0x0003))

msg = sock.recvmsg(4096)

可以使用socket python模块来做到这一点吗?我的配置中是否缺少某些内容或者是 NIC 问题?

提前致谢,

最佳答案

聚会迟到,请参阅https://stackoverflow.com/a/59760058/5459467了解完整详细信息。

我建议使用scapy's sockets (conf.L2socketsniff)已实现此代码。否则使用下面的代码片段:

import ctypes, socket

# From bits/socket.h
SOL_PACKET = 263
# From asm/socket.h
SO_ATTACH_FILTER = 26
ETH_P_8021Q = 0x8100
PACKET_AUXDATA = 8
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/pull/2091 )

但首先,在启动套接字时,使用

sock.setsockopt(SOL_PACKET, PACKET_AUXDATA, 1)

关于python - 在Python中读取原始以太网数据包的VLAN字段,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56653023/

相关文章:

python - 带范围的 pyobjc 索引访问器方法

python - 更改 matplotlib 中注释箭头的宽度

c - 如何使用 PAM 功能模块将功能授予特定用户和可执行文件?

android - 数据包捕获应用程序一旦启动,就不再具有与其他应用程序的互联网连接

java - 如何嗅探 SSL 保护的 Metro Web 服务和 WCF 客户端之间的通信?

c++ - 是否有用于 Wireshark 的 API,用于开发与其交互/增强的程序/插件?

python - Pandas-来自重复的行,保留没有空值的行

javascript - 在服务器端还是客户端进行图像处理?

sockets - 使用 ZeroMQ 实现消息总线

Python 套接字只允许一个连接,但在新连接时断开连接,而不是拒绝