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

 

posted @ 2017-12-20 11:48  elewei  阅读(1167)  评论(0)    收藏  举报