kernel 调试 打印IP地址

本文介绍了一个用于处理和打印IP头中源地址和目标地址的NIPQUAD宏定义及其使用方法。通过该宏,可以将IP地址转换为更易读的四字节数组形式,并在内核信息输出中展示。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

#define NIPQUAD(addr) \
((unsigned char *)&addr)[0], \
((unsigned char *)&addr)[1], \
((unsigned char *)&addr)[2], \
((unsigned char *)&addr)[3]

 

struct iphdr *nh;

struct sk_buff *skb;

nh = ip_hdr(skb);

printk(KERN_INFO "src: %u.%u.%u.%u, dst: %u.%u.%u.%u\n", NIPQUAD(nh->saddr), NIPQUAD(nh->daddr));

转载于:https://www.cnblogs.com/wangjq19920210/p/10331106.html

<think>我们已知用户希望在内核中筛选指定IP的skb数据包并打印其内存内容。结合引用[1]和[2]中关于skb处理流程和归属的说明,以及引用[3]中关于IP头的描述,我们可以通过以下步骤实现: 1. 在合适的内核位置(如网络层钩子)获取skb。 2. 解析skb的IP头,提取源IP或目的IP。 3. 与指定的IP地址进行比较,匹配则打印skb数据。 具体方法可以选择编写内核模块,使用netfilter钩子或kprobe来拦截skb。这里我们使用netfilter钩子,因为它相对简单且稳定。 步骤: 1. 编写内核模块,注册一个netfilter钩子(例如在NF_INET_PRE_ROUTING位置,这样可以尽早捕获数据包)。 2. 在钩子函数中,检查skb的IP头,提取IP地址(源IP或目的IP)。 3. 如果IP地址匹配指定的IP(比如192.168.1.100),则调用打印函数输出skb数据。 注意:由于IP数据包可能分片,我们这里假设只处理非分片包或第一个分片(因为IP头在第一个分片中)。如果需要处理所有分片,需要更复杂的处理。 代码示例: 首先,我们需要包含必要的头文件,并定义要过滤的IP地址(这里以IPv4为例):</think>### 如何在Linux内核中筛选指定IP的skb数据包并打印内存内容 在Linux内核中筛选指定IP的skb数据包并打印内存内容,需要结合网络协议解析和skb操作技术。以下是逐步实现方案,基于内核网络栈处理流程[^1]和skb数据结构特性[^2]: --- #### 1. **核心实现原理** - **筛选依据**:通过解析IP头部的源/目的IP地址(位于`skb->data`偏移位置)进行匹配[^3] - **拦截点选择**:推荐在`netif_receive_skb`之后的路由前阶段(如`NF_INET_PRE_ROUTING`),此时IP头完整且未修改[^1] - **内存打印**:使用`print_hex_dump`安全输出数据,避免越界访问 --- #### 2. **完整内核模块实现** ```c #include <linux/module.h> #include <linux/kernel.h> #include <linux/skbuff.h> #include <linux/ip.h> #include <linux/netfilter.h> #include <linux/netfilter_ipv4.h> #include <linux/inet.h> static struct nf_hook_ops nfho; static char *target_ip = "192.168.1.100"; // 要筛选的目标IP __be32 target_ip_n; // 网络字节序的IP地址 // 网络过滤钩子函数 unsigned int hook_func(void *priv, struct sk_buff *skb, const struct nf_hook_state *state) { struct iphdr *ip_header; if (!skb) return NF_ACCEPT; // 检查是否为IP数据包 if (skb->protocol != htons(ETH_P_IP)) return NF_ACCEPT; // 获取IPip_header = ip_hdr(skb); if (!ip_header) return NF_ACCEPT; // 检查IP地址匹配(源或目的) if (ip_header->saddr == target_ip_n || ip_header->daddr == target_ip_n) { printk(KERN_INFO "Matched SKB for IP: %pI4\n", &target_ip_n); // 打印完整IP头+前64字节负载 print_hex_dump(KERN_INFO, "SKB DATA: ", DUMP_PREFIX_OFFSET, 16, 1, skb->data, min(skb->len, sizeof(struct iphdr) + 64), true); } return NF_ACCEPT; } // 模块初始化 static int __init ip_filter_init(void) { // 转换IP为网络字节序 if (in4_pton(target_ip, -1, (u8 *)&target_ip_n, '\0', NULL) != 1) { printk(KERN_ERR "Invalid IP format\n"); return -EINVAL; } // 配置Netfilter钩子 nfho.hook = hook_func; nfho.hooknum = NF_INET_PRE_ROUTING; // 路由前拦截 nfho.pf = PF_INET; nfho.priority = NF_IP_PRI_FIRST; // 最高优先级 nf_register_net_hook(&init_net, &nfho); printk(KERN_INFO "IP filter module loaded. Target IP: %pI4\n", &target_ip_n); return 0; } // 模块卸载 static void __exit ip_filter_exit(void) { nf_unregister_net_hook(&init_net, &nfho); printk(KERN_INFO "IP filter module unloaded\n"); } module_init(ip_filter_init); module_exit(ip_filter_exit); MODULE_LICENSE("GPL"); ``` --- #### 3. **关键代码解析** 1. **IP地址匹配**: ```c in4_pton(target_ip, -1, (u8 *)&target_ip_n, '\0', NULL) // 字符串IP转网络字节序 ip_header->saddr == target_ip_n // 源IP匹配 ``` 使用内核标准函数`in4_pton`转换IP地址,支持点分十进制格式[^3] 2. **协议检查**: ```c skb->protocol != htons(ETH_P_IP) // 过滤非IPv4流量 ``` 确保仅处理IPv4数据包,避免解析错误 3. **安全打印**: ```c print_hex_dump(KERN_INFO, "SKB DATA: ", DUMP_PREFIX_OFFSET, 16, 1, skb->data, min(skb->len, sizeof(struct iphdr) + 64), true); ``` - 限制输出长度(IP头+64字节负载) - 十六进制+ASCII双格式输出 - `DUMP_PREFIX_OFFSET`显示内存偏移量 --- #### 4. **编译与使用** 1. **编译模块**: ```makefile obj-m += ip_filter.o all: make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules ``` 2. **加载模块**: ```bash sudo insmod ip_filter.ko target_ip=192.168.1.100 # 指定目标IP dmesg -w # 查看实时输出 ``` 3. **验证输出**: ``` [ 1234.567] Matched SKB for IP: 192.168.1.100 [ 1234.569] SKB DATA: 00000000: 45 00 00 54 00 00 40 00 40 01 8b 9d c0 a8 01 64 E..T..@.@......d [ 1234.571] SKB DATA: 00000010: c0 a8 01 01 08 00 4d 5a 00 01 00 01 41 41 41 41 ......MZ....AAAA ... ``` --- #### 5. **注意事项** 1. **性能影响**: - 生产环境建议添加匹配频率限制(如每10包打印1次) - 使用`static_key`控制调试开关 2. **分片处理**: - IP分片包需重组后解析,建议添加检查: ```c if (ip_header->frag_off & htons(IP_MF | IP_OFFSET)) return NF_ACCEPT; // 跳过非首片分片 ``` 3. **安全边界**: - 始终验证`skb->len >= sizeof(struct iphdr)` - 使用`skb_header_pointer`替代直接指针访问 4. **扩展功能**: - 添加`/proc`接口动态更新目标IP - 集成`jprobe`跟踪特定协议栈函数 > 此方案通过直接解析IP头部实现高效过滤,避免协议栈深层遍历[^1]。实际部署前需在测试环境验证,避免影响网络吞吐量[^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值