首页 > 其他分享 >eBPF基于LPM实现路由匹配

eBPF基于LPM实现路由匹配

时间:2024-05-04 11:33:52浏览次数:28  
标签:__ hdr eBPF lpm LPM key data 路由 struct

基于eBPF lpm map,icmp只有匹配上路由才能通。

最终目录结构

效果展示

启动应用前,可以ping通192.168.0.1和192.168.0.105。

启动应用后,无法ping通192.168.0.1,可以ping通192.168.0.105。

停止应用后,可以ping通192.168.0.1和192.168.0.105。

icmp/drop-icmp.c

#include "../headers/vmlinux.h"
#include "../headers/bpf_endian.h"
#include "../headers/bpf_helpers.h"

#define TC_ACT_SHOT 2
#define TC_ACT_OK 0

#define ETH_P_IP 0x0800

// 定义key
struct ipv4_lpm_key {
    __u32 prefixlen;
    __u32 data;
};

// 定义lpm map
struct {
    __uint(type, BPF_MAP_TYPE_LPM_TRIE);
    __type(key, struct ipv4_lpm_key);
    __type(value, __u32);
    __uint(map_flags, BPF_F_NO_PREALLOC);
    __uint(max_entries, 255);
    // 本地持久化map
    __uint(pinning, LIBBPF_PIN_BY_NAME);
} ipv4_lpm_map SEC(".maps");

struct ipv4_lpm_key *unused_ipv4_lpm_key __attribute__((unused));

char __license[] SEC("license") = "Dual MIT/GPL";

SEC("tc")
int tc_deny_icmp(struct __sk_buff *skb) {
    void *data_end = (void *)(long)skb->data_end;
    void *data = (void *)(long)skb->data;

    struct ethhdr *eth_hdr = data;
    if ((void *)eth_hdr + sizeof(*eth_hdr) > data_end || eth_hdr->h_proto != bpf_htons(ETH_P_IP)) {
        return TC_ACT_OK;
    }

    struct iphdr *ip_hdr = (void *)eth_hdr + sizeof(*eth_hdr);
    if ((void *)ip_hdr + sizeof(*ip_hdr) > data_end) {
        return TC_ACT_OK;
    }

    if (ip_hdr->protocol == IPPROTO_ICMP) {
        struct ipv4_lpm_key key = {
            .prefixlen = 32,
            .data = ip_hdr->daddr
        };

        if (!bpf_map_lookup_elem(&ipv4_lpm_map, &key)) {
            return TC_ACT_SHOT;
        }
    }

    return TC_ACT_OK;
}

cmd/main.go

#include "../headers/vmlinux.h"
#include "../headers/bpf_endian.h"
#include "../headers/bpf_helpers.h"

#define TC_ACT_SHOT 2
#define TC_ACT_OK 0

#define ETH_P_IP 0x0800

// 定义key
struct ipv4_lpm_key {
    __u32 prefixlen;
    __u32 data;
};

// 定义lpm map
struct {
    __uint(type, BPF_MAP_TYPE_LPM_TRIE);
    __type(key, struct ipv4_lpm_key);
    __type(value, __u32);
    __uint(map_flags, BPF_F_NO_PREALLOC);
    __uint(max_entries, 255);
    // 本地持久化map
    __uint(pinning, LIBBPF_PIN_BY_NAME);
} ipv4_lpm_map SEC(".maps");

struct ipv4_lpm_key *unused_ipv4_lpm_key __attribute__((unused));

char __license[] SEC("license") = "Dual MIT/GPL";

SEC("tc")
int tc_deny_icmp(struct __sk_buff *skb) {
    void *data_end = (void *)(long)skb->data_end;
    void *data = (void *)(long)skb->data;

    struct ethhdr *eth_hdr = data;
    if ((void *)eth_hdr + sizeof(*eth_hdr) > data_end || eth_hdr->h_proto != bpf_htons(ETH_P_IP)) {
        return TC_ACT_OK;
    }

    struct iphdr *ip_hdr = (void *)eth_hdr + sizeof(*eth_hdr);
    if ((void *)ip_hdr + sizeof(*ip_hdr) > data_end) {
        return TC_ACT_OK;
    }

    if (ip_hdr->protocol == IPPROTO_ICMP) {
        struct ipv4_lpm_key key = {
            .prefixlen = 32,
            .data = ip_hdr->daddr
        };

        if (!bpf_map_lookup_elem(&ipv4_lpm_map, &key)) {
            return TC_ACT_SHOT;
        }
    }

    return TC_ACT_OK;
}

编译运行

rm -f icmp/drop-icmp.o
clang -c icmp/drop-icmp.c -o icmp/drop-icmp.o -target bpf -O2 -g
go generate ./cmd
go build -o ./cmd/ebpf-test ./cmd/.
./cmd/ebpf-test

从C结构体到Go结构体

cilium/ebpf使用反射把eBPF map内的数据转为 go结构体,完成内核态与用户态之间传输。
用户态手动定义结构体的问题在于,除了首字母大写,go-binary库不是简单的memcpy,可能会让go结构体成员读到的值是错误的。
推荐自动生成Go结构体,bpf2go -type参数指定C结构体类型,C代码中加上struct key类型 *unused_xxx __attribute__((unused));

参考资料

https://docs.kernel.org/next/bpf/map_lpm_trie.html

标签:__,hdr,eBPF,lpm,LPM,key,data,路由,struct
From: https://www.cnblogs.com/WJQ2017/p/18172130

相关文章

  • Django - 初探路由
    目录路由定义规则路由定义规则准备工作:新建项目MyDjango,新建Appindex,在项目的index文件夹里新添加一个空白内容的.py文件,命名为urls.py。项目结构如下图:在App(index文件夹)里添加urls.py是将所有属于App的路由都写入该文件中,这样更容易管理和区分每个App的路由地址,而MyD......
  • 在Linux中,如何设置网络路由?
    在Linux中设置网络路由,通常涉及到使用route或ip命令来配置静态路由。以下是设置网络路由的步骤:查看当前路由表:在开始设置之前,可以使用route-n或iproute命令查看当前的路由表,以了解现有的路由信息。添加静态路由:如果需要添加一个新的静态路由,可以使用routeadd命令。例如,要......
  • 【网络知识系列】Windows路由表详解
    对于路由器的路由表,大家很熟悉,但是Windows的路由表,了解的人不多。一、Windows路由表条目解释1.1查看网卡信息使用ipconfig/all命令查看网卡信息。1.2查看路由表信息使用routeprint命令查看路由表信息。【活动路由】:ActiveRoutes【网络目标/目标网段】:Networkde......
  • 路由策略(普通路由,默认路由)和策略路由
    转自:https://blog.csdn.net/qingdao666666/article/details/114088829 路由策略和策略路由路由策略是根据一些规则,使用某种策略改变规则中/影响路由发布、接收或路由选择/的参数而改变路由发现的结果,最终改变的是路由表的内容。是在路由发现的时候产生作用。策略路由是尽管......
  • nat和路由的优先级
    nat转换和路由的优先级对内,是先目的nat 再 路由对外,是先路由 再 源nat关于NAT(网络地址转换)和路由的“优先级”,实际上它们各自在网络中扮演着不同的角色,并且在不同的网络层和操作中有着自己的顺序和逻辑。路由优先级:路由优先级也被称为路由的“管理距离”,是一个正整......
  • 38.Vue路由的简单学习整理
    关于vue路由这是关于前端的知识我大致就理解为其为跳转规则html中跳转想一下jsp跳转或者直接a标签跳转这个为人家规范的跳转这是vscode用到一些小插件{图标和idea键盘操作挺不错的}当然你需要vue插件否则无法识别vue还有就是node.js的安装就不说了首先分为前......
  • Linux基础——主机域名解析默认使用IPV6路由
    一、问题描述主机访问内网存储网段,发现域名默认解析的IPV6地址。ping访问ipv4地址正常通讯。主机本地解析/etc/resolv.conf的DNS配置正常。#ping域名默认解析IPV6地址Pingnasgroup.xxxx.xxxx.com#pingipv4地址正常ping-4nasgroup.xxxx.xxxx.com#查看本地DNS配......
  • 计算机网络中的路由器和家里的路由器有什么区别?
    计算机网络中的路由器和家里的路由器有什么区别?集线器是什么?什么叫一个网段?一个IP地址只能给一台机器用么?一台机器只能有一个IP地址么?“这里需要注意“发送方的IP”地址不是指计算机的IP,而是指网卡对应的IP,因为IP不是分配给计算机的,而是分配给网卡的,当一个计算机有多个网卡......
  • k8s kube-proxy 负载均衡路由策略 IPVS 为什么iptables 更高效
    环境lsb_release-aNoLSBmodulesareavailable.DistributorID: UbuntuDescription: Ubuntu24.04LTSRelease: 24.04Codename: noble先说原理iptables如果服务过多或者pod过多就要则添加海量的iptabes规则iptables使用的具体算法主要是线性搜索,也可以称为顺......
  • Day01 Web服务搭建&站库分离&路由访问
    常规的Web应用搭建:1.购买云服务器,购买域名2.云服务器去搭建中间件windowsserver安装web角色后默认可以直接通过域名打开网站首页3.下载并上传Web程序源码zblog源码官网可下载4.添加网站并绑定域名目录域名解析设置:二级域名ablog.whgojp.top解析到该服务器zblog程序......