tracee源码初探(二)TCP处理流程

发布时间 2023-05-25 11:45:32作者: shininglight

handleEvents(ctx), processNetCaptureEvents(若开启Capture.Net)协程一直常驻,并等待netCapChannel消息通知. 当有事件传过来时, 程序先看该事件是否需要处理,也就是说tracee是上报所有事件的,然后过滤来处理事件。在tracee.go中的initBPF函数里t.bpfModule.InitPerfBuf( "net_cap_events", ...)函数,初始化了网络事件的PerfBuf, 然后tracee.bpf.c是挂载到内核的函数SEC("cgroup_skb/ingress")SEC("cgroup_skb/egress"),当有网络事件时,把事件放到net_cap_events map中并提交到用户空间。具体过程是:
挂载事件触发函数cgroup_skb_generic-->CGROUP_SKB_HANDLE(proto)->函数定义展开为cgroup_skb_handle_proto(ctx, neteventctx, nethdrs)-->CGROUP_SKB_HANDLE_FUNCTION(proto)【这一步映射是猜的】 如果是IP报文则解析IP报文属性,当解析出事TCP报文时调用CGROUP_SKB_HANDLE_FUNCTION(proto_tcp)-->cgroup_skb_capture-->cgroup_skb_capture_event(ctx, neteventctx, NET_PACKET_CAP_BASE)-->cgroup_skb_submit(&net_cap_events,ctx,neteventctx,event_type,nc->capture_length);
这里需要注意的一点是cgroup_skb_generic函数中用到的ingress和egress方向的已存储map:cgrpctxmap_in和cgrpctxmap_eg是由SEC("kprobe/__cgroup_bpf_run_filter_skb")挂载的函数实现存储起来的,cgroup_skb_generic只通过bpf_map_lookup_elem查找处理完之后再用bpf_map_delete_elem把对应的map数据删除。

当输入传送到用户空间的handleEvents函数来处理,会调用processEvents触发processor来处理(例如processWriteEvent等)然后是deriveEvents来处理派生函数NetPacketTCP对应的派生函数是derive.NetPacketTCP()解析TCP的各个字段,最后handleEvents调用sinkEvents把事件放入到t.config.ChanEvents中,然后tracee一直运行的Run()函数取出ChanEvents中的事件进行事件输出给用户可视端。

而如果config.Capture.Net配置开启还有processNetCapEvent来处理,刚好事件的ID是NET_PACKET_CAP_BASE, 最后写入pcap文件。