Linux 网络 - 基于Netfilter的防火墙
http://www.linuxjournal.com/article/7184
http://www.paulkiddie.com/2009/10/creating-a-simple-hello-world-netfilter-module/
http://www.cis.syr.edu/~wedu/seed/Labs/Firewall_Linux/
http://www.roman10.net/2011/07/31/how-to-write-a-linux-firewall-in-less-than-1000-lines-of-codeput-everything-together/
http://www.gnu.org/software/libc/manual/html_node/index.html#SEC_Contents GNUC 库
http://wenku.it168.com/d_000339419.shtml
一个简单的基于netfilter丢弃所有包的模块
//'Hello World' kernel module, logs call to init_module // and cleanup_module to /var/log/messages // In Ubuntu 8.04 we use make and appropriate Makefile to compile kernel module #define __KERNEL__ #define MODULE #include <linux/module.h> #include <linux/kernel.h> #include <linux/init.h> #include <linux/netfilter.h> #include <linux/netfilter_ipv4.h> static struct nf_hook_ops nfho; // 定义nf_hook_ops数据结构 //function to be called by hook 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 *)) { printk(KERN_INFO "packet dropped\n"); //log to var/log/messages return NF_DROP; //drops the packet } int init_module(void) { nfho.hook = hook_func; // 定义数据结构 nfho.hooknum = NF_INET_PRE_ROUTING; //called right after packet recieved, first hook in Netfilter nfho.pf = PF_INET; //IPV4 packets nfho.priority = NF_IP_PRI_FIRST; //set to highest priority over all other hook functions nf_register_hook(&nfho); //register hook return 0; }
// 注销模块 void cleanup_module(void) { nf_unregister_hook(&nfho); }
Makefile
obj-m := hello.o KDIR := /usr/src/linux-headers-4.4.0-62-generic PWD := $(shell pwd) default: $(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules clean: $(MAKE) -C $(KDIR) M=$(PWD) clean
使用glibc来编写命令简单的命令行工具:
参考资料:
http://www.gnu.org/s/libc/manual/html_node/Getopt.html
理解getopt()函数
// cmd.c 程序 #include <stdio.h> #include <stdlib.h> #include <getopt.h> #define print_value(x) (x==NULL?"-" : x) static struct mf_rule_struct { int in_out; char *src_ip; char *src_netmask; char *src_port; //default to -1 char *dest_ip; char *dest_netmask; char *dest_port; char *proto; char *action; } mf_rule; static struct mf_delete_struct { char *cmd; char *row; } mf_delete; void send_rule_to_proc() { printf("TODO: send_rule_to_procn"); } void send_delete_to_proc() { printf("TODO: send_delete_to_procn"); } void print_rule() { printf("TODO: print_rule\n"); return; } int main(int argc, char *argv[]) { int c; int action = 1; //1: new rule; 2: print; 3: delete mf_rule.in_out = -1; mf_rule.src_ip = NULL; mf_rule.src_netmask = NULL; mf_rule.src_port = NULL; mf_rule.dest_ip = NULL; mf_rule.dest_netmask = NULL; mf_rule.dest_port = NULL; mf_rule.proto = NULL; mf_rule.action = NULL; while (1) { static struct option long_options[] = { /*set a flag*/ {"in", no_argument, &mf_rule.in_out, 1}, {"out", no_argument, &mf_rule.in_out, 0}, /*These options don't set a flag. We distinguish them by their indices.*/ {"print", no_argument, 0, 'o'}, {"delete", required_argument, 0, 'd'}, {"srcip", required_argument, 0, 's'}, {"srcnetmask", required_argument, 0, 'm'}, {"srcport", required_argument, 0, 'p'}, {"destip", required_argument, 0, 't'}, {"destnetmask", required_argument, 0, 'n'}, {"destport", required_argument, 0, 'q'}, {"proto", required_argument, 0, 'c'}, {"action", required_argument, 0, 'a'}, {0, 0, 0, 0} }; int option_index = 0; c = getopt_long(argc, argv, "od:s:m:p:t:n:q:c:a:", long_options, &option_index); /*Detect the end of the options. */ if (c == -1) break; action = 1; switch (c) { case 0: printf("flag option: %s, mf_rule.in_out = %dn", long_options[option_index].name, mf_rule.in_out); break; case 'o': action = 2; //print break; case 'd': action = 3; //delete mf_delete.cmd = (char *)long_options[option_index].name; mf_delete.row = optarg; break; case 's': mf_rule.src_ip = optarg; //src ip break; case 'm': mf_rule.src_netmask = optarg; //srcnetmask: break; case 'p': mf_rule.src_port = optarg; //srcport: break; case 't': mf_rule.dest_ip = optarg; //destip: break; case 'n': mf_rule.dest_netmask = optarg; //destnetmask break; case 'q': mf_rule.dest_port = optarg; //destport break; case 'c': mf_rule.proto = optarg; //proto break; case 'a': mf_rule.action = optarg;//action break; case '?': /* getopt_long printed an error message. */ break; default: abort(); } if (c != 0) printf("%s = %sn", long_options[option_index].name, optarg); } if (action == 1) { send_rule_to_proc(); } else if (action == 2) { print_rule(); } else if (action == 3) { send_delete_to_proc(); } if (optind < argc) { printf("non-option ARGV-elements: "); while (optind < argc) printf("%s ", argv[optind++]); putchar('\n'); } }
命令行工具程序解析:
编译程序 gcc cmd.c -o cmd
运行程序:
新建一条规则
./cmd --in --srcip 192.168.0.10 --srcnetmask 255.255.255.0 --srcport 1000 --destip 114.114.114.114 --destnetmask 255.255.255.0 --destport 53 --proto 6 --action 0
输出结果:
➜ test_cmd ./cmd --in --srcip 192.168.0.10 --srcnetmask 255.255.255.0 --srcport 1000 --destip 114.114.114.114 --destnetmask 255.255.255.0 --destport 53 --proto 6 --action 0
flag option: in, mf_rule.in_out = 1
srcip = 192.168.0.10
srcnetmask = 255.255.255.0
srcport = 1000
destip = 114.114.114.114
destnetmask = 255.255.255.0
destport = 53
proto = 6
action = 0
TODO: send_rule_to_proc
运行程序
./cmd --delete 1
➜ test_cmd ./cmd --delete 2
delete = 2
TODO: send_delete_to_proc

浙公网安备 33010602011771号