本文共 4745 字,大约阅读时间需要 15 分钟。
本篇文章使用netfilter实现抓包并进行简单数据包的解析
eth_hdr
, ip_hdr
,tcp_hdr
分别是用过skb取以太网头部,ip头部,tcp头部
ntohs
将网络字节序转换为主机字节序 由于内核中没有inet_ntoa
函数,所以自己写了个函数将int的ip地址转换为点分十进制格式的ip地址 先转换为主机字节序ntohl(iphdr->daddr)
,然后将int类型的ip地址转换为2进制然后分别取第1,2,3,4个字节用十进制打印出来即可。 kfifo_alloc
队列的初始化:
/** * kfifo_alloc - dynamically allocates a new fifo buffer * @fifo: pointer to the fifo * @size: the number of elements in the fifo, this must be a power of 2 * @gfp_mask: get_free_pages mask, passed to kmalloc() * * This macro dynamically allocates a new fifo buffer. * * The number of elements will be rounded-up to a power of 2. * The fifo will be release with kfifo_free(). * Return 0 if no error, otherwise an error code. */#define kfifo_alloc(fifo, size, gfp_mask) \__kfifo_int_must_check_helper( \({ \ typeof((fifo) + 1) __tmp = (fifo); \ struct __kfifo *__kfifo = &__tmp->kfifo; \ __is_kfifo_ptr(__tmp) ? \ __kfifo_alloc(__kfifo, size, sizeof(*__tmp->type), gfp_mask) : \ -EINVAL; \}) \)
代码实现:
/****************************************************************************** 文 件 名 : capkt.c 版 本 号 : V1.1 负 责 人 : Sophisticated 生成日期 : 2018年10月30日 最近修改 : 文件描述 : netfilter抓包函数 函数列表 : capkt_hook capture_exit capture_init print_inet_ntoa 修改历史 : 1.日 期 : 2018年10月30日 作 者 : Sophisticated 修改内容 : 创建文件******************************************************************************/#include#include #include #include #include #include #include #include #include #include #include #include #include #define FIFO_SIZE 4096struct kfifo fifo;/*将32位int类型ip地址转化为点分十进制格式的ip地址*/void print_inet_ntoa(u32 ina){ printk("%d.%d.%d.%d", (ina & 0xff000000) >> (6 * 4), (ina & 0x00ff0000) >> (4 * 4), (ina & 0x0000ff00) >> (2 * 4), ina & 0x000000ff); return;}int id = 1;/***************************************************************************** 函 数 名 : capkt_hook 功能描述 : 钩子函数的实现 输入参数 : void *priv struct sk_buff *skb const struct nf_hook_state *state 输出参数 : 无 返 回 值 : static unsigned int 调用函数 : 被调函数 : 修改历史 : 1.日 期 : 2018年10月30日 作 者 : Sophisticated 审 核 人 : # 修改内容 : 新生成函数*****************************************************************************/static unsigned int capkt_hook(void *priv,struct sk_buff *skb,const struct nf_hook_state *state){ /*设置了抓取十个数据包完毕,测试*/ if (id < 10){ struct ethhdr *ethhdr = eth_hdr(skb); struct iphdr *iphdr = ip_hdr(skb); struct tcphdr *tcphdr = tcp_hdr(skb); printk(KERN_ALERT "id: %d\n",id); printk("eth protocol: %x\n",ntohs(ethhdr->h_proto)); printk("ip protocol: %x\n",iphdr->protocol); printk("src mac:"); int i = 0; for (i; i < 6; i++) { printk("%02x:",ethhdr->h_source[i]); } printk("\n"); printk("dst mac:"); int j = 0; for (j; j < 6; j++) { printk("%02x:",ethhdr->h_dest[j]); } printk("\n"); printk("version: %d\n",iphdr->version); printk("ttl: %d\n",iphdr->ttl); printk("src ip:"); printk("%ld\n", ntohl(iphdr->saddr)); print_inet_ntoa(ntohl(iphdr->saddr)); printk("\n"); printk("dst ip:"); printk("%ld\n", ntohl(iphdr->daddr)); print_inet_ntoa(ntohl(iphdr->daddr)); printk("\n"); printk("src port:"); printk("%d\n",ntohs(tcphdr->source)); printk("dst port:"); printk("%d\n",ntohs(tcphdr->dest)); id++; /*将抓取的数据包放入队列*/ kfifo_in(&fifo, skb, sizeof(*skb)); int len = kfifo_len(&fifo); int size = kfifo_size(&fifo); printk("kfifo size: %d\n",size); printk("kfifo length: %d\n",len); } return NF_ACCEPT;}struct nf_hook_ops capture_hook_ops = { .hook = capkt_hook, .pf = NFPROTO_IPV4, .hooknum = NF_INET_PRE_ROUTING, .priority = 0,};/***************************************************************************** 函 数 名 : capture_init 功能描述 : 模块初始化函数 输入参数 : void 输出参数 : 无 返 回 值 : static 调用函数 : 被调函数 : 修改历史 : 1.日 期 : 2018年10月30日 作 者 : Sophisticated 审 核 人 : # 修改内容 : 新生成函数*****************************************************************************/static int __init capture_init(void){ if (kfifo_alloc(&fifo, FIFO_SIZE, GFP_KERNEL)) { printk("kfifo_alloc fail!\n"); } if (nf_register_hook(&capture_hook_ops) != 0) { printk("netfilter register fail!\n"); return -1; } printk("capture module insert success!\n"); return 0;}/***************************************************************************** 函 数 名 : capture_init 功能描述 : 模块移除函数 输入参数 : void 输出参数 : 无 返 回 值 : static 调用函数 : 被调函数 : 修改历史 : 1.日 期 : 2018年10月30日 作 者 : Sophisticated 审 核 人 : # 修改内容 : 新生成函数*****************************************************************************/static int __exit capture_exit(void){ kfifo_free(&fifo); nf_unregister_hook(&capture_hook_ops); printk("capture module remove success!\n"); return;}module_init(capture_init);module_exit(capture_exit);MODULE_LICENSE("GPL");
使用dmesg
命令或者cat /var/log/message
即可查看运行结果
转载地址:http://cuhpi.baihongyu.com/