- 论坛徽章:
- 0
|
内核版本2.6.30
由于之前一直在2.4版本的内核,现在刚刚改用2.6.30,其内核一些数据结构和实现机制都发送了改变,因此变写了几个小程序去验证性的跑一下,结果却发现了这个另我费解的问题。。。
本意是在测试最新版本内核中连接跟踪模块的使用情况,在新版本内核中通过struct nf_conn代替之前的ip_conntrack结构,但其中主要的一个数据结构
struct nf_conntrack_tuple_hash tuplehash[IP_CT_DIR_MAX]并没有太大改变。
好了,问题来了,按照道理说这个连接数组中 IP_CT_DIR_ORIGINAL代表的应该是原始方向的数据包,其源地址应该与ip头部中的源地址是相同的,而IP_CT_DIR_REPLY代表回复方向的数据包,其目的地址才应该为本机地址。(这是我之前的理解)
但是在我写的一个小测试用例中,得到的结果恰恰相反,ORIGINAL方向的连接的目的地址才是ip头部中的源地址,RELAY方向连接的源地址才是ip头部中的目的地址,很是困惑,想不明白,难道说是我之前对于连接跟踪方向一直理解错了吗?。。。
现在贴一下我的代码以及测试结果,有些长,各位看官不要嫌麻烦,因此这个问题真的很困扰我,急求给为牛人解惑,小弟不胜感激。。。。- #include <linux/module.h>
- #include <linux/init.h>
- #include <linux/kernel.h>
- #include <linux/types.h>
- #include <linux/errno.h>
- #include <linux/sched.h>
- #include <linux/slab.h>
- #include <linux/fs.h>
- #include <linux/poll.h>
- #include <linux/spinlock.h>
- #include <linux/ioctl.h>
- #include <linux/proc_fs.h>
- #include <linux/list.h>
- #include <linux/param.h>
- #include <asm/uaccess.h>
- #include <asm/atomic.h>
- #include <linux/skbuff.h>
- #include <linux/in.h>
- #include <linux/ip.h>
- #include <linux/tcp.h>
- #include <linux/udp.h>
- #include <linux/icmp.h>
- #include <linux/netdevice.h>
- #include <linux/netfilter.h>
- #include <linux/netfilter_ipv4.h>
- #include <linux/netfilter/nf_conntrack_tuple_common.h>
- #include <net/netfilter/nf_conntrack.h>
- #include <linux/byteorder/generic.h>
- #include <linux/if_arp.h>
- #include <linux/if_ether.h>
- #include <linux/if_packet.h>
- #include <linux/delay.h>
- #define HASH_SIZE 1024
- static unsigned int
- conn_hook(unsigned int hook,
- struct sk_buff *skb,
- const struct net_device *indev,
- const struct net_device *outdev,
- int (*okfn)(struct sk_buff *))
- {
- struct nf_conn *conn;
- struct nf_conntrack_tuple_hash tuple_list;
- struct nf_conntrack_tuple orig_tuple;
- struct nf_conntrack_tuple relay_tuple;
- struct iphdr *iph;
- struct tcphdr *tcph;
- u32 ip_saddr;
- u32 ip_daddr;
-
- if(!skb)
- {
- return NF_ACCEPT;
- }
- printk("Hook functions\n");
- //获取连接跟踪数据结构
- conn = (struct nf_conn *)(skb->nfct);
- if(!conn)
- {
- printk("no nf_conntrack \n");
- return NF_ACCEPT;
- }
-
- #if 1
- iph = ip_hdr(skb);
- tcph = tcp_hdr(skb);
- printk("ipv4 src addr: %d.%d.%d.%d,dst addr:%d.%d.%d.%d\n", NIPQUAD(iph->saddr),NIPQUAD(iph->daddr));
- printk("ipv4 tcp src port %d, dst port %d\n",tcph->source,tcph->dest);
- tuple_list = conn->tuplehash[IP_CT_DIR_REPLY];
- orig_tuple = conn->tuplehash[IP_CT_DIR_ORIGINAL].tuple;
- relay_tuple = conn->tuplehash[IP_CT_DIR_REPLY].tuple;
- ip_saddr = orig_tuple.src.u3.ip;
- ip_daddr = orig_tuple.dst.u3.ip;
- printk("ipv4 original src addr: %d.%d.%d.%d,dst src addr: %d.%d.%d.%d\n", NIPQUAD(ip_saddr),NIPQUAD(ip_daddr));
- printk("src original port: %d,dst prot: %d\n",orig_tuple.src.u.tcp.port,orig_tuple.dst.u.tcp.port);
- ip_saddr = relay_tuple.src.u3.ip;
- ip_daddr = relay_tuple.dst.u3.ip;
- printk("ipv4 relay src addr: %d.%d.%d.%d,dst src addr: %d.%d.%d.%d\n", NIPQUAD(ip_saddr),NIPQUAD(ip_daddr));
- printk("src relay port: %d,dst prot: %d\n",relay_tuple.src.u.tcp.port,relay_tuple.dst.u.tcp.port);
- #endif
- return NF_ACCEPT;
- }
- static struct nf_hook_ops conn_hook_ops = {
- .hook = conn_hook,
- .pf = PF_INET,
- .hooknum = NF_INET_POST_ROUTING,
- .priority = NF_IP_PRI_LAST-1,
- };
- static int conn_init(void)
- {
- int ret = 0;
- //注册钩子
- ret = nf_register_hook(&conn_hook_ops);
- if (ret < 0)
- {
- printk("register isatap hook ops error!\n");
- return -ENOMEM;
- }
- return 0;
- }
- static void conn_exit(void)
- {
- nf_unregister_hook(&conn_hook_ops);
- printk("Unregister conntrack hook ok\n");
- return;
- }
- module_init(conn_init);
- module_exit(conn_exit);
- MODULE_LICENSE("GPL");
复制代码 然后使运行结果;- Hook functions
- ipv4 src addr: 192.168.1.4,dst addr:192.168.1.221
- ipv4 tcp src port 5632, dst port 2824
- ipv4 original src addr: 192.168.1.221,dst src addr: 192.168.1.4
- src original port: 2824,dst prot: 5632
- ipv4 relay src addr: 192.168.1.4,dst src addr: 192.168.1.221
- src relay port: 5632,dst prot: 2824
- Hook functions
- ipv4 src addr: 192.168.1.4,dst addr:192.168.1.221
- ipv4 tcp src port 5632, dst port 2824
- ipv4 original src addr: 192.168.1.221,dst src addr: 192.168.1.4
- src original port: 2824,dst prot: 5632
- ipv4 relay src addr: 192.168.1.4,dst src addr: 192.168.1.221
- src relay port: 5632,dst prot: 2824
- Hook functions
- ipv4 src addr: 192.168.1.4,dst addr:192.168.1.221
- ipv4 tcp src port 5632, dst port 2824
- ipv4 original src addr: 192.168.1.221,dst src addr: 192.168.1.4
- src original port: 2824,dst prot: 5632
- ipv4 relay src addr: 192.168.1.4,dst src addr: 192.168.1.221
- src relay port: 5632,dst prot: 2824
- Hook functions
- ipv4 src addr: 192.168.1.4,dst addr:192.168.1.221
- ipv4 tcp src port 5632, dst port 10760
- ipv4 original src addr: 192.168.1.221,dst src addr: 192.168.1.4
- src original port: 10760,dst prot: 5632
- ipv4 relay src addr: 192.168.1.4,dst src addr: 192.168.1.221
- src relay port: 5632,dst prot: 10760
复制代码 从这个结果来看,ip首部的源地址和目的地址对应的是relay方向的连接包,通过tcp头部的端口号也证明了这一点。。。
而且我刚刚看了下ipv4_pkt_to_tuple,它所做的工作的确是从ip首部自动的源地址开始,读取两个32字节的变量,分别赋给tuple中的源地址和目的地址,按照道理说应该不会出错啊,可是我怎么得出了这么个结果。。。
这个真的很困惑,本人也是刚开始学Netfilter不久,还请各位高手帮忙解答。。。 |
|