iptables功能介绍.doc_第1页
iptables功能介绍.doc_第2页
iptables功能介绍.doc_第3页
iptables功能介绍.doc_第4页
iptables功能介绍.doc_第5页
已阅读5页,还剩9页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

iptables功能说明一、Netfilter介绍: netfilter是由Rusty Russell提出的Linux 2.4内核防火墙框架,该框架既简洁又灵活,可实现安全策略应用中的许多功能,如数据包过滤、数据包处理、地址伪装、透明代理、动态网络地址转换(Network Address Translation,NAT),以及基于用户及媒体访问控制(Media Access Control,MAC)地址的过滤和基于状态的过滤、包速率限制等。 Netfilter在ipv4中的结构:Hook1: NF_IP_PREROUTING 、 Hook2: NF_IP_LOCAL_INHook3 :NF_IP_FORWARD 、 Hook4 :NF_IP_POST_ROUTINGHook5 :LOCAL_OUT二、iptables的介绍: Iptables 是与 Linux 内核集成的 IP 信息包过滤系统。如果 Linux 系统连接到因特网或 LAN、服务器或连接 LAN 和因特网的代理服务器, 则该系统有利于在 Linux 系统上更好地控制 IP 信息包过滤和防火墙配置。 netfilter/iptables IP 信息包过滤系统是一种功能强大的工具,可用于添加、编辑和除去规则,这些规则是在做信息包过滤决定时,防火墙所遵循和组成的规则。这些规则存储在专用的信息包过滤表中,而这些表集成在 Linux 内核中。在信息包过滤表中,规则被分组放在我们所谓的链(chain)中。 虽然 netfilter/iptables IP 信息包过滤系统被称为单个实体,但它实际上由两个组件netfilter 和 iptables 组成。 netfilter 组件也称为内核空间(kernelspace),是内核的一部分,由一些信息包过滤表组成,这些表包含内核用来控制信息包过滤处理的规则集。 iptables 组件是一种工具,也称为用户空间(userspace),它使插入、修改和除去信息包过滤表中的规则变得容易。Iptables结构图:Filter表:Filter表不会对数据报进行修改,而是对数据进行过滤。它是通过钩子函数NF_IP_POSTROUTING 、NF_IP_PREROUTING、NF_IP_LOCALOUT 接入netfilter框架。因此对于任何一个数据报只有一个地方对其进行过滤。Nat表:Nat 表监听三个netfilte钩子函数:NF_IP_PREROUTING、NF_IP_POSTROUTING、NF_IP_LOCALOUT 。NF_IP_PREROUTING实现对需要转发的数据报的源地址进行地址转换,NF_IP_POSTROUTING则对需要转发的数据报的目的地址进行转换,NF_IP_LOCALOUT实现对于本地数据报的目的地址的转换。Nat表与filter表不同,只有新连接的第一个数据报将遍历表格,而随后的数据报将根据第一个数据报的结果进行同样的转换处理。Mangle表:Mangle表在NF_IP_PREROUTING、NF_IP_LOCALOUT钩子中进行注册。使用mangle表可以实现对数据报的修改或给数据报附上一些带外数据报。如mangle表支持修改TOS位及设置skb的nfmard字段。数据包在iptables中的路径图:三、Iptables原理分析:Iptables的主要函数:int main(int argc, char *argv) /主函数int do_command() /命令行处理*handle = iptc_init(*table); /从内核获取表的规则快照 list_entries /显示规则 在分析iptables工作流程时,以一条iptabls命令的执行来分析Iptables的代码。 假设要下的规则为:iptabls A INPUT i eth0 p tcp -syn s /8 d 84 j ACCEPT该规则是将源地址段在/8范围之内的主机发送的SYN包,接受的网口为eth0,且目的地址为84的,执行ACCEPT以下是执行该条命令时,iptables的流程分析。(一)、命令行的入口int main(int argc, char *argv) (iptables-standalone.c)整个iptables命令行的入口。该函数设置了默认的table=”filter”,即当命令行中没有-t选项是,就使用默认的filter表。同时还初始化了该应用程序的名字,版本号等。#ifdef NO_SHARED_LIBS init_extensions();#endif以上代码为没有定义共享库的话,要执行init_extensions()。这里我们假设不使用共享库,所以调用该函数。该函数实在执行make的时候extensions/自动生成的initext.c中的函数。在该函数里调用了所有扩展模块的init函数。注册所有的match,以及标准和扩展的target。所有的match和target都加入到iptables.c中对应的全局链表之中。以后find_match和find_target是就是搜索的这两个链表。/* Keeping track of external matches and targets: linked lists. */struct iptables_match *iptables_matches = NULL;struct iptables_target *iptables_targets = NULL;这样在不使用共享库的情况下,每次下命令之前都要初始化一下全局的链表,当然已经存在的话,就不会再次register的。(二)、命令行的核心处理do_command()是处理Iptables命令的核心部分。int do_command(int argc, char *argv, char *table, iptc_handle_t *handle)(iptables.c)1. 函数首先对一些结构、变量进行初始化。 基本上涵盖了一条规则可能出现的大部分基本参数。其中,重要的结构体有struct ipt_entry fw, *e,这两个应该是存储一条防火墙规则的;struct iptables_match *m,struct iptables_target *target,*t;分别用于存储match和target. 并将全局的match和target链表的对应flags和used为初始化为0.2. 命令行解析。初始化完毕后,进入while循环,分析用户输入的命令,设置相关的标志变量,然后根据相应标志,调用对应的处理函数。这里是我们要进行详细分析的地方。我们要分析的命令为:iptabls A INPUT i eth0 p tcp -syn s /8 d 84 j ACCEPT以下开始命令行解析:(1) 处理 A 选项 调用add_command函数,主要是对command变量进行逻辑处理。该函数的输入参数 newcmd = CMD_APPEND=0x0010,othercmds= CMD_NONE=0x0000,invert = 0; 输出参数command(初始值为0), 执行完该函数之后, command = CMD_APPEND=0x0010, chain = “INPUT” 然后程序break跳出switch语句,并将invert = FALSE,进行while的下一个循环,及处理下一个选项。(2) 处理 i 选项 调用check_inverse函数。该函数主要是检查-i对应的参数中是否使用了取反标志”!”,因此这里我们使用的是”eth0”,因此该函数直接返回FALSE。invert=0。 调用set_option函数是指对应的选项。该函数的输入参数option= OPT_VIANAMEOUT(0x0080), invert=0,输出参数options(初始化为0),fw.ip.invflags(初始化为0)。经过该函数处理之后,options = OPT_VIANAMEIN=0x0080;fw.ip.invflags=0. 调用parse_interface函数进行网络接口的解析。该函数的参数输入参数argvoptind-1=”eth0”, 输出参数fw.ip.inifaceIFNAMSIZ=“”, fw.ip.iniface_maskIFNAMSIZ=“”, 其中IFNAMSIZ=15。处理之后,fw.ip.inifaceIFNAMSIZ=“eth0”; fw.ip.iniface_maskIFNAMSIZ=0xFF, 0xFF, 0xFF, 0xFF, 0xFF;fw.nfcache = NFC_IP_IF_IN = 0x0004;(3) 处理 p 选项调用check_inverse函数,检查这里设置的协议参数是否使用了取反标志”!”。我们这里使用的是tcp,因此该函数直接返回FALSE。invert仍旧为0。调用set_option函数是指对应的选项。可以参照(2)中该函数的处理方法。options 的初始值为0x0080,最终处理完毕之后options |= OPT_PROTOCOL(0x0008) = 0x0088;fw.ip.invflags=0然后协议字串tcp全部转化为小写,protocol = “tcp”。调用parse_protocol函数将该协议字符串转换为TCP对应的协议号6,to = 6;fw.nfcache |= NFC_IP_PROTO = 0x0004 | 0x0020 = 0x0024;(4) 处理 -syn选项 由于该选项并不在全局变量opts里面,所以程序会进入switch语句的default分支执行。 进行该分支处理时一些变量的初始值:target=NULL, m=NULL,全局链表iptables_matches的used选项都为0protocol = “tcp” ,options = 0x0088, proto_used = 0根据以上参数的值,这里要执行的动作为加载该协议(m-init(), 即libipt_tcp.c中init(),并且将协议的一些选项扩展到全局变量opts里面。具体代码执行是进入该分支的if(m=NULL&)里面,具体执行的结果如下:m指向全局match链表中tcp的match。(libipt_tcp.c)proto_used = 1;size = IPT_ALIGN(sizeof(struct ipt_entry_match) + m-size;m-m = fw_calloc(1, size); (m-m为内核总的match部分)m-m-u.match_size = size; = “tcp”;m-used = 1;调用m-init(m-m, &fw.nfcache),执行init()(libipt_tcp.c)。仅是将match中的tcp的sport和dport的最大值置为0xFFFF. struct ipt_entry_match 中的data主要用于表示真正数据部分的开始,是通过fw_calloc为整个结构体以及data申请的内存,以后对数据的操作都可以通过data来索引。init(struct ipt_entry_match *m, unsigned int *nfcache) struct ipt_tcp *tcpinfo = (struct ipt_tcp *)m-data; tcpinfo-spts1 = tcpinfo-dpts1 = 0xFFFF;merge_options将tcp的一些选项扩展到全局变量opts里面。这样就可以解析 -syn选项了。opts包含了tcp协议的选项参数。并且全局变量global_option_offset += OPTION_OFFSET = 256; m-option_offset= global_option_offset =256;这里有点需要注意,就是新加到opts全局结构体中的部分,即tcp对应的option结构中所有的val成员都被赋值为:mergenum_old + i.val += *option_offset; (见merge_options函数)这里主要是为了区别和原先已有option中的val成员。而且在以后添加更多match模块的时候,都要做这样的动作。因此在命令行解析的时候,通过getopt_long得到的这些match中的命令行参数值的时候,需要先减去对应的m-option_offset,然后才能正确的parse.然后两行代码: optind-; continue;是让程序进入下一个while循环,并再次处理-syn参数。因为以上的处理只是将tcp协议的match进行了初始化工作,并没有处理该参数。因此,程序再次进入switch的default分支,不过这次是在if(!target&),由于对应tcp的match结构体的used被置1,即m-used =1; 因此程序要进行m-parse进行libipt_tcp中的parse()函数对命令行参数进行处理。该函数的第一个参数的使用方法上面已经解释过了。以下就是parse()函数对-syn的处理结果:(struct ipt_tcp *)m-data)-flg_mask = 0x16(SYN,ACK,RST);(struct ipt_tcp *)m-data)-flg_cmp = 0x02(SYN)m-flags |= TCP_FLAGS = 0x04;fw.nfcache |= NF_IP_TCP_FLAGS(0x0100) = 0x0024 | 0x0100=0x0124至此,iptables对syn选项的解析已经完成。(5) 处理-s选项同样还是check_inverse,set_option的处理,只有options变量改变;options |= OPT_SOURCE(0x0002) = 0x0088 | 0x0002 = 0x008a;shostnetworkmask= “/24”;fw.nfcache |= NFC_IP_SRC(0x0001)= 0x0124 | 0x0001 = 0x0125;(6) 处理-d选项同样还是check_inverse,set_option的处理,只有options变量改变;options |= OPT_DESTINATION (0x0004) = 0x008a | 0x0004 = 0x008e;dhostnetworkmask= “84”;fw.nfcache |= NFC_IP_DST (0x0002)= 0x0125 | 0x0002 = 0x0127;(7) 处理-j选项 首先还是set_option函数的处理: options |= OPT_JUMP(0x0010) = 0x008e | 0x0010 = 0x009e; 然后jumpto =parse_target(“ACCEPT”),主要是检查一下该字符串是否合法;接着target =find_target(jumpto, TRY_LOAD);该函数返回target为”standard”(包含了ACCEPT, DROP, QUEUE,RETURN等目标)的结构体指针。 并且: target-loaded = 1; target-used = 1 jumpto = “ACCEPT” size = IPT_ALIGN(sizeof(struct ipt_entry_target)+ target-size; target-t = fw_calloc(1, size); /分配内存给struct ipt_entry_target target-t-u.target_size = size; = “ACCEPT”这里的target-init指向了libipt_standard.c中的init(),该函数并未执行任何动作。merge_options又是将该libipt_standard.c的 opts加入到全局的opts中。由于ACCEPT目标是标准的,这里实际上并未往全局的opts中添加任何内容。仅修改了如下变量 global_option_offset += OPTION_OFFSET = 256+256=512; target-option_offset= global_option_offset =512;至此,命令行已经解析完毕,下面要接着对解析出来的各个参数进行进一步处理。3. 相关参数的检查 /*执行libipt_tcp.c中的final_check*/ m-final_check(m-mflags);/*执行libipt_standard.c中的final_check*/target-final_check(target-tflags);随后是对optind,invert,command的检查,接着的if (command &)对我们的参数没有产生任何影响。分别对shostnetworkmask,dhostnetworkmask调用parse_hostnetworkmask函数,执行的结果如下:saddrs0-s_addr = 0x0a000000 ();fw.ip.smsk.s_addr = 0xff000000 ();nsaddrs = 1;daddrs0-s_addr = 0x0a011cb8 (84);fw.ip.dmsk.s_addr = 0xffffffff (55);ndaddrs = 1;最后调用generic_opt_check(command, options)对command和options进行检查。主要是检查iptables中的command和options是否搭配。所有的搭配情况保存在全局的数组static char commands_v_optionsNUMBER_OF_CMDNUMBER_OF_OPT. 下面则要从内核表里取出对应表的全部信息。4. 取出内核中相应表的全部信息 因为在main函数中iptc_handle_t handle = NULL; 所以这里要执行的代码为:*handle = iptc_init(*table)这里返回一个iptc_handle_t *handle的结构体指针,该指针指向从内核中去中的”filter”(默认)表对应的所有信息。 先取出info结构,获取表的一些大概信息,然后再获取整个表的规则。随后的两个if (!*handle)都是判断*handle是否为NULL,如果是的话则说明有错误,获取不到对应表的相关信息。我们这里应该指向了获取的”filter”的信息的指针。因此这两个if判断都为FALSE。5. 检查chain与相关options的搭配,target的合法等问题 整个检查都在if (command = CMD_APPEND)里面进行。 首先检查chain和options的匹配情况,这里chain=”INPUT”,对于本例中设置的规则,应该都没有问题。 然后是if (target & iptc_is_chain(jumpto, *handle)。其中target为”standard”(包含了ACCEPT, DROP, QUEUE,RETURN等目标)的结构体指针。(libiptc.c)。由于我们这里的jumpto为目标ACCEPT,而并非chain,所以该if为FALSE. 因此,程序真正执行的部分是e = generate_entry(&fw, iptables_matches, target-t);用来生成一个struct ipt_entry e。e中包括了struct ipt_entry,并利用最后一个元素unsigned char elems0申请了一块内存,该内存里首先是若干个match的结构体,然后是一个target结构体,因此该块内存的大小为n*match + target.6. 具体命令的执行 这部分也是do_command函数的最后。用一个swicth(command)来判断具体执行什么动作。我们这里command=CMD_APPEND,因此调用append_entry函数来将该条iptables规则加入进去。大致介绍一下append_entry函数的功能: 源码中具体对应的函数名为TC_APPEND_ENTRY()。该函数首先调用find_label找到整个规则中指定chain的struct chain_cache结构,然后做一下target的映射,我们这里是标准的target。真正执行添加规则的是insert_rules函数。该函数找到插入规则的entry点,并将该规则插入。调整后的所有的规则都保存在结构体指针handle之中。(三)、iptables规则的提交 do_command函数执行完毕,接着调用iptc_commit(&handle)将filter调整后的所有规则提交给内核。整个iptables的工作流程解析完毕。基本上iptables与内核的交互,都是使用get/setsockopt函数来实现的,用 setsockopt写入内核,getsockopt读内核。(get/setsockopt函数功能见socket函数总结)4、 iptables常用命令对一些出口参数的影响:执行命令出口参数及初值影响出口参数-Acommand(初始值为0)command = CMD_APPEND=0x0010u-Icommand(初始值为0)command = CMD_INSERT=0x0001u-Dcommand(初始值为0)command = CMD_DELETE=0x0002u-Rcommand(初始值为0)command =CMD_REPLACE=0x0008u-Pcommand(初始值为0)command =CMD_SET_POLICY=0x0400u-Fcommand(初始值为0)command =CMD_FLUSH=0x0040u-Lcommand(初始值为0)command =CMD_LIST=0x0020u-ooptions(初始化0)fw.ip.invflags(初始化为0)options|=OPT_VIANAMEOUT(0x00100u)fw.ip.invflags|=IPT_INV_VIA_OUT-ioptions(初始化0)fw.ip.invflags(初始化为0)options| = OPT_VIANAMEIN(0x00080u)fw.ip.invflags|=IPT_INV_VIA_IN-soptions |= OPT_SOURCE(0x00002u)fw.ip.invflags|=IPT_INV_SRCIP-doptions |= OPT_DESTINATION (0x00004u) fw.ip.invflags|=IPT_INV_DSTIP-poptions |= OPT_PROTOCOL(0x00008u)fw.ip.invflags|=IPT_INV_DSTIP-jptions |= OPT_JUMP(0x00010u)fw.ip.invflags|=0五、在核心处理函数do_command里一些重要参数的变化: do_command函数下重要的参数有: struct xtables_match *m;struct xtables_rule_match *matches = NULL;struct xtables_rule_match *matchp;struct xtables_target *target = NULL;struct xtables_target *t; 其中:结构体 struct xtable_match、struct xtable_target、struct xtable_rule_match均在 iptables /include /xtables.h.in下定义。对以上参数有影响的程序段分析: for (m = xtables_matches; m; m = m-next)m-mflags = 0; mflags: 一般用来记录命令中指定了匹配的哪些选项信息。命令行中指定到某一匹配时,对应该匹配选项的一些信息标志,例如iptables -A INPUT -p udp -sport 23 .会使mflags|=UDP_SRC_PORTS,这样当指定了两个-sport那么会依据if(mflags&UDP_SRC_PORTS) exit_error(.);来进行判断是否指定了两个相同的选项-sport(可参见extensions/libipt_udp.c中的parse()函数)在函数void (*final_check)(unsigned int flags);也引用到mflags。for (t = xtables_targets; t; t = t-next) t-tflags = 0;t-used = 0;used: 当通过find_target、find_match函数来加载xtables_target、xtables_match应用扩展模块时,用来记录对应模块是否正在被使用。应用层在向内核层加载规则时就是依据这个used来判断是否要加载对应的模块。在do_command函数开头为了防止两次调用到do_command函数,必须将xtables_match、xtables_target所指引的模块中的used清空。case j: set_option(&options, OPT_JUMP, &fw.ip.invflags, invert);jumpto = parse_target(optarg);/*jumpto=下一个命令字符 */* TRY_LOAD (may be chain name) */target = xtables_find_target(jumpto, XTF_TRY_LOAD);/* target-used=1*/ if (target) size_t size;size = IPT_ALIGN(sizeof(struct ipt_entry_target)+ target-size;target-t = xtables_calloc(1, size); /*给struct ipt_entry_target分配一个大小为size的动态存储空间 */target-t-u.target_size = size;strcpy(target-t-u.user.nam

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论