一些项目始于精心规划,而skbx这个项目,始于我掉进Linux网络技术的“兔子洞”里,并且乐在其中。
起初的问题很简单:这个数据包到底去了哪里?
一个数据包可以穿越网络命名空间、路由决策、Netfilter、流量控制、XDP程序、隧道,经历克隆、复制乃至被丢弃的路径。在某个网络接口上抓到的包可能完全正确,但那仅仅展示了整个旅程中的一小段。而我想看到这段旅程的全貌,然后要能保存下来,在之后无需root权限就能回放,并且能了解捕获过程本身是否遗漏了某些观察点。
skbx正是一款为此而生的工具,一个使用Rust语言和CO-RE eBPF技术构建的Linux数据包路径“飞行记录器”。
在实时捕获期间,它会观测内核网络函数,并持续写入一个追加型的JSONL证据流。捕获结束后,这个数据流可以被回放和检查,而无需再次加载eBPF程序。整个工作流程直观地展示了从实时流量到最终事件解释的链路:实时流量进入系统,被CO-RE eBPF程序观测,生成的观测结果被封装进有边界的traceq JSONL数据流,再通过回放生成路由模式,最终用于解释某个具体事件。
它能观测Linux内核网络栈中从链路层到网络层的许多关键函数。不过,这并非要取代tcpdump或Wireshark,这些工具在处理抓包点的字节和协议问题上依然出色。skbx要解决的是数据包在本地Linux内核中的“路径”问题。同时,它也并非首个追踪数据包路径的工具,其灵感明确来自于pwru,后者展示了广泛运用eBPF进行数据包追踪的强大能力。
我尤其想探索的是,直播终端停止滚动刷新之后,证据去了哪里。实时追踪固然有用,但在排障工作中,特权会话结束后调查往往仍在继续。其他人可能需要检查捕获结果,我们可能想将它与一次成功的请求做对比,或许还要在bug报告中引用一个确切的事件。一个自动化系统或AI可能需要结构化的输入,但它绝不应被允许凭空捏造从未捕获到的观测结果。
为此,skbx的原生数据流,即traceq,拥有一个明确的“信封”结构:它以capture_start开始,中间是一系列event事件,最后以capture_end结束。这保证了流数据的完整性。每一个事件都会被赋予一个类似“event:111111111111111111111111”的稳定句柄。
回放过程会将有序的事件分组,转化为有边界的“路由模式”,这些模式同样会获得自己的句柄,如“route:1c0201e74424e253f8363577”。这样一来,事件的关联性就有了明确归属。
在数据流的末尾,页脚信息与事件本身同等重要。它记录了停止原因以及一系列可靠性计数器:包括内核预留失败次数、追踪器递归遗漏次数、读取失败次数、用户空间解码与增强失败次数,以及输出失败次数。如果页脚缺失,就意味着这个产物是不完整的;如果追踪器丢掉了观测结果,这种不确定性就会附加在最终结果上,而非被悄悄掩盖。我格外喜欢这个特性,因为追踪软件本身也是软件,它不应该假装自己无所不知。
热门跟贴