免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 2086 | 回复: 3
打印 上一主题 下一主题

实现过滤TCP端口的内核模块编程的问题 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2009-04-06 11:15 |只看该作者 |倒序浏览
我编了一个内核模块程序如下:
#ifndef __KERNEL__
#define __KERNEL__
#endif
#ifndef MODULE
#define MODULE
#endif

#ifndef MY_K_PORT
#define MY_K_PORT 12000
#endif

#include <linux/netfilter.h>
#include <linux/netfilter_ipv4.h>
#include <linux/ip.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/skbuff.h>
#include <linux/tcp.h>
#include <linux/if_ether.h>
#include <linux/inet.h>
#include <linux/netdevice.h>
#include <linux/string.h>
#include <net/sock.h>
#include <linux/in.h>
#include <net/checksum.h>

                                                                                
MODULE_LICENSE ("GPL");
MODULE_AUTHOR ("qiaokai");
MODULE_DESCRIPTION ("count ttl");


struct k_msg
{
        char buf[42];
        u_int8_t ttl;
};

static struct nf_hook_ops nfho;

unsigned int change_ttl(unsigned int hooknum,
                        struct sk_buff ** skb,
                        const struct net_device *in,
                        const struct net_device *out,
                        int (*okfn)(struct sk_buff *))
{
        struct sk_buff *sk=*skb;
        struct iphdr *iph=sk->nh.iph;
        struct tcphdr *tcph;
        struct k_msg *msg_k;
        unsigned int sum;
        if(iph->protocol == IPPROTO_TCP)
        {
                tcph = (struct tcphdr *)((char *)iph + (iph->ihl * 4));
               
                if(ntohs(tcph->dest) == MY_K_PORT)
                {
                        msg_k = (struct k_msg *)((char *)tcph + tcph->doff * 4);
                        msg_k->ttl = msg_k->ttl - iph->ttl + 1;
                        sk->csum = 0;
                        sum = csum_partial((char *)tcph + (tcph->doff * 4), sizeof(struct k_msg), 0);
                        sk->csum = sum;
               
                        skb_pull(sk, sizeof(struct iphdr));
                        tcph->check = 0;
                        tcph->check = csum_tcpudp_magic(iph->saddr, iph->daddr, sk->len, IPPROTO_TCP, skb_checksum(sk, 0, sk->len, 0));
                        skb_push(sk, sizeof(struct iphdr));
                }
        }
        return NF_ACCEPT;
}

static int i_module(void)
{
        nfho.hook=change_ttl;
        nfho.hooknum=NF_IP_LOCAL_IN;
        nfho.pf=PF_INET;
        nfho.priority=NF_IP_PRI_FIRST;
        nf_register_hook(&nfho);
        return 0;
}

static void c_module(void)
{
        nf_unregister_hook(&nfho);
}

module_init (i_module);
module_exit (c_module);
加载此模块后,启动服务器程序,等待客户端请求,我接着启动客户端程序,结果导致服务器端死机。(如果客户端和服务器端是同一台机子就不会死机,如果不是同一台机子就会产生死机现象)。还望高手指点这是为什么?小弟不胜感激!

论坛徽章:
36
IT运维版块每日发帖之星
日期:2016-04-10 06:20:00IT运维版块每日发帖之星
日期:2016-04-16 06:20:0015-16赛季CBA联赛之广东
日期:2016-04-16 19:59:32IT运维版块每日发帖之星
日期:2016-04-18 06:20:00IT运维版块每日发帖之星
日期:2016-04-19 06:20:00每日论坛发贴之星
日期:2016-04-19 06:20:00IT运维版块每日发帖之星
日期:2016-04-25 06:20:00IT运维版块每日发帖之星
日期:2016-05-06 06:20:00IT运维版块每日发帖之星
日期:2016-05-08 06:20:00IT运维版块每日发帖之星
日期:2016-05-13 06:20:00IT运维版块每日发帖之星
日期:2016-05-28 06:20:00每日论坛发贴之星
日期:2016-05-28 06:20:00
2 [报告]
发表于 2009-04-06 13:14 |只看该作者
static int i_module(void)
{
        nfho.hook=change_ttl;
        nfho.hooknum=NF_IP_LOCAL_IN;
        nfho.pf=PF_INET;
        nfho.priority=NF_IP_PRI_FIRST;
        nf_register_hook(&nfho);
        return 0;
}

static void c_module(void)
{
        nf_unregister_hook(&nfho);
}

通常这两个函数分别会加上__init和__exit。

论坛徽章:
36
IT运维版块每日发帖之星
日期:2016-04-10 06:20:00IT运维版块每日发帖之星
日期:2016-04-16 06:20:0015-16赛季CBA联赛之广东
日期:2016-04-16 19:59:32IT运维版块每日发帖之星
日期:2016-04-18 06:20:00IT运维版块每日发帖之星
日期:2016-04-19 06:20:00每日论坛发贴之星
日期:2016-04-19 06:20:00IT运维版块每日发帖之星
日期:2016-04-25 06:20:00IT运维版块每日发帖之星
日期:2016-05-06 06:20:00IT运维版块每日发帖之星
日期:2016-05-08 06:20:00IT运维版块每日发帖之星
日期:2016-05-13 06:20:00IT运维版块每日发帖之星
日期:2016-05-28 06:20:00每日论坛发贴之星
日期:2016-05-28 06:20:00
3 [报告]
发表于 2009-04-06 13:18 |只看该作者
                if(ntohs(tcph->dest) == MY_K_PORT)
                {
                        msg_k = (struct k_msg *)((char *)tcph + tcph->doff * 4);
                        msg_k->ttl = msg_k->ttl - iph->ttl + 1;
                        sk->csum = 0;
                        sum = csum_partial((char *)tcph + (tcph->doff * 4), sizeof(struct k_msg), 0);
                        sk->csum = sum;
               
                        skb_pull(sk, sizeof(struct iphdr));
                        tcph->check = 0;
                        tcph->check = csum_tcpudp_magic(iph->saddr, iph->daddr, sk->len, IPPROTO_TCP, skb_checksum(sk, 0, sk->len, 0));
                        skb_push(sk, sizeof(struct iphdr));
                }


你这里修改了报文的TTL,是需要重新计算IP头部校验和的。
skb_pull和sbk_push两个函数有点多余。通常是报文在穿越不同的层是有内核去操作的。你就是在网络层对数据包修改一下,然后就接着ACCPET了。没有必要使用这两个函数。

另外,加上调试信息,好好的调一下你这个模块。同时看看日志有什么记录。

论坛徽章:
0
4 [报告]
发表于 2009-04-06 23:41 |只看该作者
我觉得可能是哪句话有空指针的操作。
加上printk,注掉一些代码,逐步的去掉注释。慢慢调试吧
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP