⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 linux防火墙实现技术比较.htm

📁 这是我对防火墙技术的一些见解
💻 HTM
📖 第 1 页 / 共 3 页
字号:
        <BR>skb2=skb_clone(skb, GFP_ATOMIC); <BR>if(skb2) 
        <BR>pt_prev-&gt;func(skb2, skb-&gt;dev, pt_prev); 
        <BR>这样的话如果你想丢弃此包的话,光将其free掉是不够的,因为它只是其中的一份拷贝而已。 
        <BR>FW1是怎么解决这个问题的呢?见下面的代码(从汇编代码翻译成的C程序): <BR><BR>packet_type 
        *fw_type_list=NULL; <BR><BR>static struct packet_type fw_ip_packet_type 
        = <BR>{ <BR>__constant_htons(ETH_P_IP), <BR>NULL, /* All devices */ 
        <BR>fw_filterin, <BR>NULL, <BR>NULL, /* next */ <BR>}; 
        <BR><BR>fwinstallin(int isinstall ) <BR>{ <BR>packet_type *temp; 
        <BR><BR>/*安装*/ <BR>if(isinstall==0){ 
        <BR>dev_add_pack(&amp;fw_ip_packet_type); <BR>fw_type_list = 
        fw_ip_packet_type-&gt;next; <BR><BR>for(temp = fw_type_list; temp; 
        temp=temp-&gt;temp) <BR>dev_remove_pack(temp); <BR>} <BR>/*卸载*/ <BR>else 
        { <BR>dev_remove_pack(&amp;fw_ip_packet_type); <BR><BR>for(temp = 
        fw_ip_packet_type; temp; temp=temp-&gt;next) <BR>dev_add_pack(temp); 
        <BR>} <BR>} 
        <BR><BR>不难看出,FW1把ip_packet_type歇载掉了,然后自己在自己的处理函数(fw_filterin)中调ip_recv。 
        <BR><BR>输出的挂载和lkm的手法一样,更改dev-&gt;hard_start_xmit。dev结构在2.2版本的发展过程中变了一次,为了兼容FW1对这点也做了处理(通过检查版本号来取偏移)。 
        <BR><BR>还有一款linux下的防火墙产品WebGuard(<A 
        href="http://www.gennet.com.tw/b5/csub_webguard.html" 
        target=_blank>http://www.gennet.com.tw/b5/csub_webguard.html</A>)采用的手法与FW1其非常类似。有兴趣的人可以自行研究一下。 
        <BR><BR><BR>四 规则 <BR><BR>4.0 综述 <BR><BR>4.1 ipchains <BR><BR>man 
        ipfw可以看到这一段的详细解释。关键数据结构如下: 
        <BR><BR>规则链用ip_chain结构来表示,缺省有input,ouptput,forward三条链。在配置规则的时候,也可以添加新的链。每条链事实上就是一组相关的规则,以链表的形式存储。 
        <BR>struct ip_chain <BR>{ <BR>ip_chainlabel label; /* Defines the label 
        for each block */ <BR>struct ip_chain *next; /* Pointer to next block */ 
        <BR>struct ip_fwkernel *chain; /* Pointer to first rule in block */ 
        <BR>__u32 refcount; /* Number of refernces to block */ <BR>int policy; 
        /* Default rule for chain. Only * <BR>* used in built in chains */ 
        <BR>struct ip_reent reent[0]; /* Actually several of these */ <BR>}; 
        <BR><BR>每条规则用一个ip_fwkernel结构表示: <BR>struct ip_fwkernel <BR>{ <BR>struct 
        ip_fw ipfw; <BR>struct ip_fwkernel *next; /* where to go next if current 
        <BR>* rule doesn match */ <BR>struct ip_chain *branch; /* which branch 
        to jump to if <BR>* current rule matches */ <BR>int simplebranch; /* Use 
        this if branch == NULL */ <BR>struct ip_counters counters[0]; /* 
        Actually several of these */ <BR>}; 
        <BR><BR>ip_fwkernel中的一个重要部分就是ip_fw,用来表示待匹配的数据包消息: <BR>struct ip_fw <BR>{ 
        <BR>struct in_addr fw_src, fw_dst; /* Source and destination IP addr */ 
        <BR>struct in_addr fw_smsk, fw_dmsk; /* Mask for src and dest IP addr */ 
        <BR>__u32 fw_mark; /* ID to stamp on packet */ <BR>__u16 fw_proto; /* 
        Protocol, 0 = ANY */ <BR>__u16 fw_flg; /* Flags word */ <BR>__u16 
        fw_invflg; /* Inverse flags */ <BR>__u16 fw_spts[2]; /* Source port 
        range. */ <BR>__u16 fw_dpts[2]; /* Destination port range. */ <BR>__u16 
        fw_redirpt; /* Port to redirect to. */ <BR>__u16 fw_outputsize; /* Max 
        amount to output to <BR>NETLINK */ <BR>char fw_vianame[IFNAMSIZ]; /* 
        name of interface "via" */ <BR>__u8 fw_tosand, fw_tosxor; /* Revised 
        packet priority */ <BR>}; <BR><BR>2.2内核中网络包与规则的实际匹配在ip_fw_check中进行。 
        <BR><BR>4.2 iptables <BR><BR>一条规则分为三部分: <BR>struct ipt_entry 
        file://主要用来匹配IP头 <BR>struct ip_match file://额外的匹配(tcp头,mac地址等) 
        <BR>struct ip_target file://除缺省的动作外(如ACCEPT,DROP),可以增加新的(如REJECT)。 
        <BR><BR>man iptable: <BR>&gt;A firewall rule specifies criteria for a 
        packet, and a <BR>&gt;target. If the packet does not match, the next 
        rule in <BR>&gt;the chain is the examined; if it does match, then the 
        next <BR>&gt;rule is specified by the value of the target, which can be 
        <BR>&gt;the name of a user-defined chain, or one of the special 
        <BR>&gt;values ACCEPT, DROP, QUEUE, or RETURN. 
        <BR><BR>2.4内核中网络包与规则的实际匹配在ip_do_table中进行。这段代码的流程在 <BR>netfilter hacking 
        howto 4.1.3描述的非常清楚。 <BR><BR>简化代码如下: <BR>/* Returns one of the generic 
        firewall policies, like NF_ACCEPT. */ <BR>unsigned int 
        <BR>ipt_do_table(struct sk_buff **pskb, <BR>unsigned int hook, <BR>const 
        struct net_device *in, <BR>const struct net_device *out, <BR>struct 
        ipt_table *table, <BR>void *userdata) <BR>{ <BR>struct ipt_entry *e; 
        <BR>struct ipt_entry_target *t; <BR>unsigned int verdict = NF_DROP; 
        <BR><BR>table_base = (void *)table-&gt;private-&gt;entries <BR>+ 
        TABLE_OFFSET(table-&gt;private, <BR>cpu_number_map(smp_processor_id())); 
        <BR>e = get_entry(table_base, table-&gt;private-&gt;hook_entry[hook]); 
        <BR><BR>... <BR>ip_packet_match(ip, indev, outdev, &amp;e-&gt;ip, 
        offset); <BR><BR>... <BR>IPT_MATCH_ITERATE(e, do_match, *pskb, in, out, 
        offset, protohdr, datalen, &amp;hotdrop) <BR><BR>... <BR>t = 
        ipt_get_target(e); <BR><BR>... <BR>verdict = 
        t-&gt;u.kernel.target-&gt;target(pskb, hook, in, out, t-&gt;data, 
        userdata);//非标准的target走这一步 <BR><BR>... <BR>return verdict; <BR>} 
        <BR><BR>流程: <BR>---&gt;NF_HOOK();(/include/linux/netfilter.h) 
        <BR>---&gt;nf_hook_slow;(/net/core/netfilter.c) 
        <BR>---&gt;nf_iterate();(/net/core/netfilter.c) 
        <BR>---&gt;然后运行登记的函数;如果你希望有一套ipt_entry结构规则,并将它放到table里,你此时便可调用ipt_do_table来匹配。 
        <BR><BR>在2.4内核中,规则本身也是可扩展的,体现可自己定义并添加新的ip_match和ip_target上。 <BR><BR>4.2 
        FW1 <BR>未作分析。 <BR><BR><BR>五 与应用层的交互 <BR><BR>5.0 综述 
        <BR><BR>防火墙除了内核里的功能以外,还需要在应用层有相应的的配置工具,如添加修改规则等,这就涉及如何与内核通信的问题。 
        <BR>内核模块有三种办法与进程打交道:首先是系统调用,缺点是必须添加新的系统调用或修改原有的,造成对内核代码原有结构的变换;第二种办法是通过设备文件(/dev目录下的文件),不必修改编译原有的代码,但在使用之前要先用mknod命令产生一个这样的设备;第三个办法便是使用proc文件系统。 
        <BR><BR>5.1 ipchains 
        <BR>由于ipchains是已经是内核的正式一部分,它采用了修改系统调用的办法来添加修改命令,采用的办法就是扩展setsockopt系统调用: 
        <BR>int setsockopt (int socket, IPPROTO_IP, int command, void *data, int 
        length) <BR><BR>man ipfw可以获得这方面的细节。 <BR><BR>ipchains应用程序首先要需要建立一个raw 
        socket(libipfwc.c),然后在之上调用setsockopt。 <BR>sockfd = socket(AF_INET, 
        SOCK_RAW, IPPROTO_RAW) <BR><BR>调用顺序: <BR>ipchains在应用层调用setsockopt,进入内核: 
        <BR>---&gt;sys_socketcall(net/socket.c) 
        <BR>---&gt;sys_setsockopt(net/socket.c) 
        <BR>---&gt;inet_setsockopt(net/ipv4/af_inet.c) 
        <BR>---&gt;sock_setsockopt(net/core/sock.c) 
        <BR>---&gt;raw_setsockopt(net/ipv4/raw.c) 
        <BR>---&gt;ip_setsockopt(net/ipv4/ip_sockglue.c) 
        <BR>---&gt;ip_fw_ctl(net/ipv4/ip_fw.c) <BR><BR>5.2 iptables 
        <BR>原理同ipchains, 但内部命令格式作了大幅简化。详见nf_setsockopt()。 <BR><BR>5.3 FW1 
        <BR>FW1 登记了一个字符设备,通过它来进行用户空间与内核空间的交互。相关代码(从汇编代码翻译成的C程序)如下: 
        <BR><BR>static unsigned int fw_major=0; <BR><BR>static struct 
        file_operations fw_fops= <BR>{ <BR>NULL, /* lseek */ <BR>fw_read, /* 
        read */ <BR>fw_write, /* write */ <BR>NULL, /* readdir */ <BR>fw_poll, 
        /* poll */ <BR>fw_ioctl, /* ioctl */ <BR>NULL, /* mmap */ <BR>fw_open, 
        /* open */ <BR>NULL, /* flush */ <BR>fw_release /* release */ <BR>NULL, 
        /* fsync */ <BR>}; <BR><BR>int init_module() <BR>{ <BR>... <BR>/*man 
        register_chrdev <BR>On success, register_chrdev returns 0 if major is a 
        number <BR>other then 0, otherwise Linux will choose a major number and 
        <BR>return the chosen value.*/ 
        <BR>if(fw_major=register_chrdev(UNNAMED_MAJOR, “fw”, &amp;fw_fops)) 
        <BR>return -1; <BR>... <BR>} <BR><BR>void cleanup_module() <BR>{ <BR>... 
        <BR>unregister_chrdev(fw_major, "fw"); <BR>... <BR><BR>} 
        <BR><BR>fw_ioctl()用来做配置工作。 <BR><BR><BR>六 碎片的处理 <BR><BR>6.0 综述 
        <BR>关于分片重组的实现可参看【13】。 <BR><BR>6.1 ipchains 
        <BR>在2.2内核中除非设置了alway_defrag,否则包过滤模块不会对经过的包进行重组。它采用的办法是只看第一片,因为只有这一片中有完整的头信息,而后序的分片一律允许通过。为了防止分片欺骗(比如第一片极小,把传输层信息放到了第二片中),对这种正常情况中不可能出现的包做了而外的处理(太小的分片会被丢弃)。 
        <BR><BR>6.2 iptables <BR>在2.4内核有些变化,如果启动了conncetion 
        track,所有到达防火墙的碎片都会重组,这点在以后可能会变化,正如howto 
        中说的,现在考虑的还只是功能的完备性,效率还要在以后的版本中改进。检测点也有了变化,输入检测在改在重组之后。 <BR><BR>6.3 FW1 
        <BR>FW1对分片也做了额外处理,但目前尚未对其实现做仔细的分析。 <BR><BR><BR>七 状态检测 <BR><BR>7.0 综述 
        <BR>基于状态的检测对管理规则提出了非常大的方便,现在已成了防火墙的一项基本要求。但目的明确之后,其实现可以选择多种不同的方法。 
        <BR><BR>7.1 ipchains 
        <BR>ipchains本身不能完成状态检测,但有几份pacth为它做了一下这方面的补充,采用的是简单的动态添加规则的办法,这是作者对其的介绍: 
        <BR>&gt; I believe it does exactly what I want: Installing a temporary 
        <BR>&gt; "backward"-rule to let packets in as a response to an <BR>&gt; 
        outgoing request. <BR><BR>7.2 iptables 
        <BR>在2.4内核中,基于状态的检测已经实现,利用的是connection track模块。此模块检查所有到来的数据包,将得到的状态(enum 
        ip_conntrack_status)保留在sk_buff结构中(即skb-&gt;nfct,可通过ip_conntrack_get()得到)。 
        <BR>在规则中要指明状态信息(作为一个ipt_match),既实际上仍是比较每一条规则。从效率上,这种处理方式感觉不如下面FW1采用的方式好。 
        <BR><BR>7.3 FW1 
        <BR>这段的代码没有做分析,但有一些文章通过黑箱操作的办法“猜测“出了它的实现原理,如【1】。除规则表以外,FW1另外维护一份状态表。当一个新的连接发生的时候,FW1与规则表配备,如果允许通过的话,则在状态表中建立相应表项。以后的数据过来的时候首先匹配状态表,如果它属于一个连接,便允许通过,而不再检查规则表。 
        <BR>草草看了一下BSD下的防火墙ipfilter的howto,感觉它的实现与FW1基本相同。 <BR><BR><BR>八 函数指针的问题 
        <BR>许多初读内核的人对函数指针的应用很不适应,在netfilter中更是用的非常广泛。大量register函数的应用,使得netfilter非常的模块化,但是给初学者带来的问题也不小。 
        <BR><BR>这里是linuxforum上的一份帖子,如果看代码时对函数指针的指向总是糊里糊涂的话,可借鉴一下这个思路(当然关键还是要找到指针初始化的地方): 
        <BR><BR>&gt;Linux内核技术 <BR>&gt;herze (stranger ) 01/15/01 02:54 PM 
        <BR>&gt;高手指点:PPP的发送函数在那里? 
        <BR>&gt;在Linux内核2.4.0中对于PPP数据包已经打好的包,内核中的ppp_generic.c文件中发送的流程好像如下 
        <BR>&gt;ppp_file_write()-&gt;ppp_xmit_process()-&gt;ppp_push()(可能也由其它的发送流程,但是最后都是 
        <BR>&gt;用到了ppp_push())这个函数,而这个函数调用了一个struct channel中struct ppp_channel中的 
        <BR>&gt;struct ppp_channel_ops 中的一个函数指针 <BR>&gt;int (*start_xmit)(struct 
        ppp_channel *, struct sk_buff *)来进行发送的,但是下面我就不明白了。 
        <BR>&gt;虽然在drivers/char/cyclades.c和drivers/char/serial167.c中找到了 
        <BR>&gt;start_xmit( struct cyclades_port *info )但是函数说明都不相同。 <BR>&gt;请教: 
        <BR>&gt;int (*start_xmit)(struct ppp_channel *, struct sk_buff *) 
        <BR>&gt;到底这个函数指针是指到了什么地方? <BR>&gt;是不是和具体的硬件有关,但是我怎么在内核中找不到对应的函数? 
        <BR><BR>&gt;Linux内核技术 <BR>&gt;yawl (stranger ) 01/15/01 11:31 PM 
        <BR>&gt;思路这样 [re: herze] 
        <BR>&gt;内核中常有这样的类似处理,查找这种函数指针的一个好办法,就是找那种结构的实例,对于你的问题,就是找 
        <BR>&gt;ppp_channel_ops,最终会找到async_ops(ppp_async.c)和sync_ops(ppp_synctty.c),没看过这块的 
        <BR>&gt;具体代码,不敢多说,但思路如此。 <BR><BR><BR>九 后记 
        <BR>尽管此文中是在【12】的基础之上完成的,但是在内容上并未完全包括前者,感兴趣的朋友在那篇文章上可能能找到一些有趣的原始信息。由于时间关系,本文在此主题上的探讨仍显粗浅,对此只能说抱歉了。 
        <BR><BR><BR>十 参考文献 <BR>【1】了解Check Point FW-1状态表 <BR><A class=red 
        href="http://magazine.nsfocus.com/detail.asp?id=538" target=_blank><A 
        href="http://magazine.nsfocus.com/detail.asp?id=538" 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -