Linux内核基于Netfilter的内核级包过滤防火墙实现.docx
《Linux内核基于Netfilter的内核级包过滤防火墙实现.docx》由会员分享,可在线阅读,更多相关《Linux内核基于Netfilter的内核级包过滤防火墙实现.docx(38页珍藏版)》请在冰点文库上搜索。
Linux内核基于Netfilter的内核级包过滤防火墙实现
Linux内核--基于Netfilter的内核级包过滤防火墙实现
测试内核版本:
LinuxKernel2.6.35----LinuxKernel3.2.1
知识基础:
本防火墙的开发基于对Linux内核网络栈有个良好的概念,本人对网络栈的分析是基于早期版本(Linux1.2.13),在明确了网络栈架构的前提下,上升一步分析高级版本内核中的Netfilter防火墙实现原理,然后进行模块或内核编程,开发一款基于包过滤的个人防火墙。
包过滤防火墙:
包过滤防火墙是用一个软件查看所流经的数据包的包头(header),由此决定整个包的命运。
它可能会决定丢弃(DROP)这个包,可能会接受(ACCEPT)这个包(让这个包通过),也可能执行其它更复杂的动作。
工作于网络层,能对IP数据报进行首部检查。
例如:
IP源地址,目的地址,源端口和目的端口等。
本防火墙的包过滤功能如下:
*拒绝来自某主机或某网段的所有连接。
*允许来自某主机或某网段的所有连接。
*拒绝来自某主机或某网段的指定端口的连接。
*允许来自某主机或某网段的指定端口的连接。
*拒绝发去某主机或某网段的所有连接。
*允许发去某主机或某网段的所有连接。
*拒绝发去某主机或某网段的指定端口的连接。
*允许发去某主机或某网段的指定端口的连接。
Netfilter框架是Linux内核分析和过滤特定协议数据包处理框架,为其他模块动态参与网络层数据包处理提供了方便的途径。
该防火墙的总体结构如下:
本防火墙的简单功能就是检查数据包是否符合过滤的条件,如果不符合就舍弃(Drop),否则就接受(Accept),这里定义八个链表头结点
[cpp]viewplaincopyprint?
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;/*拒绝的本地主机或网络传输层端口号头节点*/
structip_nodeip_allowed_in_node_head;/*允许的远程主机或网络IP地址头节点*/
structip_nodeip_denied_in_node_head;/*拒绝的远程主机或网络IP地址头节点*/
structip_nodeip_allowed_out_node_head;/*允许的本地主机或网络IP地址头节点*/
structip_nodeip_denied_out_node_head;/*拒绝的本地主机或网络IP地址头节点*/
structport_nodeport_allowed_in_node_head;/*允许的远程主机或网络传输层端口号头节点*/
structport_nodeport_denied_in_node_head;/*拒绝的远程主机或网络传输层端口号头节点*/
structport_nodeport_allowed_out_node_head;/*允许的本地主机或网络传输层端口号头节点*/
structport_nodeport_denied_out_node_head;/*拒绝的本地主机或网络传输层端口号头节点*/
用于保存配置文件中的地址或端口信息。
定义两个钩子函数hook_func_in和hook_func_out,分别将其挂载到INET协议族的入口NF_INET_LOCAL_IN和出口NF_INET_LOCAL_OUT:
[cpp]viewplaincopyprint?
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
}
};
staticstructnf_hook_opsmy_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
}
};
说明一下自己定义的一些宏和引用的头文件:
[cpp]viewplaincopyprint?
#ifndef MODULE
#define MODULE
#endif
#ifndef __KERNEL__
#define __KERNEL__
#endif
//#define NET_DOWN
#define MY_FIREWALL_DEBUG
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#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
#ifndefMODULE
#defineMODULE
#endif
#ifndef__KERNEL__
#define__KERNEL__
#endif
//#defineNET_DOWN
#defineMY_FIREWALL_DEBUG
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#defineYES1
#defineNO0
#defineIP_MAX_LEN20
#definePORT_MAX_LEN20
#defineALLOWED_IP_IN0
#defineDENIED_IP_IN1
#defineALLOWED_IP_OUT2
#defineDENIED_IP_OUT3
#defineALLOWED_PORT_IN0
#defineDENIED_PORT_IN1
#defineALLOWED_PORT_OUT2
#defineDENIED_PORT_OUT3
#defineALLOWED_IN_IP_CONF_FILE_DIR"/etc/my_firewall/ip_allowed_in"
#defineDENIED_IN_IP_CONF_FILE_DIR"/etc/my_firewall/ip_denied_in"
#defineALLOWED_IN_PORT_CONF_FILE_DIR"/etc/my_firewall/port_allowed_in"
#defineDENIED_IN_PORT_CONF_FILE_DIR"/etc/my_firewall/port_denied_in"
#defineALLOWED_OUT_IP_CONF_FILE_DIR"/etc/my_firewall/ip_allowed_out"
#defineDENIED_OUT_IP_CONF_FILE_DIR"/etc/my_firewall/ip_denied_out"
#defineALLOWED_OUT_PORT_CONF_FILE_DIR"/etc/my_firewall/port_allowed_out"
#defineDENIED_OUT_PORT_CONF_FILE_DIR"/etc/my_firewall/port_denied_out"
//DEFINEFORWORK_MODE
/*不工作状态,默认*/
#defineMODE_FREE0
/*允许来自某主机或某网段的所有连接*/
#defineMODE_IP_ONLY_ALLOWED_IN1
/*拒绝来自某主机或某网段的所有连接*/
#defineMODE_IP_ONLY_DENIED_IN2
/*允许来自某主机或某网段指定端口的连接*/
#defineMODE_IP_PORT_ALLOWED_IN3
/*拒绝来自某主机或某网段的指定端口的连接*/
#defineMODE_IP_PORT_DENIED_IN4
/*允许本地主机或本地网络与其他主机或网络的所有连接*/
#defineMODE_IP_ONLY_ALLOWED_OUT5
/*拒绝本地主机或本地网络与其他主机或网络的所有连接*/
#defineMODE_IP_ONLY_DENIED_OUT6
/*允许本地主机或网络与其他主机或其他网络的指定端口的连接*/
#defineMODE_IP_PORT_ALLOWED_OUT7
/*拒绝本地主机或网络与其他主机或其他网络的指定端口的连接*/
#defineMODE_IP_PORT_DENIED_OUT8
下面是防火墙模块的初始化函数:
[cpp]viewplaincopyprint?
int init_firewall()
{
(&ip_allowed_in_node_head)->next = NULL;
(&ip_denied_in_node_head)->next = NULL;
(&port_allowed_in_node_head)->next = NULL;
(&port_denied_in_node_head)->next = NULL;
(&ip_allowed_out_node_head)->next = NULL;
(&ip_denied_out_node_head)->next = NULL;
(&port_allowed_out_node_head)->next = NULL;
(&port_denied_out_node_head)->next = NULL;
switch(work_mode)
{
case MODE_IP_ONLY_ALLOWED_IN:
open_ip_cfg_file(ALLOWED_IN_IP_CONF_FILE_DIR,ALLOWED_IP_IN);
break;
case MODE_IP_ONLY_DENIED_IN:
open_ip_cfg_file(DENIED_IN_IP_CONF_FILE_DIR,DENIED_IP_IN);
break;
case MODE_IP_PORT_ALLOWED_IN:
open_port_cfg_file(ALLOWED_IN_PORT_CONF_FILE_DIR,ALLOWED_PORT_IN);
open_ip_cfg_file(ALLOWED_IN_IP_CONF_FILE_DIR,ALLOWED_IP_IN);
break;
case MODE_IP_PORT_DENIED_IN:
open_port_cfg_file(DENIED_IN_PORT_CONF_FILE_DIR,DENIED_PORT_IN);
open_ip_cfg_file(ALLOWED_IN_IP_CONF_FILE_DIR,ALLOWED_IP_IN);
break;
case MODE_IP_ONLY_ALLOWED_OUT:
open_ip_cfg_file(ALLOWED_OUT_IP_CONF_FILE_DIR,ALLOWED_IP_OUT);
break;
case MODE_IP_ONLY_DENIED_OUT:
open_ip_cfg_file(DENIED_OUT_IP_CONF_FILE_DIR,DENIED_IP_OUT);
break;
case MODE_IP_PORT_ALLOWED_OUT:
open_port_cfg_file(ALLOWED_OUT_PORT_CONF_FILE_DIR,ALLOWED_PORT_OUT);
open_ip_cfg_file(ALLOWED_OUT_IP_CONF_FILE_DIR,ALLOWED_IP_OUT);
break;
case MODE_IP_PORT_DENIED_OUT:
open_port_cfg_file(DENIED_OUT_PORT_CONF_FILE_DIR,DENIED_PORT_OUT);
open_ip_cfg_file(ALLOWED_OUT_IP_CONF_FILE_DIR,ALLOWED_IP_OUT);
break;
default:
break;
}
//open_port_cfg_file(DENIED_PORT_CONF_FILE,DENIED_PORT);
nf_register_hook(&my_netfilter[0]);
nf_register_hook(&my_netfilter[1]);
printk("INIT my firewall OK!
\n");
return 0;
}
intinit_firewall()
{
(&ip_allowed_in_node_head)->next=NULL;
(&ip_denied_in_node_head)->next=NULL;
(&port_allowed_in_node_head)->next=NULL;
(&port_denied_in_node_head)->next=NULL;
(&ip_allowed_out_node_head)->next=NULL;
(&ip_denied_out_node_head)->next=NULL;
(&port_allowed_out_node_head)->next=NULL;
(&port_denied_out_node_head)->n