简单介绍
最早的内核包过滤机制是ipfwadm。后来是ipchains。再后来就是iptables/netfilter了。
再往后,也就是如今是nftables。
只是nftables与iptables还处于争雄阶段,谁能胜出眼下还没有定论。可是他们都属于netfilter项目的子成员。
钩子
netfilter基于钩子,在内核网络协议栈的几个固定的位置由netfilter的钩子。
我们知道数据包有两种流向,一种是给本机的:驱动接收——》路由表——》本机协议栈——》驱动发送。一种是要转发给别人的:驱动接收——》路由表——》转发——》驱动发送。
针对这几个关键位置,netfilter定义了几个钩子:NF_IP_PRE_ROUTING是在查路由表之前,NF_IP_LOCAL_IN实在查完路由表决定发送本机之后,NF_IP_FORWARD实在查完路由表决定转发的时候。NF_IP_POST_ROUTING是要交给驱动发送之前。NF_IP_LOCAL_OUT是本机产生的数据交给驱动发送之前。通过在这几个钩子位置注冊函数。截断数据包的流动。能够完毕数据包的过滤和转换功能。要知道的是,转发功能一般仅仅在路由器上打开。一般的PC假设发现不是自己的数据包就会直接选择丢弃。所以。普通PC能够使用的钩子有NF_IP_PRE_ROUTING、NF_IP_LOCAL_IN、NF_IP_LOCAL_OUT、NF_IP_POST_ROUTING四个。
能够看到都是在IP层的钩子,然而,这些钩子可不仅仅仅能够处理IP层的数据,由于在IP层能够拿到完整的数据包,所以你想处理哪一层都是能够的。
iptables不是注冊在钩子函数上,可是位置是一致的。是netfilter框架下的一个附属的功能。由table、chain、rule组成。
netfilter提供了几个重要的功能,方便不管是iptables还是nftables使用。caching功能能够有一个缓存,通过查询数据包的某个位置能够决定该数据包根本不会经过后面的过滤规则。
用户空间使用iptables
table、chain和rule
chain和rule是iptables自创的概念,我们知道在钩子函数的地方能够运行指定的函数调用。
iptables系统就默认实现了几个调用,而且用统一的数据结构来组织这个调用的形式。这个组织结构就是table、chain和rule。
在不论什么一个hook点,都能够定义多个table,一个table有多个chain。每一个chain中能够定义多个rule。要记住的是table和chain仅仅是容器,里面的rule才是真正发挥作用的规则。
理论上我们能够在不论什么一个hook点做过滤、nat、改动数据包等全部操作。可是iptables为了统一架构起见。在各个hook点定义了顺序的几个table,每一个table用来完毕一类的工作。
提前定义的table包含:filter、nat和mangle。这每一个table表示的是功能,并非表示位置,一个table内部有多个chain。当中每一个chain位于特定的位置。
下图是一个内部已经定义的table、chain关系图表:
https://upload.wikimedia.org/wikipedia/commons/3/37/Netfilter-packet-flow.svg
FILTER: PREROUTING, FORWARD, POSTROUTING
NAT: PREROUTING, INPUT, OUTPUT, POSTROUTING
MANGLE: PREROUTING, INPUT, FORWARD, OUTPUT,POSTROUTING
能够看到,提前定义的3个表表示3种不同的功能。每一个表都在一些hook点定义了一组chain。如此,当一个用户想要在某一个hook点做某一件事情。就能够定位到table(功能)——》chain(位置)——rule(行为)来完毕数据包操作。
每一条rule的格式都是同样的,包含源IP地址、目的IP地址、上层协议、接口、操作(target)。可是并非每一个域对于每一个chain都是可用的。比如在INPUT的地方匹配输出接口就是永远匹配不到的。所以有效的rule在不同的chain上是不同的。
iptables是个可扩展的软件,其对TCP、UDP等经常使用协议的支持都是通过扩展,iptables本体仅仅支持到ip层,你仅仅要使用相应的选项就会自己主动的使用扩展。另一些不是协议的扩展,这些扩展一般通过iptables –m 调用,比如iptables –m mac能够用来匹配mac地址。-m limit能够用来限制每秒钟匹配的数目,超过的就放行。这些扩展包含:
l xt_mac.ko:匹配mac地址
l xt_limit.ko:限制每秒钟匹配的数目,超过的就放行
l xt_owner.ko:用来匹配某个某个进程或用户创建的数据包
l xt_state.ko:用来匹配处于某个连接状态的数据包(比如NEW、ESTABLLISHED、RELATED)
l xt_pkttype.ko:用来依据多播、广播还是单播来匹配包
l xt_quota.ko:能够为一个rule设置quota。当quota达到后。改rule失效
l xt_recent.ko:同意你设置一个IP列表。兴许的IP列表的用户都不生效
l xt_string.ko:同意你匹配数据包中的一个字符串
l xt_time.ko:同意你依据数据包的到达和离去时间进行匹配
l xt_u32.ko:通过匹配检查数据包的某4位是否与要求的一致来进行操作
还有非常多target的扩展和conntrack的扩展、ipv6的扩展。能够依据应用的类型进行匹配,能够改动ttl、TOS等数据位。基本能用得上的功能都有相应的扩展。
操作(target)也是能够扩展的。常见的默认的操作有ACCEPT和DROP。扩展的还有LOG、REJECT等。用户还能够自己实现。还有两种默认是QUEUE和RETURN,RETURN实现了各个规则之间的函数式调用。QUEUE则实现了数据包的排队。这些操作也都相应着详细的模块:nft_queue.ko、nft_reject.ko、xt_LOG.ko、nft_log.ko等。
bpf
用户空间不止能够加入规则,还能够加入代码。
这是通过xt_bpf模块实现的。iptables –m bpf –bytecode 后面跟详细的code就好了,从汇编编译成code的程序再linux内核的tool/net下有。
内核模块使用netfilter
不可是用户空间能够给iptables加入规则,内核模块加入规则的能力更强大。由于其具备编码能力,所以不仅仅是能够丢弃一个数据包,还能够返回NF_STOLEN,这样这个数据包对于协议栈来说将会停止向上发送。而这个模块将会处理这个数据包的兴许流程。
应该注意的是。netfilter这个名字指的是内核过滤数据包这个架构,而iptables则是table、chain、rule这套设计。内核里面一般直接使用netfilter的钩子。而不使用iptables的规则。