在NF_IP_PRE_ROUTING挂钩子修改skbuff问题
时间:2010-07-18
来源:互联网
以下代码是在2.6.31内核中执行的,根据send_rst改写的。但是代码存在以下几个问题:
1、捕包发现ip头的version字段为0,offset的值不为0,校验出错。
2、udp头的内容好像并没有更改。
3、us指针指向的内容并没有改变
4、经常死机
请大家帮我看看是哪里的问题
- #ifndef __KERNEL__
- #define __KERNEL__
- #endif
-
- #ifndef MODULE
- #define MODULE
- #endif
-
- #include <linux/module.h>
- #include <linux/kernel.h>
- #include <linux/skbuff.h>
- #include <linux/netfilter.h>
- #include <linux/netfilter_ipv4.h>
- #include <linux/ip.h>
- #include <linux/if_ether.h>
- #include <linux/netdevice.h>
- #include <linux/if_packet.h>
- #include <net/tcp.h>
- #include <net/udp.h>
- #include <asm/string.h>
-
- #define ETH "eth0"
- #define ETH_HLEN 14
- #define UDP_HLEN 8
- #define loc_swap(a,b) {(a)=(a)^(b);(b)=(a)^(b);(a)=(a)^(b);}
- #define DNSPORT 53
- #define MAC_FMT "%02x:%02x:%02x:%02x:%02x:%02x"
- #define MAC_ARG(x) ((u8*)(x))[0],((u8*)(x))[1],((u8*)(x))[2],((u8*)(x))[3],((u8*)(x))[4],((u8*)(x))[5]
- #define FLAGS 0x8003
-
- typedef struct _rfc1035_header rfc1035_header;
- struct _rfc1035_header {
- unsigned short id;
- unsigned int qr:1;
- unsigned int opcode:4;
- unsigned int aa:1;
- unsigned int tc:1;
- unsigned int rd:1;
- unsigned int ra:1;
- unsigned int rcode:4;
- unsigned short qdcount;
- unsigned short ancount;
- unsigned short nscount;
- unsigned short arcount;
- };
-
- unsigned int modify_dns(unsigned int hooknum,
- struct sk_buff *skb,
- const struct net_device *in,
- const struct net_device *out,
- int (*okfn)(struct sk_buff *))
- {
- struct net_device *dev;
- struct iphdr *iph = NULL;
- struct ethhdr *eth = NULL;
- struct udphdr *udph = NULL;
- unsigned char mac_temp[ETH_ALEN] = {0};
- unsigned int iph_len;
- char *dns_data;
- int data_len;
- rfc1035_header *qh;
- unsigned short *us;
- printk("before dev = in\n");
- dev = dev_get_by_name(&init_net, "eth0");
- if(NULL == dev)
- goto out;
-
- if(NULL == skb)
- return NF_ACCEPT;
- printk("before decide packet type\n");
- if((IPPROTO_UDP != (ip_hdr(skb)->protocol))
- && (DNSPORT != udp_hdr(skb)->dest))
- return NF_ACCEPT;
-
- iph = (struct iphdr *)ip_hdr(skb);
- iph_len = iph->ihl << 2;
- printk("iphdr_len=%d data_len=%d sip=%04x dip=%04x\n", iph_len, ntohs(iph->tot_len), iph->saddr, iph->daddr);
- udph = udp_hdr(skb);
- printk("source=%hu dest=%hu len=%d\n", ntohs(udph->source), ntohs(udph->dest), ntohs(udph->len));
- data_len = ntohs(udph->len) - UDP_HLEN;
- dns_data = (char *)udph + UDP_HLEN;
- printk("before modify dns data\n");
- qh = (rfc1035_header *) dns_data;
-
- us = (unsigned short *)(dns_data + 2);
- *us = *us | FLAGS;
- printk("flags=%hu\n", *us);
-
- loc_swap(iph->saddr, iph->daddr);
- loc_swap(udph->source, udph->dest);
- iph->ihl = sizeof(struct iphdr)/4;
- iph->tot_len = htons(skb->len);
-
- printk("source=%uh dest=%uh len=%d\n", ntohs(udph->source), ntohs(udph->dest), ntohs(udph->len));
- printk("before udp checksum\n");
- udph->check = 0;
- udph->check = ~csum_tcpudp_magic(iph->saddr, iph->daddr, ntohs(udph->len), IPPROTO_UDP, 0);
- iph->frag_off = htons("IP_DF");
- iph->id = 0;
- printk("before ip checksum\n");
- iph->check = 0;
- iph->check = ip_fast_csum((unsigned char *)iph, iph_len);
-
-
- printk("before skb_push\n");
- eth = (struct ethhdr *)skb_push(skb, ETH_HLEN);
- if(NULL == eth)
- goto out;
- if(NULL != eth->h_source)
- printk("SOURCE:" MAC_FMT "\n", MAC_ARG(eth->h_source));
- if(NULL != eth->h_dest)
- printk("DEST:" MAC_FMT "\n", MAC_ARG(eth->h_dest));
-
- printk("before swap mac adress\n");
- memcpy(mac_temp, (unsigned char *)eth->h_dest, ETH_ALEN);
- memcpy(eth->h_dest, (unsigned char *)eth->h_source, ETH_ALEN);
- memcpy(eth->h_source, mac_temp, ETH_ALEN);
-
-
- printk("before send packet\n");
- if (0 > dev_queue_xmit(skb))
- goto out;
- return NF_ACCEPT;
-
- out:
- printk("in out: ");
- if (NULL != skb)
- {
- printk("skb not null\n");
- dev_put(dev);
- kfree_skb(skb);
- }
- return NF_ACCEPT;
- }
-
- static struct nf_hook_ops dns_ops[] = {
- {
- .hook = modify_dns,
- .owner = THIS_MODULE,
- .pf = PF_INET,
- .hooknum = NF_IP_PRE_ROUTING,
- .priority = NF_IP_PRE_ROUTING,
- }
- };
-
- static int __init init(void)
- {
- int ret;
- printk("before nf_register_hooks\n");
- ret = nf_register_hooks(dns_ops, ARRAY_SIZE(dns_ops));
- if(ret < 0)
- {
- printk("can't register dns_ops!\n");
- return ret;
- }
- printk("insmod dns_ops ok!\n");
- return 0;
- }
-
- static void __exit fini(void)
- {
- nf_unregister_hooks(dns_ops, ARRAY_SIZE(dns_ops));
- printk("rmmod dns_ops ok!\n");
- }
-
- module_init(init);
- module_exit(fini);
- MODULE_LICENSE("GPL");
- MODULE_AUTHOR("KAL");
- MODULE_DESCRIPTION("MODIFY DNS PACKETS");
作者: kangle000 发布时间: 2010-07-18
作者: kangle000 发布时间: 2010-07-19
作者: @sky 发布时间: 2010-07-19
- .priority = NF_IP_PRE_ROUTING,
- iph = (struct iphdr *)ip_hdr(skb);
- iph_len = iph->ihl << 2;
- udph = udp_hdr(skb);
作者: platinum 发布时间: 2010-07-19
platinum 发表于 2010-07-19 09:29
谢谢,那个prio确实错了。但是ip头长度不就是iph->ihl *4 吗。那个udp指针是没问题的。udp_hdr调用了
- static inline unsigned char *skb_transport_header(const struct sk_buff *skb)
- {
- return skb->head + skb->transport_header;
- }
作者: kangle000 发布时间: 2010-07-19
你从哪里看到的 IP 头长度就是 iph->ihl * 4 了?
如果是这样,那么 iph->tot_len 又是做什么的?
建议恶补一下 TCP/IP 详解卷一的 IP 那一章,基本概念都错了!
1. static inline unsigned char *skb_transport_header(const struct sk_buff *skb)
2. {
3. return skb->head + skb->transport_header;
4. }
复制代码
来计算udp头
你能确保此时 skb->transport_header 的数据是正确的吗?
作者: platinum 发布时间: 2010-07-19
作者: @sky 发布时间: 2010-07-19
热门阅读
-
office 2019专业增强版最新2021版激活秘钥/序列号/激活码推荐 附激活工具
阅读:74
-
如何安装mysql8.0
阅读:31
-
Word快速设置标题样式步骤详解
阅读:28
-
20+道必知必会的Vue面试题(附答案解析)
阅读:37
-
HTML如何制作表单
阅读:22
-
百词斩可以改天数吗?当然可以,4个步骤轻松修改天数!
阅读:31
-
ET文件格式和XLS格式文件之间如何转化?
阅读:24
-
react和vue的区别及优缺点是什么
阅读:121
-
支付宝人脸识别如何关闭?
阅读:21
-
腾讯微云怎么修改照片或视频备份路径?
阅读:28