[实用开源]用于网络包检查的内核模块
非常简单的网络包检查的内核模块,基于此可以做更多有意义的事情。基于内核 3.2 测试通过。
pkt_chk.c
1 2 3 4 5 6 7 |
/** * @file * @author Z. Liu * * @brief kernel module for packet inspection */ |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 |
#include #include #include #include #include #include MODULE_LICENSE("Dual BSD/GPL"); MODULE_AUTHOR("Z. Liu "); MODULE_DESCRIPTION("demo of packet inspection"); static unsigned int pkt_chk_out(unsigned int hooknum, struct sk_buff *skb, const struct net_device *in, const struct net_device *out, int (*okfn)(struct sk_buff *)) { struct tcphdr *th; struct udphdr *uh; uint16_t sport = 0, dport = 0; struct iphdr *iph = (struct iphdr *)skb_network_header(skb); switch (iph->protocol) { case IPPROTO_UDP: uh = (struct udphdr *)skb_transport_header(skb); sport = (unsigned int)ntohs(uh->source); dport = (unsigned int)ntohs(uh->dest); break; case IPPROTO_TCP: th = (struct tcphdr *)skb_transport_header(skb); sport = (unsigned int)ntohs(th->source); dport = (unsigned int)ntohs(th->dest); break; default: break; } pr_info("OUT: %pI4:%u -> %pI4:%u, proto: %u\n", &iph->saddr, sport, &iph->daddr, dport, iph->protocol); return NF_ACCEPT; } static unsigned int pkt_chk_in(unsigned int hooknum, struct sk_buff *skb, const struct net_device *in, const struct net_device *out, int (*okfn)(struct sk_buff *)) { static const char nulldevname[IFNAMSIZ] __attribute__((aligned(sizeof(long)))); struct tcphdr *th; struct udphdr *uh; uint16_t sport = 0, dport = 0; struct iphdr *iph = (struct iphdr *)skb_network_header(skb); const char *indev; indev = in ? in->name : nulldevname; // @note when a packet goes in from wire, it travels from physical layer, // data link layer, network layer upwards, therefore it might not go // through the functions for skb_transport_header to work as expected. // so we need a hack: skip the ip header. switch (iph->protocol) { case IPPROTO_UDP: uh = (struct udphdr *)(skb_transport_header(skb) + (iph->ihl << 2)); sport = (unsigned int)ntohs(uh->source); dport = (unsigned int)ntohs(uh->dest); break; case IPPROTO_TCP: th = (struct tcphdr *)(skb_transport_header(skb) + (iph->ihl << 2)); sport = (unsigned int)ntohs(th->source); dport = (unsigned int)ntohs(th->dest); break; default: break; } pr_info("IN: %pI4:%u -> %pI4:%u, proto: %u\n", &iph->saddr, sport, &iph->daddr, dport, iph->protocol); return NF_ACCEPT; } static struct nf_hook_ops packet_ops[] __read_mostly = { { .hook = pkt_chk_in, .owner = THIS_MODULE, .pf = PF_INET, .hooknum = NF_INET_PRE_ROUTING, .priority = NF_IP_PRI_FIRST, }, { .hook = pkt_chk_out, .owner = THIS_MODULE, .pf = PF_INET, .hooknum = NF_INET_LOCAL_OUT, .priority = NF_IP_PRI_FIRST, }, }; static int __init pkt_chk_init(void) { int ret; pr_info("initialize of packet inspection module\n"); ret = nf_register_hooks(packet_ops, ARRAY_SIZE(packet_ops)); if (ret < 0) { return ret; } return 0; } static void __exit pkt_chk_exit(void) { nf_unregister_hooks(packet_ops, ARRAY_SIZE(packet_ops)); pr_info("packet inspection module unloaded.\n"); } module_init(pkt_chk_init); module_exit(pkt_chk_exit); |
Makefile
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
ifeq ($(KERNELRELEASE),) KERNELDIR ?= /lib/modules/$(shell uname -r)/build PWD := $(shell pwd) .PHONY: modules clean modules: $(MAKE) -C $(KERNELDIR) M=$(PWD) modules modules_install: $(MAKE) -C $(KERNELDIR) M=$(PWD) modules_install clean: @rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions @rm -rf modules.order Module.symvers else obj-m := pkt_chk.o endif |
6条评论
能告诉我哪些头文件吗、、?
http://www.libevent.cn/article/show/9
好好学习,崇拜死我了,下次再发的时候把tcp和udp还有ip的结构体顺便也发了
写 的真不错 %0ax003c%u003c%3c+ADw- %c0%ab%c1%81%c1%84%c1%b7%c0%ad%2bADw-
这个写的不错 ;>_<:
不错哇 确实可以做很多的事情了