可以看到它加载了几个插件,来实现上述功能,运行时候,捕获进程数据、UDP数据、DNS的信息,以及监控到的java运行程序信息等,并打印,当然可以自己方便扩展 。
三 处理流程3.1 流程处理说明为了看懂代码,特意学习了下golang,大概对流程有了了解, 启动点是main.go 核心代码,加载各个模块代码,进行初始化和运行:
for k, module := range user.GetModules() {if module.Name() != "EBPFProbeBPFCall" {//continue //模块启用临时开关}logger.Printf("start to run %s module", k)//初始化err := module.Init(ctx, logger)if err != nil {panic(err)}// 加载ebpf,挂载到hook点上,开始监听go func(module user.IModule) {err := module.Run()if err != nil {logger.Fatalf("%v", err)}}(module) }
每个功能以一个模块的形式来运行,module是定义的一组接口,如下
type IModule interface { // Init 初始化 Init(context.Context, *log.Logger) error // Name 获取当前module的名字 Name() string // Run 事件监听感知 Run() error // Start 启动模块 Start() error // Stop 停止模块 Stop() error // Close 关闭退出 Close() error SetChild(module IModule) Decode(*ebpf.Map, []byte) (string, error) Events() []*ebpf.Map DecodeFun(p *ebpf.Map) (IEventStruct, bool)}
在user的目录下的imodule.go代码文件中定义,里面定义了相关方法的基本实现 。然后各个模块把自己注册到全局的map中,Go语言比较有意思map的定义比较奇葩,如下:
var modules = make(map[string]IModule)
以string作为key,IModule作为value的map 变量modules,通过开放函数:
func GetModules() map[string]IModule { return modules}
返回 。核心模块的类(结构体)的类图如下:
文章插图
运行的整体流程
文章插图
- 将c代码开发的proc_kern.c等ebpf程序,通过LLVM编译成 ebuf的byte code 字节码;
- 利用go-bindata 将字节码文件转成go文件,为assets/ebpf_probe.go;
- main.go 获取模块组信息,运行模块初始化;
- main.go 调用模块的Run方法,Run方法调用IModule接口的start方法,在这里面通过bpfManager加载epbf_probe.go字节码;
- Module.ReadEvent 获取事件的map,判断map类型,按照类型读取map数据(读取之前判断是否结束),读取数据后,通过Decode方法进行解码,Decode 需要获取解码函数,然后根据不同的event进行解码 。6.解码结束后,通过Write方法写到屏幕上,或者写到ES中去 。
- 基于bcc开发ebpf程序的c代码,代码运行在内核中的 。
- 实现特定事件处理接口,即字节码转成具体的结构体成员 。
- 开发go的Module,加载ebpf的字节码,注册等;
[ehids/ebpfmanager: A golang ebpf libary base on cilium/ebpf and datadog/ebpf. (github.com)](https://github.com/ehids/ebpfmanager)
推荐阅读
- 基于零信任的安全架构
- 使用Java带你打造一款简单的外卖系统
- 一款支持直播的开源录屏工具
- 教你编译一个基于arm的Linux内核,并用qemu模拟器测试
- 基于机器学习的自适应码率算法的进一步探索与改进
- 基于Modbus协议实现Openplc与Kingview的仿真通讯与模拟测试
- 运动手环基本介绍 运动手环怎么样
- 一款能够让chrome浏览器速度提升3倍的软件
- 如何挑选一款字体显示出色的显示器?这些问题值得注意
- 基于oAuth的授权登陆