Linux内核--基于Netfilter的内核级包过滤防火墙实现
测试内核版本:Linux Kernel 2.6.35----Linux Kernel 3.2.1
知识基础:本防火墙的开发基于对Linux内核网络栈有个良好的概念,本人对网络栈的分析是基于早期版本(Linux 1.2.13),在明确了网络栈架构的前提下,上升一步分析高级版本内核中的Netfilter防火墙实现原理,然后进行模块或内核编程,开发一款基于包过滤的个人防火墙。
包过滤防火墙:包过滤防火墙是用一个软件查看所流经的数据包的包头(header),由此决定整个包的命运。它可能会决定丢弃(DROP)这个包,可能会接受(ACCEPT)这个包(让这个包通过),也可能执行其它更复杂的动作。工作于网络层,能对IP数据报进行首部检查。例如:IP源地址,目的地址,源端口和目的端口等。
本防火墙的包过滤功能如下:
* 拒绝来自某主机或某网段的所有连接。
* 允许来自某主机或某网段的所有连接。
* 拒绝来自某主机或某网段的指定端口的连接。
* 允许来自某主机或某网段的指定端口的连接。
* 拒绝发去某主机或某网段的所有连接。
* 允许发去某主机或某网段的所有连接。
* 拒绝发去某主机或某网段的指定端口的连接。
* 允许发去某主机或某网段的指定端口的连接。
Netfilter框架是Linux内核分析和过滤特定协议数据包处理框架,为其他模块动态参与网络层数据包处理提供了方便的途径。
本防火墙的简单功能就是检查数据包是否符合过滤的条件,如果不符合就舍弃(Drop),否则就接受(Accept),这里定义八个链表头结点
- struct ip_node ip_allowed_in_node_head;/*允许的远程主机或网络IP地址头节点*/
- struct ip_node ip_denied_in_node_head;/*拒绝的远程主机或网络IP地址头节点*/
- struct ip_node ip_allowed_out_node_head;/*允许的本地主机或网络IP地址头节点*/
- struct ip_node ip_denied_out_node_head;/*拒绝的本地主机或网络IP地址头节点*/
- struct port_node port_allowed_in_node_head;/*允许的远程主机或网络传输层端口号头节点*/
- struct port_node port_denied_in_node_head;/*拒绝的远程主机或网络传输层端口号头节点*/
- struct port_node port_allowed_out_node_head;/*允许的本地主机或网络传输层端口号头节点*/
- struct port_node port_denied_out_node_head;/*拒绝的本地主机或网络传输层端口号头节点*/
用于保存配置文件中的地址或端口信息。
定义两个钩子函数hook_func_in和hook_func_out,分别将其挂载到INET协议族的入口NF_INET_LOCAL_IN和出口NF_INET_LOCAL_OUT:
- static struct nf_hook_ops my_netfilter[] =
- {
- {
- .hook =hook_func_in,
- .owner =THIS_MODULE,
- .pf =PF_INET,
- .hooknum =NF_INET_LOCAL_IN,
- .priority =100
- },
- {
- .hook =hook_func_out,
- .owner =THIS_MODULE,
- .pf =PF_INET,
- .hooknum =NF_INET_LOCAL_OUT,
- .priority =100
- }
- };
说明一下自己定义的一些宏和引用的头文件:
- #ifndef MODULE
- #define MODULE
- #endif
- #ifndef __KERNEL__
- #define __KERNEL__
- #endif
- //#define NET_DOWN
- #define MY_FIREWALL_DEBUG
- #include <asm/system.h>
- #include <linux/module.h>
- #include <linux/types.h>
- #include <linux/kernel.h>
- #include <linux/string.h>
- #include <linux/net.h>
- #include <linux/socket.h>
- #include <linux/sockios.h>
- #include <linux/in.h>
- #include <linux/inet.h>
- #include <net/ip.h>
- #include <net/protocol.h>
- #include <linux/skbuff.h>
- #include <net/sock.h>
- #include <net/icmp.h>
- #include <net/raw.h>
- #include <net/checksum.h>
- #include <linux/netfilter_ipv4.h>
- #include <linux/tcp.h>
- #include <linux/udp.h>
- #include <linux/igmp.h>
- #include <linux/fs.h>
- #include <linux/mm.h>
- #include <asm/uaccess.h>
- #define YES 1
- #define NO 0
- #define IP_MAX_LEN 20
- #define PORT_MAX_LEN 20
- #define ALLOWED_IP_IN 0
- #define DENIED_IP_IN 1
- #define ALLOWED_IP_OUT 2
- #define DENIED_IP_OUT 3
- #define ALLOWED_PORT_IN 0
- #define DENIED_PORT_IN 1
- #define ALLOWED_PORT_OUT 2
- #define DENIED_PORT_OUT 3
- #define ALLOWED_IN_IP_CONF_FILE_DIR "/etc/my_firewall/ip_allowed_in"
- #define DENIED_IN_IP_CONF_FILE_DIR "/etc/my_firewall/ip_denied_in"
- #define ALLOWED_IN_PORT_CONF_FILE_DIR "/etc/my_firewall/port_allowed_in"
- #define DENIED_IN_PORT_CONF_FILE_DIR "/etc/my_firewall/port_denied_in"
- #define ALLOWED_OUT_IP_CONF_FILE_DIR "/etc/my_firewall/ip_allowed_out"
- #define DENIED_OUT_IP_CONF_FILE_DIR "/etc/my_firewall/ip_denied_out"
- #define ALLOWED_OUT_PORT_CONF_FILE_DIR "/etc/my_firewall/port_allowed_out"
- #define DENIED_OUT_PORT_CONF_FILE_DIR "/etc/my_firewall/port_denied_out"
- //DEFINE FOR WORK_MODE
- /*不工作状态,默认*/
- #define MODE_FREE 0
- /*允许来自某主机或某网段的所有连接*/
- #define MODE_IP_ONLY_ALLOWED_IN 1
- /*拒绝来自某主机或某网段的所有连接*/
- #define MODE_IP_ONLY_DENIED_IN 2
- /*允许来自某主机或某网段指定端口的连接*/
- #define MODE_IP_PORT_ALLOWED_IN 3
- /*拒绝来自某主机或某网段的指定端口的连接*/
- #define MODE_IP_PORT_DENIED_IN 4
- /*允许本地主机或本地网络与其他主机或网络的所有连接*/
- #define MODE_IP_ONLY_ALLOWED_OUT 5
- /*拒绝本地主机或本地网络与其他主机或网络的所有连接*/
- #define MODE_IP_ONLY_DENIED_OUT 6
- /*允许本地主机或网络与其他主机或其他网络的指定端口的连接*/
- #define MODE_IP_PORT_ALLOWED_OUT 7
- /*拒绝本地主机或网络与其他主机或其他网络的指定端口的连接*/
- #define MODE_IP_PORT_DENIED_OUT 8