《Linux防火墙程序设计.doc》由会员分享,可在线阅读,更多相关《Linux防火墙程序设计.doc(15页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、 Linux防火墙程序设计 Yahoo、eBay、CNN.com、Amazon、B和 E*Trade等著名商业网站连续遭到黑客攻击,造成了数以十亿美元的损失,向世人再一次敲响了网络并不安全的警钟。防火墙作为一种网络或系统之间强制实 行访问控制的机制,是确保网络安全的重要手段。目前社会上各种商业产品的防火墙非常多,功能也大都很强。我们暂且不管这些防火墙产品的价格如何,由于它们 在开发设计过程中注重的是产品的通用性、兼容性,考虑更多的是市场和利润,因此对于某些特殊的应用就不一定很合适。如果用户能根据自己的实际需要,将防火 墙设计的一般理论和方法与自己系统的具体实践相结合,设计一些小而精、精而强的防
2、火墙程序,则往往可以发挥出比花大价钱买来的通用型防火墙更好的作用。由于篇幅所限,本文不可能对防火墙的一般理论和结构进行深入的讨论,因此仅以Linux系统为例,具体说明防火墙程序的设计方法。一、 从程序设计角度看Linux网络编写防火墙程序并不一定要求对Linux网络内核有多么深刻的理解,只是需要明白在网络内核中有这样一种机制,那就是内核可以自动调用用户编写的防火墙程序,并根据这个防火墙程序返回的结果来决定对网络收发数据报的处理策略。二、 怎样将自己编写的防火墙程序登记到内核中我们已经知道内核在网络层中自动调用用户编写的防火墙程序。但有一个前提条件就是用户必须正确地将自己编写的防火墙程序登记到内
3、核中。内核中提供了防火墙的登记和卸载函数,分别是register_firewall和unregister_firewall,参见firewall.c。1、 register_firewall函数原型如下:int register_firewall(int pf,struct firewall_ops *fw)返回值:0代表成功,小于0表示不成功。参数:* 协议标志pf,主要的取值及其代表的协议如下:2代表Ipv4协议,4代表IPX协议,10代表Ipv6协议等。* 参数结构fw定义如下:struct firewall_opsstruct firewall_ops *next;int (*fw_f
4、orward)(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 *p
5、hdr, 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_firewallunregister_firewall的原型说明与调用方法同register_firewall。三、 防火墙函数模块的设计1、 防火墙函
6、数模块的返回值返回值是至关重要的,内核将根据它来决定对网络数据报采取的处理策略。主要返回值及意义如下:0和1 通知内核忽略该网络报。-1 通知内核忽略该网络报,并发送不可达到的网络控制报(ICMP报文)。2 通知内核认可该网络报。2、 各模块函数的入口参数* 参数this指向register_firewall中的fw参数结构。* 参数pf含义同register_firewall中的pf参数。* 参数devdev 是指向数据结构device的指针。在Linux系统中,每一个网络设备都是用device数据结构来描述的。在系统引导期间,网络设备驱动程序向 Linux登记设备信息,如设备名、设备的I/
7、O基地址、设备中断号、网卡的48位硬件地址等,device数据结构中包括这些设备信息以及设备服务函数 的地址。关于device结构的详细信息可参见netdevice.h头文件。* 参数phdr该参数指向链路层数据报报头首址。* 参数arg利用这个参数可以向内核传递信息,如重定向时的端口号。* 参数pskb此 参数是指向sk_buff结构指针的指针。在Linux中,所有网络数据的发送和接收都用sk_buff数据结构表示。在sk_buff数据结构中包含有 对应设备结构的device地址、传输层、网络层、链路层协议头地址等。关于sk_buff的定义可参见skbuff.h头文件。3、防火墙程序示例下
8、面给出一个简单防火墙程序。在这里假设读者对以太协议、IP协议、TCP协议等常用协议有一定的了解。用命令行gcc -Wall -O2 -c MyFirewall.c进行编译,再用insmod命令加载程序后,系统将只响应外部网络用TCP协议的80端口所进行的访问。要让系统恢复原有功 能,则可用rmmod命令卸载该程序,源代码见网站上的同名文章。/ MyFirewall.c 2000年3月7日编写#ifndef _KERNEL_# define _KERNEL_ /按内核模块编译#endif#ifndef MODULE# define MODULE /按设备驱动程序模块编译#endif#includ
9、e linux/module.h /最基本的内核模块头文件#include linux/sched.h#include linux/kernel.h /最基本的内核模块头文件#include linux/netdevice.h#include linux/ip.h#include linux/tcp.h#include linux/skbuff.h#include linux/proc_fs.h#include linux/if.h#include linux/in.h#include linux/firewall.h#define SOL_ICMP 1#define PERMIT_PORT
10、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(nPermit a ARP Packet);return FW_AC
11、CEPT;/允许地址解析协议报if(skb-protocol=htons(ETH_P_RARP)printk(nPermit a RARP Packet);return FW_ACCEPT;/允许反向地址解析协议报if(skb-protocol=htons(ETH_P_IP)iph=skb-nh.iph;if (iph-protocol=SOL_ICMP)printk(nPermit a ICMP Packet);return FW_ACCEPT;/允许网络控制报if(iph-protocol=SOL_TCP)tcph=skb-h.th;if(tcph-dest=PERMIT_PORT)pri
12、ntk(nPermit 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(nzzl_output is called );return FW_SKIP;int zzl_foreward(struct firewall_
13、ops *this,int pf,struct device *dev,void *phdr,void *arg,struct sk_buff *pskb)/程序编写方法同zzl_input函数模块printk(nzzl_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(nunable register firewall);return -1;printk(nzzl_ops=%p,&zzl_ops);return 0;void cleanup_module(void)printk(unloadn);unregister_firewall(PF_INET,&zzl_ops); (完)
限制150内