netfilter的架构就是在整个网络流程的若干位置放置了一些检测点(HOOK ),而在每个检测点上上登记了一些处理函数进行处理(如包过滤,NAT等,甚至可以是用户自定义的功能)。

  常见问题

  这一小节覆盖了常见的netfilter(和非netfilter)相关的问题,我们在邮件列表中经常看到它们。

  1、我从哪里可以获取netfilter/iptables?

  Netfilter和iptables集成在Linux2.4.x内核系列中了,请从http://www.kernel.org/或它的镜像站点获取一个最近的内核。用户空间工具iptables可以在netfilter的主页及它的镜像站点http://www.netfilter.org/, http://www.iptables.org/, http://netfilter.samba.org/, http://netfilter.gnumonks.org/ 或 http://netfilter.filewatcher.org/.上找到。

  2、Linux2.2有netfilter的backport吗?

  没有,至少目前还没有,但是如果有人想开发它,也应该不会太难,因为对网络堆栈有干净的接口,这一块有任何动静请通知我一声。

  3、有ICQ conntrack/NAT帮助模块吗?

  如果你在一个Linux2.2盒子上使用伪装技术,你总会用ip_masq_icq module来直接获取客户端到客户端的ICQ操作。没有人为netfilter重新实现过这个模块,因为ICQ协议太丑陋了:),但是我猜测它需要一点时间,除非有一个现成的可用。

  Rusty曾经指出要为协议开发一个模块,至少要有一个开放的客户端和开放的服务器被集成到主netfilter发布中,对于ICQ而言,它只有开放的客户端,因此它不符合这个标准。(开放即自由,而不是免费的啤酒)

  4、ip_masq_vdolive / ip_masq_quake / ...等模块何去何从?

  它们中的一部分是不需要的,另一部分还没有集成到netfilter,Netfilter可以跟踪所有连接甚至是UDP,并且策略尽可能少的干扰数据包。

  5、patch-o-matic是什么?我如何使用它?

  2.4.x内核是一个稳定版本,因此我们不能提交我们目前的开发版本到主流内核,我们所有的代码首先要在netfilter patch-o-matic中测试,如果你想使用netfilter的边缘功能,你不得不从patch-o-matic应用一个或更多的补丁,你可以在最新的iptables的包中找到patch-o-matic(或从CVS源代码找),请在netfilter主页去下载。

  patch-o-matic现在有3个不同的选项:

  make pending-patches

  make most-of-pom

  make patch-o-matic

  第一个选项只是确保所有重要的bug修复补丁(它已经被提交给内核维护者了)应用到你的内核;第二个选项提醒你所有新的特征在没有冲突的情况将被应用;第三个选项是为真正的专家准备的,可以看到所有的补丁—但是要小心,它们可能互相冲突。

  patch-o-matic有一个整洁的用户接口,只需要输入

  make most-of-pom (或 pending-patches或 patch-o-matic,请看上面)

  或者,如果你的内核树不在/usr/src/linux,使用

  make KERNEL_DIR={your-kernel-dir} most-of-pom

  在iptables包的顶级目录,patch-o-matic检查每一个补丁是否可以应用到你已经安装的内核代码,如果一个补丁可以应用,你将看到一个关于该补丁的更多信息提示,应用这个补丁,跳到下一个... ...

  关于patch-o-matic更多的信息,请查看netfilter的扩展HOWTO(http://www.netfilter.org/documentation/index.html#HOWTO)。

  6、我在哪里可以找到ipnatctl以及关于它的更多信息?

  ipnatctl用于从用户空间设置你的NAT规则,它是一个非常早的2.3.x内核时期的开发版本,现在不再需要它了,因此不再有效,它的所有功能现在都集成到iptables身上了,请在netfilter主页上查看NAT HOWTO。

  7、iptables/ip6tables能做IPv6 NAT吗?

  不行,NAT核心不支持任何类型的IPv6/IPv4 NAT。

  8、有计划支持SIP吗?

  SIP(会话初始化协议)是相当复杂的,特别是它横跨防火墙和NAT设备时,最初的计划是在FCP(防火墙控制协议)上的一个代理通讯。现在IETF MIDCOM工作组已经成立了,他们也想使用SIP。

  netfilter/iptables团队目前没有资源实施SIP conntrack/NAT支持,但是我们对发起者是打开门欢迎的。

  9、netfilter/iptables支持failover/HA?

  答案是‘支持’和‘不支持’。

  如果你正在考虑一个完整的失效恢复,那么多有的状态信息需要保留:不现实。在多个节点之间同步状态是一个非常困难的过程,Harald(netfilter团队核心成员)已经发布了一个关于这个的报告,但是没有发现任何对开发有帮助的资助。同时,你可以尝试使用我的‘连接捡起’特性,它【在发生故障后】尝试捡起已经建立好的连接:可能需要足够充分的条件。

  如果你用了NAT并且想保留你的NAT映射:不支持。

  如果你使用包过滤:支持。

建立过程中的问题

  1、我用内核>=2.4.0-test4时不能编译iptables-1.1

  这是一个已知的问题,检查补丁应用的机制被中断,尝试使用make build替代make。更好的方法:升级到iptables-1.1.2或更高版本。

  2、我用最近的内核(>=2.3.99-pre8)不能编译iptables1.1.0

  iptables内部结构已经改变了,请升级到iptables>=1.1.1。

  3、一些来自iptables>=1.2.1a的patch-o-matic补丁不能与>=2.4.4内核一起工作

  请使用一个最近的iptables发布。

  4、ipt_BALANCE, ip_nat_ftp, ip_nat_irc, ipt_SAME, ipt_NETMAP不能编译

  最大的可能是你正在经历一个叫做ip_nat_setup_info的函数编译问题。

  如果你使用是iptables<=1.2.2,你需要应用`dropped-table' 和 `ftp-fixes'补丁。

  如果你使用的是iptables>1.2.2或最近的CVS版本,你不能应用`dropped-table'补丁,因为它与BALANCE, NETMAP, irc-nat, SAME and talk-nat不兼容。

  5、我正在使用Alan Cox的2.4.x-acXX系列内核,我遇到问题了

  netfilter核心团队都是基于Linus的内核树进行开发的,因此使用-ac系列你自己承担风险。

  6、错误:Invalid option KERNEL_DIR=/usr/src/linux-2.4.19

  我打赌你肯定尝试过运行类似下面这样的命令

  # ./runme pending KERNEL_DIR=/usr/src/linux-2.4.19

  但是bash/sh不像make,变量不能作为一个参数,在你运行runme脚本前需要设置变量:

  # KERNEL_DIR=/usr/src/linux-2.4.19 ./runme pending

  运行中问题

  1、NAT:X dropping untracked packet Y Z aaa.aaa.aaa.aaa -> 224.bbb.bbb.bbb

  这个消息是由NAT代码打印出来的,因为多播包命中了NAT表,连接跟踪不能立刻控制多播包,在你对多播没有主意的时候,或不需要它的时候,使用:

  iptables -t mangle -I PREROUTING -j DROP -d 224.0.0.0/8

  2、NAT: X dropping untracked packet Y Z aaa.aaa.aaa.aaa -> bbb.bbb.bbb.bbb

  我的系统日志或我的终端显示下面的消息:

  NAT: X dropping untracked packet Y Z aaa.aaa.aaa.aaa -> bbb.bbb.bbb.bbb

  这个消息由NAT代码打印的,它丢掉了数据包,因为为了做NAT它需要有效的连接跟踪信息,这个消息为所有连接跟踪信息无效的数据包打印的。

  可能的原因是:

  达到了连接跟踪数据库条目的最大限制

  不能确定反向数组(多播,广播)

  kmem_cache_alloc失效(内存泄露)

  响应未经认可的连接

  多播数据包(请看前面的问题)

  icmp数据包太短了

  icmp变成碎片了

  icmp校验和错误

  如果你想得到这些包的更详细的日志信息(如:如果你怀疑它是远程探测/扫描数据包),使用下面的命令:

  iptables -t mangle -A PREROUTING -j LOG -m state --state INVALID

  是的,你不得不将这个规则放到mangle表中,因为数据包在抵达过滤表之前已经被NAT代码给丢掉了。

  3、ip_conntrack: max number of expected connections N of M reached for aaa.aaa.aaa.aaa -> bbb.bbb.bbb.bbb

  我的系统日志或终端有规则地显示下面的信息:

  ip_conntrack: max number of expected connections N of M reached for aaa.aaa.aaa.aaa -> bbb.bbb.bbb.bbb

  这是正常的不用担心,特别如果N和M是1,并且消息紧跟在reusing后,在linux内核特殊版本(2.4.19=

  内核版本升级后(>=2.4.21-pre4)这个消息就不再出现了,如果你仍然收到与这个类似的消息,联系http://lists.netfilter.org/mailman/listinfo/netfilter-devel邮件列表。

   4、我不能与Linux bridging代码一起使用netfilter

  你想建立一个完全透明的防火墙吗?好注意!如果是2.4.16内核,你仍然需要给你的内核打一个额外补丁。可以在http://bridge.sourceforge.net/找到。

  5、IRC模块不能控制DCC恢复

  这只有一半是事实,只有NAT模块不能控制它们,如果你在防火墙中不用NAT功能,它将工作得很好,等待补丁。

  6、SNAT如何与多地址一起工作的?

  Netfilter尝试尽可能少地产生破坏,因此,如果我们有一台刚刚重启了的机器,有一些在SNAT盒子后面的人用本地端口1234打开一个连接,netfilter盒子仅仅破坏ip地址保留相同的端口。

  一旦另外的人用相同的端口打开了另一个连接,如果它是一个单ip SNAT的话,netfilter将破坏ip和端口,但是如果有更多ip的话,它将只破坏ip部分。

  7、ip_conntrack: maximum limit of XXX entries exceeded

  如果你在系统日志中注意到有这个的消息,它看起来好像是你环境中的连接跟踪数据库没有足够的条目了,连接跟踪默认处理固定数量的并发连接,这个数量依赖于系统最大内存大小(64MB:4096;128M:8192;... ...)

  你可以轻易地增加这个最大连接跟踪数量,但是小心每个跟踪的连接要消耗大约350字节的非交换空间的内核内存。

  要提升这个限制到如8192,输入:

  echo "8192" > /proc/sys/net/ipv4/ip_conntrack_max

  为了优化性能,请同时提高哈希存储的数量,通过使用ip_conntrack.o模块hashsize模块载入时参数,请注意由于当前的哈希算法的特性使然,一个相同的哈希数量是一个坏的选择。

  例子(用1023个存储)

  modprobe ip_conntrack hashsize=1023

  8、我如何列出所有跟踪的/伪装的连接,与在2.2.x中ipchains -L -M类似吗?

  在proc文件系统中有一个文件,它叫做/proc/net/ip_conntrack,你可以用下面的命令查看这个文件的内容:

  cat /proc/net/ip_conntrack

  9、我如何列出所有有效的ip表?

  用下面的命令列出所有有效的ip表

  cat /proc/net/ip_tables_names

  10、从iptables-1.2发现iptables-save / iptables-restore失效

  已知的问题,请升级到最近的CVS版本或使用即将发布的iptables>=1.2.1

  11、iptables –L显示规则用了很长的时间

  这是因为iptables给每个ip地址做了一次DNS查询,因为每个规则至少有2个地址,那么每个规则至少做2此DNS查询。

  12、我如何阻止日志显示到我的终端?

  你需要适当地配置你的syslogd和/或klogd:程序核心日志的优先级是warning(4),查看syslogd.conf帮助页面了解更多关于优先级的信息。

  默认情况下,所有内核消息的优先级超过了debug(7)都会发送到终端,如果你将其提升到4,在终端上将看不到日志消息。

  小心这也可能会抑制其他重要的消息显示在终端上(不仅影响syslog)。

  13、我如何用squid和iptables建立一个透明的代理?

  首先,你需要一套合适的DNAT或REDIRECT规则,仅当squid运行在NAT盒子模式时使用REDIRECT,例如:

  iptables -t nat -A PREROUTING -p tcp --dport 80 -j DNAT --to 192.168.22.33:3128

  然后,你要对squid做适当的配置,我们在这里只能给出一个简单的注解,请参考squid的文档获取更详细的内容,squid2.3的配置文件squid.conf需要下面这些条目:

  http_port 3128

  httpd_accel_host virtual

  httpd_accel_port 80

  httpd_accel_with_proxy on

  httpd_accel_uses_host_header on

  squid2.4需要再添加一行:

  httpd_accel_single_host off

  

14、我如何使用LOG target/我能记录日志和删除日志吗?

  LOG target我们叫做非终端的目标,如:它不终止数据包规则的遍历。如果你使用了LOG target,数据包将被记录,规则遍历一个接一个地进行。

  那么在同一时间我如何记录日志和删除日志呢?没有比这更容易的了,创建一个自定义链表,包括下面2个规则:

  iptables -N logdrop

  iptables -A logdrop -j LOG

  iptables -A logdrop -j DROP

  现在每当你想记录和删除一个数据包时,你可以使用‘-j logdrop’来完成了。

  15、我如何用netfilter阻止蠕虫XYZ?

  简单地说你不能用netfilter正确地阻止。大多数蠕虫使用一个合法的高级协议(如HTTP,SMTP—如用VB脚本附加一个email,或者寄生在后台进程的病毒攻击代码控制了协议),高级协议意味着高于TCP/IP,因为iptables无法理解这些高级协议,所以它几乎不能过滤出任何内容,因此,你需要的是应用程序过滤代理。

  请不要从patch-o-matic使用字符串匹配替代应用程序代理过滤,它任何时候都能战胜不完整的数据包(如一个HTTP请求被分成2个TCP数据包),通过IDS逃避技术等,你会收到警告信息,字符串匹配是有用的但是目的各不相同。

  16、内核日志:Out of window data xxx

  你从patch-o-matic使用了tcp-window-tracking补丁,它的代码保持跟踪可接受的允许TCP数据流按照数据包的序列/应答号、分段大小等数据包,当它检查一个不可接受的数据包时(窗口之外),它将其标记为INVALID并打印出上面的消息。

  新版本的数据包日志什么失败条件才会正确地记录:

  ACK在较低的界限之下(可能过分延迟的ACK)

  ACK在较高的界限之上(ACK数据还没有被看到)

  SEQ在较低的界限之下(转发已经ACK的数据)

  SEQ在较高的界限之上(超过了窗口的接收条件)

  同时,在新版本中,日志能能通过sysctl完全被抑制

  echo 0 > /proc/sys/net/ipv4/netfilter/ip_ct_tcp_log_out_of_window

  17、为什么连接跟踪系统跟踪无应答的连接非常容易超时?

  首先,检查你是否在使用2.4.20内核,如果是,请立即应用https://bugzilla.netfilter.org/cgi-bin/bugzilla/showattachment.cgi?attach_id=8这个补丁!2.4.20内核有一个已经确认的bug引起大量伪造的UNREPLIED连接跟踪条目(查看https://bugzilla.netfilter.org/cgi-bin/bugzilla/show_bug.cgi?id=56)

  因此你看/proc/net/ip_conntrack时就会发现UNREPLIED条目有一个非常高的计时器(可能超过5天),你可能会感到非常奇怪,为什么我们要浪费连接跟踪条目在UNREPLIED条目(很明显,它没有连接)上呢?

  答案很简单:UNREPLIED条目是临时条目,如:一旦我们的连接跟踪条目装满时(达到/proc/sys/net/ipv4/ip_conntrack_max定义的数量时),我们将删除旧的UNREPLIED条目。换句话说:用空条目进行替换,我们只保留真实有用的条目。

  18、为什么不能执行iptables –c(--check)?

  首先是我们懒惰:),一旦你启动了有状态的防火墙要执行一个检查选项几乎是不可能的,传统的无状态的防火墙仅依赖当前数据包的头来进行判断,但是使用连接跟踪后(-m state规则),过滤结果的判断依赖于数据包头+有效负载,也包括这个连接里面前面的数据包。

  19、为什么我在PREROUTING链表中不能使用REJECT target?

  REJECT target是为过滤器准备的,过滤表已经有INPUT/OUPUT/FORWARD链表了,REJECT target只能用在这些链表中(以及子链表)。

  Netfilter用户在nat或mangle表中不做包过滤。

  20、在内核升级后(nat表)报'iptables: Invalid argument'

  你只升级了你的内核,没有对命令进行修改(特别是nat表),你经历的可能象下面这样:

  # iptables -A POSTROUTING -t nat -o ppp0 -j MASQUERADE

  iptables: Invalid argument

  这会在内核和用户空间之间的结构大小发生变化是发生,你需要重新编译iptables用户空间程序,使用包括你新内核的文件进行编译,如果你已经应用了一些只针对旧或新内核的补丁也会发生,使用kernel.org上的内核一般不会发生,如果发生了,请到netfilter-devel邮件列表寻求支持。

关于netfilter开发的问题

  1、我不知道如何从用户空间使用QUEUE target

  一个叫做libipq的库被提供用于用户空间数据包处理,请查看它的帮助文档获取更多的信息,你需要编译和安装iptables开发组件:

  make install-devel

  然后查看libipq(3)【译者注:man libipq 3】

  你也可能对Perl绑定libipq有兴趣,Perlipq在http://www.intercode.com.au/jmorris/perlipq/,绑定它自己是使用libipq的一个例子。

  其他代码例子包括:

  来自netfilter CVS的testsuite/tools/intercept.c

  ipqmpd(查看http://www.gnumonks.org/projects/)

  nfqtest,netfilter-tools的一部分(查看http://www.gnumonks.org/projects/)

  Jerome Etienne的WAN模拟器(查看http://www.off.net/~jme/)

  2、我的libipq应用程序报"Failed to received netlink message: No buffer space available"

  这意味着内核方Netlink套接字缓冲区超出了空间范围,用户空间应用程序不能控制从内核出来的大量数据。

  增大那些内核缓冲区让我不再遇到这个问题是可能的吗?

  是的,这些标准的Netlink套接字,你可以通过/proc/sys/net/core,sysctl或在描述符文件上使用SO_RCVBUF选项来调整它们的接收缓冲区大小。

  你还可以尝试确保你的应用程序尽可能快地读取任何接收到的数据,如果你不需要完整的数据包,尝试拷贝少量的数据到用户空间(查看ipq_set_mode(3))

  3、我想贡献一些代码,但是我还不知道该怎么做

  netfilter核心团队维护了一个TODO列表,它里面列出了所有想要的修改/新特征,你看通过匿名CVS检索这个列表,具体指令在netfilter的主页上,你还可以用CVSweb去http://cvs.netfilter.org/cgi-bin/cvsweb/netfilter/TODO/看看。

  4、我已经修复了一个bug或编写了一个扩展,我如何提交它?

  如果你想发布它,请将其发送到netfilter-devel邮件列表,订阅说明在http://lists.netfilter.org/mailman/listinfo/netfilter-devel/。

  正确的发送一个补丁的方法如下:

  邮件主题以[PATCH]开头

  直接包括在消息的主体中,不是MIME`d

  一个cvs-checkin/Changelog条目

  diff –u old new表格,来自root目录外部(如当进入未解压的目录时用-p1)

  如果你编写了一个新的扩展,或给一个旧的扩展增加了一些新的选项,同时更新netfilter-extension-HOWTO将新的扩展/功能描述包括进来是一个很不错的主意,另外,它将引出更多用户使用你的扩展,你将会得到更多的反馈。

  5、提供了增加/移除规则的c/c++ API吗?

  不幸的是还没有。

  你或许会想libiptc如何?已经在邮件列表中多次指出,libiptc从来就不是被作为一个公共接口使用的,我们不能保证一个稳定的接口,它已经计划在下一个Linux包过滤器中被移除出去,libiptc是太底层的东西。

  我们已经注意到缺少一个最基本的API,我们已经开始在这方面努力改进了,到那时,要么使用system()或打开一个管道进入iptables-restore标准输入,今后将给你提供一套性能更好的方法。