只是获取的步骤,基本上看看DNS协议的人都会写。如果要做URL过滤的话,拿到URL后可以自己
添加匹配过程,最终DROP或者ACCEPT就行,献丑了。
编译脚本:
添加匹配过程,最终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段兄的帖子: