netfilterフック2
netfilterフックルーチンその2
以下の4箇所のフックポイントでフックしパケットの内容をmessagesに出力する。
・PRE_ROUTING
・POST_ROUTING
・LOCAL_IN
・LOCAL_OUT
あくまで解析/デバッグ用。ログ吐きすぎ。
ビルドの方法などは以下参照。
http://d.hatena.ne.jp/kwata8459/20121115/1352986791
/* * exp_netfilter2.c */ #include <linux/types.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/init.h> #include <linux/skbuff.h> #include <linux/netfilter.h> #include <linux/netfilter_ipv4.h> #include <linux/ip.h> #include <linux/udp.h> #include <linux/tcp.h> #define DRIVER_AUTHOR "NABETI" #define DRIVER_DESC "netfilter experiment" void yydump(char *p, int length); void dump_sk_buff(struct sk_buff *skb); void dump_ip(struct iphdr* iph); void dump_tcp(struct tcphdr* tcph); void dump_udp(struct udphdr* udph); static struct nf_hook_ops nfho_pre_routing; static struct nf_hook_ops nfho_post_routing; static struct nf_hook_ops nfho_local_in; static struct nf_hook_ops nfho_local_out; //---------------------------------- static unsigned int hook_func(unsigned int hooknum, struct sk_buff *skb, const struct net_device *in, const struct net_device *out, int (*okfn)(struct sk_buff *)) { const char *str_hooknum[NF_INET_NUMHOOKS] = { "NF_INET_PRE_ROUTING", "NF_INET_LOCAL_IN", "NF_INET_FORWARD", "NF_INET_LOCAL_OUT", "NF_INET_POST_ROUTING" }; printk(KERN_INFO "[NFE] --- hook_func ------------------\n"); if((0 <= hooknum) && (hooknum < NF_INET_NUMHOOKS)){ printk(KERN_INFO "hooknum : %s\n", str_hooknum[hooknum]); } else{ printk(KERN_INFO "hooknum : %s\n", "Unknown Hooknum"); } printk(KERN_INFO "in : %s\n", in->name); printk(KERN_INFO "out : %s\n", out->name); dump_sk_buff(skb); printk(KERN_INFO "\n"); return NF_ACCEPT; } //---------------------------------- static int __init nfe_init(void) { printk(KERN_INFO "[NFE] nfe_init\n"); nfho_pre_routing.hook = hook_func; nfho_pre_routing.hooknum = NF_INET_PRE_ROUTING; nfho_pre_routing.pf = PF_INET; nfho_pre_routing.priority = NF_IP_PRI_FIRST; nf_register_hook(&nfho_pre_routing); nfho_post_routing.hook = hook_func; nfho_post_routing.hooknum = NF_INET_POST_ROUTING; nfho_post_routing.pf = PF_INET; nfho_post_routing.priority = NF_IP_PRI_FIRST; nf_register_hook(&nfho_post_routing); nfho_local_in.hook = hook_func; nfho_local_in.hooknum = NF_INET_LOCAL_IN; nfho_local_in.pf = PF_INET; nfho_local_in.priority = NF_IP_PRI_FIRST; nf_register_hook(&nfho_local_in); nfho_local_out.hook = hook_func; nfho_local_out.hooknum = NF_INET_LOCAL_OUT; nfho_local_out.pf = PF_INET; nfho_local_out.priority = NF_IP_PRI_FIRST; nf_register_hook(&nfho_local_out); return 0; } //---------------------------------- static void __exit nfe_exit(void) { printk(KERN_INFO "[NFE] nfe_exit\n"); nf_unregister_hook(&nfho_pre_routing); nf_unregister_hook(&nfho_post_routing); nf_unregister_hook(&nfho_local_in); nf_unregister_hook(&nfho_local_out); } //---------------------------------- // Dump sk_buff //---------------------------------- void dump_sk_buff(struct sk_buff *skb) { printk(KERN_INFO "next : %p\n", skb->next); printk(KERN_INFO "prev : %p\n", skb->prev); printk(KERN_INFO "tstamp.tv64: %llu\n", skb->tstamp.tv64); printk(KERN_INFO "dev.name : %s\n", skb->dev->name); printk(KERN_INFO "len : %d\n", skb->len); printk(KERN_INFO "data_len : %d\n", skb->data_len); printk(KERN_INFO "mac_len : %d\n", skb->mac_len); printk(KERN_INFO "hdr_len : %d\n", skb->hdr_len); printk(KERN_INFO "priority : %d\n", skb->priority); printk(KERN_INFO "protocol : %d\n", skb->protocol); printk(KERN_INFO "head : %p\n", skb->head); printk(KERN_INFO "data : %p\n", skb->data); printk(KERN_INFO "tail : %p\n", skb->tail); printk(KERN_INFO "end : %p\n", skb->end); printk(KERN_INFO "skb_mac_header() : %p\n", skb_mac_header(skb)); printk(KERN_INFO "skb_network_header() : %p\n", skb_network_header(skb)); printk(KERN_INFO "skb_transport_header() : %p\n", skb_transport_header(skb)); dump_ip((struct iphdr*)skb_network_header(skb)); yydump(skb->head, skb->end - skb->head); } //---------------------------------- // Dump IP packet //---------------------------------- void dump_ip(struct iphdr* iph) { char *ps = NULL; printk(KERN_INFO "iphdr.version : %d\n", iph->version); printk(KERN_INFO "iphdr.ihl : %d\n", iph->ihl); printk(KERN_INFO "iphdr.tos : %02x\n", iph->tos); printk(KERN_INFO "iphdr.tot_len : %d\n", iph->tot_len); printk(KERN_INFO "iphdr.id : %04x\n", iph->id); switch(iph->protocol){ case 1: ps = "ICMP"; break; case 4: ps = "IPv4"; break; case 6: ps = "TCP"; break; case 17: ps = "UDP"; break; default: sprintf(ps, "<%d>", iph->protocol); break; } printk(KERN_INFO "iphdr.protocol: %s\n", ps); printk(KERN_INFO "iphdr.saddr : %08x\n", iph->saddr); printk(KERN_INFO "iphdr.daddr : %08x\n", iph->daddr); switch(iph->protocol){ case 6: dump_tcp((struct tcphdr*)((char *)iph + sizeof(struct iphdr))); break; case 17: dump_udp((struct udphdr*)((char *)iph + sizeof(struct iphdr))); break; } } //---------------------------------- // Dump TCP packet //---------------------------------- void dump_tcp(struct tcphdr* tcph) { char buf[128]; sprintf(buf, "Flags -- "); printk(KERN_INFO "tcphdr.source : %u\n", tcph->source); printk(KERN_INFO "tcphdr.dest : %u\n", tcph->dest); printk(KERN_INFO "tcphdr.seq : %u\n", tcph->seq); printk(KERN_INFO "tcphdr.ack_seq: %u\n", tcph->ack_seq); printk(KERN_INFO "tcphdr.window : %u\n", tcph->window); if(tcph->fin == 1) strcat(buf, "[FIN]"); if(tcph->syn == 1) strcat(buf, "[SYN]"); if(tcph->rst == 1) strcat(buf, "[RST]"); if(tcph->psh == 1) strcat(buf, "[PSH]"); if(tcph->ack == 1) strcat(buf, "[ACK]"); if(tcph->urg == 1) strcat(buf, "[URG]"); if(tcph->ece == 1) strcat(buf, "[ECE]"); if(tcph->cwr == 1) strcat(buf, "[CWR]"); strcat(buf, "\n"); printk(KERN_INFO "%s",buf); } //---------------------------------- // Dump UDP packet //---------------------------------- void dump_udp(struct udphdr* udph) { printk(KERN_INFO "udphdr.source : %u\n", udph->source); printk(KERN_INFO "udphdr.dest : %u\n", udph->dest); printk(KERN_INFO "udphdr.len : %u\n", udph->len); } //---------------------------------- // hex dump to /var/log/messages //---------------------------------- void yydump(char *p, int length) { int address = (int)p; char data[17]; int i; char buf[128]; char tmp[32]; data[16] = 0; /* for string terminator */ for(;length>0;){ sprintf(buf, "%08X :", address); for(i=0;i<16;i++){ data[i] = *p++; length--; /* data is out of range */ if(length < 0){ sprintf(tmp, " "); strcat(buf, tmp); data[i] = ' '; } else{ sprintf(tmp, "%02X", (unsigned char)data[i]); strcat(buf, tmp); /* eliminate undisplayable character */ if((data[i] < 0x20) || (0x7E < data[i])){ data[i] = '.'; } } } sprintf(tmp, " : %s\n", data); strcat(buf, tmp); address += 16; printk(KERN_INFO "%s",buf); } } module_init(nfe_init); module_exit(nfe_exit); MODULE_LICENSE("GPLv3"); MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC);