linux ebpf_防火墙拦截dns解析

linux ebpf_防火墙拦截dns解析自基于Netfilter的iptables取代ipchains之后,Linux防火墙技术貌似一直停留在iptables,虽然近年来nftables被宣称有取代iptables之势,但事实上并无起色。无论是晚期ipchains,还是iptables,或者nftables,其底层基础均是Netfilter,一个精心设计的五点HOOKs框架,在软件意义上,这个设计非常棒,但是涉及到单机性能问题,总是退…

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺

自基于Netfilter的iptables取代ipchains之后,Linux防火墙技术貌似一直停留在iptables,虽然近年来nftables被宣称有取代iptables之势,但事实上并无起色。

无论是晚期ipchains,还是iptables,或者nftables,其底层基础均是Netfilter,一个精心设计的五点HOOKs框架,在软件意义上,这个设计非常棒,但是涉及到单机性能问题,总是退让三分。

这让人不得开心颜,于是很多人花大量的时间精力投入到了防火墙优化中,当然,包括我自己在内。


如今,新一代的Linux防火墙技术出现了!是的,它就是基于eBPF的bpfilter!

eBPF是一个非常古老但最近才大行其道的技术,Linux内核中被埋下了越来越多的eBPF调用点,bpfilter正是基于这些非固定的,不断增多的HOOK点来其作用的,这和Netfilter固定的HOOK非常不同。

比如,XDP就是一个eBPF调用点。它位于网络协议栈的最底层,网卡层面,这里做数据包过滤非常高效,并且可以依托硬件特性将数据包过滤行为offload到硬件中,很棒的主意。

看起来非常令人遗憾的是,BPF(伯克利包过滤器)从名字上看虽然本身就是一个包过滤器,但是对于Linux系统而言,在包过滤领域,BPF除了用于抓包之外,在其它方面很少其关键作用。

不过,现在它的时代来了。事情正在起变化。

目前Linux内核中,XDP,TC,Socket是TCP/IP网络协议栈中三个关键的eBPF程序的调用点,可以想象,这种eBPF调用点会越来越多,它不像Netfilter那样是固定的5个或者说几个HOOK点。

所谓的eBPF调用点理解起来非常简单,就是在这些点上,内核会调用通过用户态灌进来的eBPF字节码,目前在网络协议栈领域最常用的eBPF调用点就是XDP了。

好了,大致框架就是以上这些,下面是试一试的时间。

为了让这一切run起来,我们要解决几个问题:

  • 如何编写eBPF过滤程序。
  • 如何编译eBPF过滤程序。
  • 如何将编译好的eBPF字节码灌进XDP。

目前,bpfilter的POC已经完美回到了上面的问题,详见:
https://lwn.net/Articles/747504/
https://www.netronome.com/blog/bpf-ebpf-xdp-and-bpfilter-what-are-these-things-and-what-do-they-mean-enterprise/
很棒的一个点就是,为了让iptables平滑过渡,bpfilter准备了一个非常trick的机制,可以将配置下发下来的iptables规则JIT编译成eBPF字节码到XDP。

然而这些都是宏观的东西,下面我来演示一下Step by Step的微观细节,我要解决一个实际问题,即:

  • 禁止enp0s3所有数据包。

如何编写eBPF程序呢?很容易,下面的C代码便是:

#include <linux/bpf.h>

#define __section(NAME) \ __attribute__((section(NAME), used))

__section("prog")
int drop_all(struct xdp_md *ctx)
{ 
   
	return XDP_DROP;
}

char __license[] __section("license") = "GPL";

如何编译它呢?

root@zhaoya-VirtualBox:~/xdp# clang -Wall -target bpf -c simple.c -o simple.o

如何使能它到enp0s3呢?

root@zhaoya-VirtualBox:~/xdp# ip link set dev enp0s3 xdp obj simple.o

作为骨灰级的Netfilter,iproute2玩家,我是一直跟随着最新进展,iproute2真的牛X到不行。

很多年前我玩Cisco ACL就知道,Cisco的做法是将ACL规则优化编译加载到网卡,如今Linux的eBPF字节码在XDP运行,也是一样的路子。

循序渐进,下面的例子稍微有点难度,需要自己来解析数据包,禁止所有的TCP数据包:

#include <linux/bpf.h>
#include <linux/in.h>
#include <linux/if_ether.h>
#include <linux/ip.h>

#define __section(NAME) __attribute__((section(NAME), used))

__section("prog")
int drop_tcp(struct xdp_md *ctx)
{ 
   
	int ipsize = 0;

	void *data = (void *)(long)ctx->data;
	struct iphdr *ip;

	ip = data + sizeof(struct ethhdr);

	if (ip->protocol == IPPROTO_TCP) { 
   
		return XDP_DROP;
	}

	return XDP_PASS;
}

char _license[] __section("license") = "GPL";

难道我们为了编写一条数据包过滤规则都要写个C程序吗?很多人并不具备编程能力,或者仅仅是不精通C,看起来根本没有必要必须写一个C程序。

好在有很多的前端可以帮我们生成字节码。

事实上我们常用的tcpdump就有这样的功能,当我们用-d,-dd执行tcpdump时,打印出来的就是过滤程序:

root@zhaoya-VirtualBox:~/xdp# tcpdump -i enp0s3 dst 11.22.33.44 -d
(000) ldh      [12]
(001) jeq      #0x800 jt 2 jf 4
(002) ld       [30]
(003) jeq      #0xb16212c jt 8 jf 9
(004) jeq      #0x806 jt 6 jf 5
(005) jeq      #0x8035 jt 6 jf 9
(006) ld       [38]
(007) jeq      #0xb16212c jt 8 jf 9
(008) ret      #262144
(009) ret      #0
root@zhaoya-VirtualBox:~/xdp# tcpdump -i enp0s3 dst 11.22.33.44 -dd
{ 
    0x28, 0, 0, 0x0000000c },
{ 
    0x15, 0, 2, 0x00000800 },
{ 
    0x20, 0, 0, 0x0000001e },
{ 
    0x15, 4, 5, 0x0b16212c },
{ 
    0x15, 1, 0, 0x00000806 },
{ 
    0x15, 0, 3, 0x00008035 },
{ 
    0x20, 0, 0, 0x00000026 },
{ 
    0x15, 0, 1, 0x0b16212c },
{ 
    0x6, 0, 0, 0x00040000 },
{ 
    0x6, 0, 0, 0x00000000 },
root@zhaoya-VirtualBox:~/xdp#

唉,又要搬家,这种日子持续了将近5年,终于快要结束了。作于两趟搬运之间的间隙,腰酸背痛!


浙江温江皮鞋湿,下雨进水不会胖。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/191103.html原文链接:https://javaforall.net

(0)
上一篇 2026年2月7日 下午8:15
下一篇 2026年2月7日 下午8:43


相关推荐

  • 无源汇上下界可行流_格怎么找最小上界和最大下界

    无源汇上下界可行流_格怎么找最小上界和最大下界给定一个包含 n 个点 m 条边的有向图,每条边都有一个流量下界和流量上界。给定源点 S 和汇点 T,求源点到汇点的最小流。输入格式第一行包含四个整数 n,m,S,T。接下来 m 行,每行包含四个整数 a,b,c,d 表示点 a 和 b 之间存在一条有向边,该边的流量下界为 c,流量上界为 d。点编号从 1 到 n。输出格式输出一个整数表示最小流。如果无解,则输出 No Solution。数据范围1≤n≤50003,1≤m≤125003,1≤a,b≤n,0≤c≤d≤21474836

    2022年8月9日
    6
  • CAN协议要点及车辆CAN协议激活成功教程

    CAN协议要点及车辆CAN协议激活成功教程一、CAN协议要点1.电压2.波形3.CAN报文概述CAN一共规定了5中类型的帧,帧也称为报文。CAN总线的数据帧有标准格式(StandardFormat)和扩展格式(ExtendedFormat)的区分。4.CAN报文编码格式Intel格式编码 当一个信号的数据长度不超过1Byte,并且信号在一个字节内实现时,该信号的高位(S_msb)将被放在该字节的高位,信号的低位(S_lsb)将被放在该字节的低位。 当一个信号的数据长度超过..

    2022年6月28日
    194
  • BitBlt参数详解[通俗易懂]

    BitBlt参数详解[通俗易懂]对BitBlt()这个函数的最后一个参数的意义一直不是太了解,只会使用SRCCOPY,最近的一个项目使用到了这个函数,但是要求要背景透明的将源绘制到目标区域上,源是背景色和字,怎么只拷贝字而把背景色透明化呢??我的解决方法是,把源的背景色绘制为白色,字为黑色,然后在BitBlt的时候最后一个参数用SRCAND,果然可以达到我要的效果,这是为什么呢?呵呵趁此机会好好看看这个参数介绍吧~~开始之前,首先要明白,绘制其实就是在给每一个像素点涂颜色,每种颜色都是由红蓝黄三要素组合而成,因此通过RGB颜色值可以

    2022年10月18日
    4
  • 怎么用nginx搭建文件服务器,使用nginx搭建简单文件服务器

    怎么用nginx搭建文件服务器,使用nginx搭建简单文件服务器最近再做一个博客 本想使用 fastdfs 标准的文件存储服务器 但考虑到资源占用问题 且使用 nginx 比较快速 且效果不差 于是采用 ngixn 搭建 nginx 搭建文件服务器 本质上就是 nginx 的静态文件访问配置 安装 nginxmac brewinstalln 直接下载解压就行 配置文件路径对 nginx conf 进行配置 mac 的 brew 安装后配置文件在 usr l

    2026年3月16日
    2
  • 采用J2EE架构

    采用J2EE架构J2EE 是目前业界公认的企业级信息系统的支撑体系结构 是各个系统和系统内部各个组成部分之间的粘合剂 J2EE 提供了跨平台的解决方案 提供了通用的 JDBC 数据库访问接口 无缝支持通过 XML 进行系统间和系统内部的数据传递 支持 LDAP 目录访问接口 在 J2EE 体系结构中 所有的技术都是开放

    2026年3月18日
    2
  • springboot——kaptcha

    springboot——kaptcha导入包: <dependency> <groupId>com.github.penggle</groupId> <artifactId>kaptcha</artifactId> <version>2.3.2</version> </dependency>配置类:p…

    2022年6月18日
    26

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号