龙蜥开源内核追踪利器 Surftrace:协议包解析效率提升 10 倍! | 龙蜥技术
一、理解 Linux 内核协议栈
1.1 网络报文分层结构
1.2 sk_buff 结构体
unsignedchar *head, *data;
1.3 内核网络协议栈地图
不难发现,上图中几乎所有函数都涉及到 skb 结构体处理,因此要想深入了解网络报文在内核的处理过程,skb->data 应该就是最理想的引路蜂。
二、Surftrace 对网络报文增强处理
skb->data 指针在不同网络层指向的协议头并不固定; 除了获取当前结构内容,还有获取上一层报文内容的需求,比如一个我们在 udphdr结构体中,是无法直接获取到 udp 报文内容; 源数据呈现不够人性化。如 ipv4 报文 IP 是以一个 u32 数据类型,可读性不佳,过滤器配置困难。
2.1 网络协议层标记处理
staticint__netif_receive_skb_core(struct sk_buff *skb, bool pfmemalloc, struct packet_type **ppt_prev);
surftrace 'p __netif_receive_skb_core proto=@(struct iphdr *)l3%0->protocol`
可以跨协议层向上解析报文结构体,如在 l3 层去分析 struct icmphdr 中的数据成员 不可以跨协议层向下解析报文结构体,如在 l4 层去分析 struct iphdr 中的成员
2.2 扩充下一层报文内容获取方式
data=@(struct icmphdr*)l3%0->sdata[1]
2.3 IP 和字节序模式转换
前缀名 | 数据输出形式 | 数据长度(字节) |
ip_ | a.b.c.d | ip字符串 |
b16_ | 10 进制 | 2 |
b32_ | 10 进制 | 4 |
b64_ | 10 进制 | 8 |
B16_ | 16 进制 | 2 |
B32_ | 16 进制 | 4 |
B64_ | 16 进制 | 8 |
2.4 牛刀小试
intip_output(struct net *net, struct sock *sk, struct sk_buff *skb)
surftrace 'p ip_output proto=@(struct iphdr*)l3%2->protocol ip_dst=@(struct iphdr*)l3%2->daddr b16_dest=@(struct udphdr*)l3%2->dest comm=$comm body=@(struct udphdr*)l3%2->Sdata[0] f:proto==17&&ip_dst==10.0.1.221&&b16_dest==9988'
surftrace 'p ip_output proto=@(struct iphdr*)l3%2->protocol ip_dst=@(struct iphdr*)l3%2->daddr b16_dest=@(struct udphdr*)l3%2->dest comm=$comm body=@(struct udphdr*)l3%2->Sdata[0] f:proto==17&&ip_dst==10.0.1.221&&b16_dest==9988' echo 'p:f0 ip_output proto=+0x9(+0xe8(%dx)):u8 ip_dst=+0x10(+0xe8(%dx)):u32 b16_dest=+0x16(+0xe8(%dx)):u16 comm=$comm body=+0x1c(+0xe8(%dx)):string' >> /sys/kernel/debug/tracing/kprobe_events echo 'proto==17&&ip_dst==0xdd01000a&&b16_dest==1063' > /sys/kernel/debug/tracing/instances/surftrace/events/kprobes/f0/filter echo 1 > /sys/kernel/debug/tracing/instances/surftrace/events/kprobes/f0/enable echo 0 > /sys/kernel/debug/tracing/instances/surftrace/options/stacktrace echo 1 > /sys/kernel/debug/tracing/instances/surftrace/tracing_on <...>-2733784 [014] .... 12648619.219880: f0: (ip_output+0x0/0xd0) proto=17 ip_dst=10.0.1.221 b16_dest=9988 comm="nc" body="Hello World\! @"
三、实战:定位网络问题
3.1 问题背景
3.2 surftrace 跟踪
surftrace 'p dev_queue_xmit proto=@(struct iphdr *)l2%0->protocol ip_dst=@(struct iphdr *)l2%0->daddr f:proto==1&&ip_dst==192.168.1.3' -s
3.3 锁定丢包点
rc = q->enqueue(skb, q, &to_free) & NET_XMIT_MASK;
surftrace 'p dev_queue_xmit+678 pfun=%bx'
四、总结
【1】《TCP/IP详解》
【2】《Linux内核设计与实现》
【3】《深入理解 Linux 网络技术内幕》
https://github.com/aliyun/surftrace/blob/master/ReadMe.md
龙蜥社区系统运维 SIG 致力于打造一个集主机管理、配置部署、监控报警、异常诊断、安全审计等一系列功能的自动化运维平台。
欢迎更多开发者加入系统运维 SIG:网址:https://openanolis.cn/sig/sysom邮件列表:sysom@lists.openanolis.cnsurftracel链接:https://gitee.com/anolis/surftrace
加入微信群:添加社区助理-龙蜥社区小龙(微信:openanolis_assis),备注【龙蜥】与你同在;加入钉钉群:扫描下方钉钉群二维码。欢迎开发者/用户加入龙蜥社区(OpenAnolis)交流,共同推进龙蜥社区的发展,一起打造一个活跃的、健康的开源操作系统生态!
龙蜥社区(OpenAnolis)由企事业单位、高等院校、科研单位、非营利性组织、个人等在自愿、平等、开源、协作的基础上组成的非盈利性开源社区。龙蜥社区成立于 2020 年 9 月,旨在构建一个开源、中立、开放的Linux 上游发行版社区及创新平台。
龙蜥社区成立的短期目标是开发龙蜥操作系统(Anolis OS)作为 CentOS 停服后的应对方案,构建一个兼容国际 Linux 主流厂商的社区发行版。中长期目标是探索打造一个面向未来的操作系统,建立统一的开源操作系统生态,孵化创新开源项目,繁荣开源生态。
目前,龙蜥OS 8.4已发布,支持 X86_64 、Arm64、LoongArch 架构,完善适配 Intel、兆芯、鲲鹏、龙芯等芯片,并提供全栈国密支持。
欢迎下载:
https://openanolis.cn/download
加入我们,一起打造面向未来的开源操作系统!
https://openanolis.cn
往期精彩推荐