|
马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?注册
×
防火墙作为一种网络或系统之间强制实行访问控制的机制,是确保网络安全的重要手段,在开发设计过程中注重的是产品的通用性、兼容性,将防火墙设计的一般理论和方法与自己系统的具体实践相结合,设计一些小而精、精而强的防火墙程序,本文仅以Linux系统为例,具体说明防火墙程序的设计方法。
一、从程序设计角度看Linux网络
编写防火墙程序并不一定要求对Linux网络内核有多么深刻的理解,只是需要明白在网络内核中有这样一种机制,那就是内核可以自动调用用户编写的防火墙程序,并根据这个防火墙程序返回的结果来决定对网络收发数据报的处理策略。
二、怎样将自己编写的防火墙程序登记到内核中
我们已经知道内核在网络层中自动调用用户编写的防火墙程序。但有一个前提条件就是用户必须正确地将自己编写的防火墙程序登记到内核中。
内核中提供了防火墙的登记和卸载函数,分别是register_firewall和unregister_firewall
1、 register_firewall
函数原型如下:
int register_firewall(int pf,struct firewall_ops *fw)
返回值:0代表成功,小于0表示不成功。
参数:
* 协议标志pf,主要的取值及其代表的协议如下:
2代表Ipv4协议,4代表IPX协议,10代表Ipv6协议等。
* 参数结构fw定义如下:
struct firewall_ops{
struct firewall_ops *next;
int (*fw_forward)(struct firewall_ops *this, int pf,
struct device *dev, void *phdr, void *arg, struct sk_buff **pskb);
int (*fw_input)(struct firewall_ops *this, int pf,
struct device *dev, void *phdr, void *arg, struct sk_buff **pskb);
int (*fw_output)(struct firewall_ops *this, int pf,
struct device *dev, void *phdr, void *arg, struct sk_buff **pskb);
int fw_pf;
int fw_priority;
};
结构中next的域将由内核来修改,使其指向下一个防火墙模块。
fw_pf域为协议标志,含义同上。
fw_priority指定优先级,一般应大于0。
fw_input、fw_output、fw_forward是用户编写的防火墙函数模块,在接收到网络报和发送网络报时内核将调用这些模块,后面将详细讨论。
2、 unregister_firewall
unregister_firewall的原型说明与调用方法同register_firewall。
三、防火墙函数模块的设计
1、防火墙函数模块的返回值
返回值是至关重要的,内核将根据它来决定对网络数据报采取的处理策略。主要返回值及意义如下:
0和1 通知内核忽略该网络报。
-1 通知内核忽略该网络报,并发送不可达到的网络控制报(ICMP报文)。
2 通知内核认可该网络报。
2、各模块函数的入口参数
* 参数this
指向register_firewall中的fw参数结构。
* 参数pf
含义同register_firewall中的pf参数。
* 参数dev
dev是指向数据结构device的指针。在Linux系统中,每一个网络设备都是用device数据结构来描述的。在系统引导期间,网络设备驱动程序向Linux登记设备信息,如设备名、设备的I/O基地址、设备中断号、网卡的48位硬件地址等,device数据结构中包括这些设备信息以及设备服务函数的地址。关于device结构的详细信息可参见netdevice.h头文件。
* 参数phdr
该参数指向链路层数据报报头首址。
* 参数arg
利用这个参数可以向内核传递信息,如重定向时的端口号。
* 参数pskb
此参数是指向sk_buff结构指针的指针。在Linux中,所有网络数据的发送和接收都用sk_buff数据结构表示。在sk_buff数据结构中包含有对应设备结构的device地址、传输层、网络层、链路层协议头地址等。关于sk_buff的定义可参见skbuff.h头文件。
3、防火墙程序示例
下面给出一个简单防火墙程序。需要你对以太协议、IP协议、TCP协议等常用协议有一定的了解。用命令行"gcc -Wall -O2 -c MyFirewall.c"进行编译,再用insmod命令加载程序后,系统将只响应外部网络用TCP协议的80端口所进行的访问。要让系统恢复原有功能,则可用rmmod命令卸载该程序。(那些专用的库函数属于华为公司的内部机密文件,你只是允许引用,看不到里面真实的代码)
// MyFirewall.c 2009年5月7日编写
#ifndef __KERNEL__
# define __KERNEL__ //按内核模块编译
#endif
#ifndef MODULE
# define MODULE //按设备驱动程序模块编译
#endif
#include //最基本的内核模块头文件
#include
#include //最基本的内核模块头文件
#include
#include
#include
#include
#include
#include
#include
#include
#define SOL_ICMP 1
#define PERMIT_PORT 80 //只允许访问TCP的80端口
int zzl_input(struct firewall_ops *this,int pf,struct device *dev,
void *phdr,void *arg,struct sk_buff **pskb)
{//每当收到一个网络报时,此函数将被内核调用
struct tcphdr *tcph; //TCP的头指针
struct iphdr *iph; //IP头指针
struct sk_buff *skb=*pskb;
if (skb->protocol==htons(ETH_P_ARP)){
printk("
Permit a ARP Packet");
return FW_ACCEPT;//允许地址解析协议报
}
if(skb->protocol==htons(ETH_P_RARP)){
printk("
Permit a RARP Packet");
return FW_ACCEPT;//允许反向地址解析协议报
}
if(skb->protocol==htons(ETH_P_IP))
{
iph=skb->nh.iph;
if (iph->protocol==SOL_ICMP)
{
printk("
Permit a ICMP Packet");
return FW_ACCEPT;//允许网络控制报
}
if(iph->protocol==SOL_TCP){
tcph=skb->h.th;
if(tcph->dest==PERMIT_PORT){
printk("
Permit a valid access");
return FW_ACCEPT;//允许对TCP端口80的访问
}
}
}
return FW_REJECT;//禁止对本计算机的所有其它访问
}
int zzl_output(struct firewall_ops *this,int pf,struct device *dev,
void *phdr,void *arg,struct sk_buff **pskb)
{//程序编写方法同zzl_input函数模块
printk("
zzl_output is called ");
return FW_SKIP;
}
int zzl_foreward(struct firewall_ops *this,int pf,struct device *dev,
void *phdr,void *arg,struct sk_buff **pskb)
{//程序编写方法同zzl_input函数模块
printk("
zzl_foreward is called ");
return FW_SKIP;
}
struct firewall_ops zzl_ops=
{
NULL,
zzl_foreward,
zzl_input,
zzl_output,
PF_INET,
01
};
int init_module(void)
{
if(register_firewall(PF_INET,&zzl_ops)!=0)
{
printk("
unable register firewall");
return -1;
}
printk("
zzl_ops=%p",&zzl_ops);
return 0;
}
void cleanup_module(void)
{
printk("unload
");
unregister_firewall(PF_INET,&zzl_ops);
}
这只是一个用C语言和网络协议实现的一个基本反火强的应用程序框架的,很多的功能都在是在这个基础扩展的。
一定要学好C语言,或者精通某一门语言,当你工作之后,你很难在区别你写程序是具体用的那中语言,其实本身C语言和VC语言或者C++语言的界定及不是很清楚,也可以这么理解VC语言或者C++语言给C语言加了一下框子,使其开发程序更加灵活,对于软件控制硬件的程序基本上都是用C语言等这些底层语言开发的。
个人的意见,希望对大家有所启迪。 |
|