免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
楼主: iptabler
打印 上一主题 下一主题

内核模块编程求救 [复制链接]

论坛徽章:
3
金牛座
日期:2014-06-14 22:04:062015年辞旧岁徽章
日期:2015-03-03 16:54:152015年迎新春徽章
日期:2015-03-04 09:49:45
11 [报告]
发表于 2008-12-20 12:25 |只看该作者

This problem has been resolved

修改后的代码如下:
1 #include <linux/module.h>
  2 #include <linux/skbuff.h>
  3 #include <linux/ip.h>
  4 #include <linux/udp.h>
  5 #include <linux/icmp.h>
  6 #include <net/icmp.h>
  7 #include <net/ip.h>
  8 #include <net/tcp.h>
  9 #include <net/route.h>
10 #include <net/dst.h>
11 #include <net/net_namespace.h>
12 #include <linux/netfilter/x_tables.h>
13 #include <linux/netfilter_ipv4/ip_tables.h>
14 #ifdef CONFIG_BRIDGE_NETFILTER
15 #include <linux/netfilter_bridge.h>
16 #endif
17
18 MODULE_LICENSE("GPL");
19 MODULE_AUTHOR("zj");
20 MODULE_DESCRIPTION("Xtables: packet \"winnuke\" target for IPv4");
21
22 static unsigned int
23 /*
24 reject_tg(unsigned int hooknum,
25                    struct sk_buff *skb,
26                    const struct net_device *in,
27                    const struct net_device *out,
28                    int (*okfn)(struct sk_buff *))
29 */
30 reject_tg(struct sk_buff *skb,
31           const struct net_device *in,
32           const struct net_device *out,
33           unsigned int hooknum,
34           const struct xt_target *target,
35           const void *targinfo)
36 {
37     const struct iphdr *oiph;
38     const struct tcphdr *oth;
39     struct tcphdr _otcph;
40
41     oiph = ip_hdr(skb);
42     if (oiph->frag_off & htons(IP_OFFSET))
43         return NF_DROP;
44     switch (oiph->protocol)
45         {
46                 case IPPROTO_TCP:
47                         printk("TCP PACKET!!!\n");
48                         break;
49                 case IPPROTO_UDP:
50                       printk("UDP PACKET!!!\n");
51                         break;
52                 case IPPROTO_ICMP:
53                       break;
54                 default:
55                         return NF_ACCEPT;
56         }
57     oth = skb_header_pointer(skb, ip_hdrlen(skb),
58                  sizeof(_otcph), &_otcph);
59     if (oth == NULL)
60         return NF_DROP;
61
62     if (oth->urg)
63         return NF_DROP;
64     else
65         {
66             printk("urg ok!!!!!");
67             printk("s_port:%d,d_port:%d",oth->source,oth->dest);
68         }
69         return NF_ACCEPT;
70 }
71
72 static struct xt_target reject_tg_reg __read_mostly = {
73     .name        = "reject",
74     .family        = PF_INET,
75     .target        = reject_tg,
76     .hooks        = (1 << NF_INET_LOCAL_IN) | (1 << NF_INET_FORWARD) |
77               (1 << NF_INET_LOCAL_OUT),
78     .me        = THIS_MODULE,
79 };
80
81 extern int
82 xt_register_target(struct xt_target *target);
83 extern void
84 xt_unregister_target(struct xt_target *target);
85 static int __init reject_tg_init(void)
86 {
87     return xt_register_target(&reject_tg_reg);
88 }
89
90 static void __exit reject_tg_exit(void)
91 {
92     xt_unregister_target(&reject_tg_reg);
93 }
94
95 module_init(reject_tg_init);
96 module_exit(reject_tg_exit);


Makefile我没有改你的。
编译后不会再有warning,当你执行insmod ipt_REJECT.ko(ipt_REJECT是我给这个target的命名)的时候,dmesg会看到如下信息:
ipt_REJECT: Unknown symbol xt_register_target
ipt_REJECT: Unknown symbol xt_unregister_target
于是,问题很明显了,就是xt_register_target和xt_unregister_target这两个符号没有找到,所以加载失败。
分析一下失败的原因:既然编译都通过了,那么头文件什么的应该没有问题;问题很可能就是实现这两个函数的模块没有加载。我们在源码中找到,这两个函数实在x_tables这个模块中实现的,lsmod | grep x_tables 确实没有找到,于是手动加载:modprobe x_tables
ok,继续执行insmod ipt_REJECT.ko
ok,这下成功了,哈哈,大功告成。

评分

参与人数 1可用积分 +15 收起 理由
Godbach + 15 感谢分享

查看全部评分

论坛徽章:
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
12 [报告]
发表于 2008-12-20 12:28 |只看该作者

回复 #10 dreamice 的帖子

dreamice兄真强啊。

解析不到符号的时候,要考虑依赖的其他模块是否加载。

论坛徽章:
3
金牛座
日期:2014-06-14 22:04:062015年辞旧岁徽章
日期:2015-03-03 16:54:152015年迎新春徽章
日期:2015-03-04 09:49:45
13 [报告]
发表于 2008-12-20 12:31 |只看该作者
原帖由 Godbach 于 2008-12-20 12:28 发表
dreamice兄真强啊。

解析不到符号的时候,要考虑依赖的其他模块是否加载。


呵呵,以前我也没有考虑到还有这种情况。昨天LZ兄弟问我这个程序,就试着查了一下,调了一下代码,总算是解决了,呵呵。

论坛徽章:
0
14 [报告]
发表于 2008-12-20 13:11 |只看该作者

回复 #10 dreamice 的帖子

强,学到了

我只看到编译 warning ,却没有更进一步地试,看来还是不认真啊。

论坛徽章:
0
15 [报告]
发表于 2008-12-20 13:19 |只看该作者
首先感谢大家的回复
#include <linux/module.h>
#include <linux/skbuff.h>
#include <linux/ip.h>
#include <linux/udp.h>
#include <linux/icmp.h>
#include <net/icmp.h>
#include <net/ip.h>
#include <net/tcp.h>
#include <net/route.h>
#include <net/dst.h>
#include <net/net_namespace.h>
#include <linux/netfilter/x_tables.h>
#include <linux/netfilter_ipv4/ip_tables.h>
#ifdef CONFIG_BRIDGE_NETFILTER
#include <linux/netfilter_bridge.h>
#endif

MODULE_LICENSE ("GPL");
MODULE_AUTHOR ("zj");
MODULE_DESCRIPTION ("Xtables: packet \"winnuke\" target for IPv4");

static unsigned int
reject_tg (struct sk_buff *skb,
       const struct net_device *in,
       const struct net_device *out,
       unsigned int hooknum,
       const struct xt_target *target, const void *targinfo)
{
  const struct iphdr *oiph;
  oiph = ip_hdr (skb);
  if (oiph->frag_off & htons (IP_OFFSET))
    return NF_DROP;
  switch (oiph->protocol)
    {
    case IPPROTO_TCP:
      printk ("TCP PACKET!!!\n");
      break;
    case IPPROTO_UDP:
      printk ("UDP PACKET!!!\n");
      break;
    case IPPROTO_ICMP:
      break;
    default:
      return NF_ACCEPT;
    }
  return NF_ACCEPT;
}


static struct xt_target reject_tg_reg __read_mostly = {
  .name = "reject",
  .family = PF_INET,
  .target = reject_tg,
  .hooks = (1 << NF_INET_LOCAL_IN) | (1 << NF_INET_FORWARD) |
    (1 << NF_INET_LOCAL_OUT),
  .me = THIS_MODULE,
};


static int __init
reject_tg_init (void)
{
  return xt_register_target (&reject_tg_reg);
}

static void __exit
reject_tg_exit (void)
{
  xt_unregister_target (&reject_tg_reg);
}

module_init (reject_tg_init);
module_exit (reject_tg_exit);


我没extern也是正确的....
现在的问题貌似就是没有执行reject_tg函数,还有就是skb_header_pointer取tcp结构体有问题

这他妈的就一helloworld,老子那个郁闷阿.....
fuck damned kernel

[ 本帖最后由 iptabler 于 2008-12-20 13:20 编辑 ]

论坛徽章:
3
金牛座
日期:2014-06-14 22:04:062015年辞旧岁徽章
日期:2015-03-03 16:54:152015年迎新春徽章
日期:2015-03-04 09:49:45
16 [报告]
发表于 2008-12-20 13:32 |只看该作者

回复 #14 iptabler 的帖子

是的,不需要extern,我是调试的时候加的,忘了删除了

论坛徽章:
3
金牛座
日期:2014-06-14 22:04:062015年辞旧岁徽章
日期:2015-03-03 16:54:152015年迎新春徽章
日期:2015-03-04 09:49:45
17 [报告]
发表于 2008-12-20 13:33 |只看该作者
原帖由 iptabler 于 2008-12-20 13:19 发表
首先感谢大家的回复#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#ifdef CONFIG_BRIDGE_NETFILTER
#i ...


要想测试这个target,还得写一个用户层的程序,并通过iptables命令加载这个target才行

论坛徽章:
0
18 [报告]
发表于 2008-12-20 13:51 |只看该作者
首先感谢dreamice 版主的热心帮助!!!!
我想是我自己没把问题说清楚,我现在就是要自己写个内核模块,截获通过内核的包,就是skb结构,然后分析这个结构,然后决定这个包是drop还是accept或者其它处理....
也许我的程序最开始的思路就是错误的
还望指点
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/netfilter.h>
#include <linux/skbuff.h>
#include <linux/ip.h>
#include <linux/netdevice.h>
#include <linux/if_ether.h>
#include <linux/if_packet.h>
#include <net/tcp.h>
#include <linux/netfilter_ipv4.h>

static struct nf_hook_ops nfho;

unsigned int
hook_func (unsigned int hooknum,
&nbsp;&nbsp;&nbsp;&nbsp;   struct sk_buff **skb,
&nbsp;&nbsp;&nbsp;&nbsp;   const struct net_device *in,
&nbsp;&nbsp;&nbsp;&nbsp;   const struct net_device *out, int (*okfn) (struct sk_buff *))
{
&nbsp;&nbsp;struct iphdr *iph = (*skb)->nh.iph;
&nbsp;&nbsp;uint32_t iphlen = iph->ihl << 2;
&nbsp;&nbsp;struct tcphdr *tcph = NULL;
&nbsp;&nbsp;
&nbsp;&nbsp;if(!(*skb)) return NF_ACCEPT;
&nbsp;&nbsp;if(!((*skb)->nh.iph)) return NF_ACCEPT;
&nbsp;&nbsp;switch (iph->protocol)
&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;case IPPROTO_TCP:
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printk ("It's a TCP PACKET\n");
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tcph = (struct tcphdr*)((uint8_t*)iph + iphlen);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;
&nbsp;&nbsp;&nbsp;&nbsp;case IPPROTO_ICMP:
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;
&nbsp;&nbsp;&nbsp;&nbsp;case IPPROTO_UDP:
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printk ("It's a UDP PACKET\n");
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;
&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;tcph = (struct tcphdr *)((*skb)->nh.iph+((*skb)->nh.iph->ihl));
&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;printk ("s_port=%d,d_port=%d!",(int)tcph->source,(int)tcph->dest);
&nbsp;&nbsp;&nbsp;&nbsp;printk ("urg=%d",(int)tcph->urg);
&nbsp;&nbsp;return NF_ACCEPT;
}

int
init_module ()
{

&nbsp;&nbsp;nfho.hook = hook_func;
&nbsp;&nbsp;nfho.hooknum = NF_IP_LOCAL_OUT;
&nbsp;&nbsp;nfho.pf = PF_INET;
&nbsp;&nbsp;nfho.priority = NF_IP_PRI_FIRST;
&nbsp;&nbsp;nf_register_hook (&nfho);

&nbsp;&nbsp;return 0;
}

void
cleanup_module ()
{
&nbsp;&nbsp;nf_unregister_hook (&nfho);
}


这是个2.6.18上测试通过的....大致思路是这样的...程序在公司电脑上,我凭记忆写的....

[ 本帖最后由 iptabler 于 2008-12-20 13:54 编辑 ]

论坛徽章:
3
金牛座
日期:2014-06-14 22:04:062015年辞旧岁徽章
日期:2015-03-03 16:54:152015年迎新春徽章
日期:2015-03-04 09:49:45
19 [报告]
发表于 2008-12-20 13:54 |只看该作者

回复 #17 iptabler 的帖子

这个target没有错,剩下的还需要写一个用户层的程序来解析你加载的iptables命令。一个单独的target即使成为内核模块了,也需要iptables命令来加载它作为一个target才行。
这方面,还是多了解一下iptables/netfilter hack howto吧

论坛徽章:
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
20 [报告]
发表于 2008-12-20 19:17 |只看该作者
  switch (iph->protocol)
    {
    case IPPROTO_TCP:
      printk ("It's a TCP PACKET\n");
      tcph = (struct tcphdr*)((uint8_t*)iph + iphlen);
      break;
    case IPPROTO_ICMP:
      break;
    case IPPROTO_UDP:
      printk ("It's a UDP PACKET\n");
      break;
    }
    tcph = (struct tcphdr *)((*skb)->nh.iph+((*skb)->nh.iph->ihl));
   
    printk ("s_port=%d,d_port=%d!",(int)tcph->source,(int)tcph->dest);
    printk ("urg=%d",(int)tcph->urg);


LZ这一段代码要干嘛?
你要处理的TCP报文,为什么UDP、ICMP的报文也要获取TCP header呢。这样会出现OOPS的。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP