Chinaunix首页 | 论坛 | 博客
  • 博客访问: 4842472
  • 博文数量: 930
  • 博客积分: 12070
  • 博客等级: 上将
  • 技术积分: 11448
  • 用 户 组: 普通用户
  • 注册时间: 2008-08-15 16:57
文章分类

全部博文(930)

文章存档

2011年(60)

2010年(220)

2009年(371)

2008年(279)

分类: LINUX

2009-12-18 15:41:33

只是获取的步骤,基本上看看DNS协议的人都会写。如果要做URL过滤的话,拿到URL后可以自己
添加匹配过程,最终DROP或者ACCEPT就行,献丑了。

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/ip.h>
#include <linux/netdevice.h>
#include <linux/skbuff.h>
#include <linux/if_arp.h>
#include <linux/if_ether.h>
#include <linux/if_vlan.h>
#include <linux/netfilter_bridge.h>
#include <linux/netfilter_ipv4.h>
#include <linux/netfilter_ipv6.h>
#include <linux/netfilter_arp.h>
#include <linux/in_route.h>
#include <net/ip.h>
#include <net/ipv6.h>
#include <net/route.h>
#define STR_IP(str, n) sprintf((str), "%u.%u.%u.%u", (n)  & 0xff, ((n)>> 8) & 0xff, ((n)>>16) & 0xff, ((n)>>24) & 0xff)
#define DNS_PORT 53
#define UDP_HEAD_LEN 8
#define DNS_HEAD_LEN 12



static int get_name(const char* addr, char* szBuff, int len);
static unsigned int cme_hook(unsigned int hook,
    struct sk_buff **pskb,         
    const struct net_device *in,         
    const struct net_device *out,         
    int (*okfn)(struct sk_buff *))
{
     struct sk_buff * skb = *pskb;
    char szurl[1024] = {0};
    struct udphdr *uhead;
    unsigned char* udp_data = 0;
   
    u_int16_t src_port, dst_port;
    u_int16_t udp_len = 0;
    u_int8_t flag;

      char src[20] = {0},dst[20]={0};

     if(!skb)return NF_ACCEPT;
     
    if (skb->protocol != htons(ETH_P_IP))
     return NF_ACCEPT;

    if(skb->nh.iph->protocol != IPPROTO_UDP)
    return NF_ACCEPT;

      
    STR_IP(src, skb->nh.iph->saddr );
      STR_IP(dst, skb->nh.iph->daddr);
   
    uhead = (struct udphdr *)(skb->data  + (skb->nh.iph->ihl * 4));

    src_port = ntohs(uhead->source);
    dst_port = ntohs(uhead->dest);
    udp_len  = ntohs(uhead->len) - UDP_HEAD_LEN;
   
    if(udp_len <= DNS_HEAD_LEN)
    {
        printk("error DNS message\n");
        return NF_ACCEPT;
    }
    //get to start point of udp data

    udp_data = (unsigned char*)(uhead + 1);   

    flag = ((u_int8_t)udp_data[2])& 8;

    if((src_port != DNS_PORT)&&(dst_port != DNS_PORT))
    return NF_ACCEPT;

    if(flag) return NF_ACCEPT;
   
    get_name(udp_data + DNS_HEAD_LEN, szurl, udp_len - DNS_HEAD_LEN);   
    printk("query url:%s\n", szurl);   
      printk("dns packet--dir : %s:%u ==> %s:%u, len = %u, type:%s\n",
        src, src_port, dst, dst_port, udp_len, flag ? "response" : "query");
    return NF_ACCEPT;                 
}
static struct nf_hook_ops  ops =
{
      .hook = cme_hook,   
      .owner = THIS_MODULE,   
      .pf = PF_INET,   
      .hooknum = NF_IP_POST_ROUTING,   
      .priority = NF_IP_PRI_FIRST,
};
int init(void)
{
     nf_register_hook(&ops);
     printk("cme hook registering.......\n");
     return 0;
}
void finish(void)
{
     nf_unregister_hook(&ops);
     printk("removing cme hook.......\n");
}
module_init(init)
module_exit(finish)

MODULE_LICENSE("GPL");
MODULE_VERSION("1.0");
int get_name(const char* addr, char* szBuff, int len)
{
    const char * p = addr;
    int pos = 0;

    // "03 w w w 03 1 2 6 03 c o m" means ""

    while(p && (*p > 0))
    {
        if(*p > len)
        {
            printk("error url len:%d\n", *p);
            break;
        }
        strncpy(szBuff + pos, p + 1, *p);
        pos +=  *p;
        szBuff[pos] = '.';
        pos++;
        len -= (*p + 1);
        p += (*p + 1);
    }
    if(pos > 0)
    szBuff[pos - 1] = '\0';
    return pos;
}


编译脚本:
MODULE_NAME:=dns_filter
obj-m:=$(MODULE_NAME).o
$(MODULE_NAME)-objs := dns_hook.o
KERNELDIR ?= /lib/modules/$(shell uname -r)/build
PWD       := $(shell pwd)
all:
        $(MAKE) -C $(KERNELDIR) M=$(PWD) modules
clean:
        rm -fr *.ko *.o *.cmd  $(MODULE_NAME).mod.c


 
cu段兄的帖子:
阅读(1590) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~