为什么我没有收到使用带 udp 套接字的 BPF 的任何数据包?

麦饼

目标:编写一个 BPF 过滤器,它只允许来自特定 src 地址的 UDP 数据包并将其附加到 UDP 套接字。

问题:如果我执行程序并尝试从具有正确 src IP 的 VM 发送 udp 数据包,我将不会收到任何数据包

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>

#include <arpa/inet.h>
#include <linux/filter.h>

/* udp and src 192.168.56.101 */
struct sock_filter bpfcode[] = {
    { 0x28, 0, 0, 0x0000000c },
    { 0x15, 6, 0, 0x000086dd },
    { 0x15, 0, 5, 0x00000800 },
    { 0x30, 0, 0, 0x00000017 },
    { 0x15, 0, 3, 0x00000011 },
    { 0x20, 0, 0, 0x0000001a },
    { 0x15, 0, 1, 0xc0a83865 },
    { 0x6,  0, 0, 0x00040000 },
    { 0x6,  0, 0, 0x00000000 },
};

int main(void)
{
    struct sock_fprog bpf = {
        sizeof(bpfcode) / sizeof(struct sock_filter),
        bpfcode
    };
    struct sockaddr_in src = {
        .sin_family = AF_INET,
        .sin_addr.s_addr = INADDR_ANY,
        .sin_port = htons(1025)
    };
    char buf[1024];
    ssize_t res;
    int fd, ret;

    fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
    if (fd < 0) {
        printf("error: socket\n");
        exit(EXIT_FAILURE);
    }

    ret = setsockopt(fd, SOL_SOCKET, SO_ATTACH_FILTER, &bpf, sizeof(bpf));
    if (ret < 0) {
        perror("error: setsockopt\n");
        close(fd);
        exit(EXIT_FAILURE);
    }

    ret = bind(fd, (struct sockaddr *)&src, sizeof(src));
    if (ret < 0) {
        printf("error: bind\n");
        close(fd);
        exit(EXIT_FAILURE);
    }

    res = recvfrom(fd, buf, sizeof(buf), 0, NULL, 0);
    printf("res = %zi\n", res);

    close(fd);

    return 0;
}
凯尔

评论中的讨论摘要:

首先,套接字的类型是SOCK_DGRAM,因此您获得的数据从 L4 (UDP) 开始,而不是像过滤器期望的那样从 L2 开始。使用 aSOCK_RAW代替。

然后, usingSOCK_RAW将使您可以访问 L3,而不是 L2(您需要为此更改套接字域)。所以你需要稍微调整你的过滤器:

    { 0x28, 0, 0, 0x0000000c }, // load Ethertype
    { 0x15, 6, 0, 0x000086dd }, // If IPv6 goto drop
    { 0x15, 0, 5, 0x00000800 }, // If not IPv4 (and not IPv6) goto drop
    { 0x30, 0, 0, 0x00000017 }, // Load IP protocol
    { 0x15, 0, 3, 0x00000011 }, // If not UDP goto drop
    { 0x20, 0, 0, 0x0000001a }, // Load src address
    { 0x15, 0, 1, 0xc0a83865 }, // If not 192.168.56.1.1 goto drop
    { 0x6,  0, 0, 0x00040000 }, // Pass packet
    { 0x6,  0, 0, 0x00000000 }, // Drop

应该变成(归功于自己修复它的 OP :)):

    // UDP check is harmless but useless
    // { 0x30, 0, 0, 0x00000009 }, // Note the offset update
    // { 0x15, 0, 3, 0x00000011 },
    { 0x20, 0, 0, 0x0000000c }, // Note the offset update
    { 0x15, 0, 1, 0xc0a83865 },
    { 0x6,  0, 0, 0x00040000 },
    { 0x6,  0, 0, 0x00000000 },

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

通过侦听多个UDP套接字来避免数据包类型检查

从长度未知的UDP套接字读取数据

如何读取Golang中收到的UDP数据报的输入接口和远程套接字地址?

使用UDP套接字的Java对等

在Wireshark中看到的数据报,Qt UDP套接字未收到

使用.Net Core创建UDP套接字

如何使用BPF重新过滤漏斗数据包?

从同一套接字读取tcp和udp数据包

为什么我的服务器套接字没有收到客户端发送的数据包

对UDP套接字使用shutdown()

如何使用bpf返回数据包

AF_PACKET套接字未在C中发送带有SOCK_RAW的空UDP数据包

使用同一套接字发送和接收UDP多播数据包

使用Linux原始套接字捕获PTP数据包

避免在udp套接字中积累数据或从udp套接字读取最新数据

以太网数据包通过套接字原始文件具有尾部而不是udp标头

网络数据包计数:无法从BPF套接字过滤器读取数据包数据

什么是ICMP数据包?TCP或UDP

通过UDP套接字发送数据

使用Wireshark的Java套接字获取数据包

Linux C套接字UDP服务器。select()没有收到任何东西

无法接收到原始套接字的数据包

使用 UDP 进行 Java 套接字编程

如何使用相同的 UDP 套接字来发送和接收数据包?我在这段代码中缺少什么?

udp 套接字究竟接收什么?

Flutter 中的 udp 套接字未收到任何消息

有没有办法检查 Filebeat 是否收到任何 UDP 数据包?

C (UDP) 中的套接字服务器不接收数据包。怎么做?

数据包套接字没有接收到数据