netfilter数据流图

这两天因为内部kubernetes的网络配置问题和同事交流了一下,由于内部使用了calico网络,在内部pod出网时有两种选择,使用nat或者不使用nat,为此还经历了一番讨论,突然发现自己对netfilter包括其相关的很多概念还是比较模糊,所以查了查资料,尝试深入了解一下。

netfilter

在网上找到了一张图,发现还是能比较清楚的描述整个netfilter架构的,来源来自http://xkr47.outerspace.dyndns.org,先把图贴出来:

netfilter packet flow

这张图更像是从iptables chain的角度去描述netfilter数据流,总的来说其实不太影响最终的理解,实际netfilter提供了NF_IP_PRE_ROUTINGNF_IP_LOCAL_IN
NF_IP_FORWARDNF_IP_LOCAL_OUTNF_IP_POST_ROUTING几个HOOK点,具体到图上:

- `PREROUTING`: 对应`NF_IP_PRE_ROUTING`,看名字就可以知道,该HOOK在收到数据包,进行路由判断之前触发;
- `INPUT`: 对应`NF_IP_LOCAL_IN`,当经过`PREROUTING`阶段,如果目的地址是本机,那么将触发`INPUT`,之后就可能被传给应用程序处理;
- `FORWARD`: 对应`NF_IP_FORWARD`,对应如果数据包在路由表中是需要转发到另一个网络接口的,那么将触发`FORWARD`;
- `POSTROUTING`: 对应`NF_IP_POST_ROUTING`,所有数据包在进行路由选择之后,在实际发送给网络接口之前,会触发`POSTROUTING`;
- `OUTPUT`: 对应`NF_IP_LOCAL_OUT`,对于所有本地生成的数据包,在路由选择之前会触发`OUTPUT`。

PS:根据文档描述,包括上图中的备注也说明了,在实际上,对于本地生成的数据包,是先进行过一次路由选择,拿到一些需要的信息(比如源IP和一些IP选项)后,再触发`OUTPUT`的。

实际上netfilter最重要的就是提供这些HOOK点,针对图上的这些HOOK点,可以方便的注册各种处理逻辑来实现对包的处理,像常用的LVS,也是利用了这一系列的HOOK,来实现负载均衡功能。

iptables

说完netfilter的基本信息,需要在具体说一下iptables的主要数据流,实际上iptables也是在netfilter上注册了一系列的HOOK,并将这些HOOK通过几个table来管理,同样是针对上面的图,从iptables table这个角度来看,
也可以很直观的看到iptables的所有表,到底都在netfilter的哪些阶段被注册了,在很的教程中,都喜欢以table维度来介绍数据流,个人觉得是没有从hook这个维度看起来清晰的。

需要说明的是,因为NAT包含SNAT(修改源地址)和DNAT(修改目的地址),而这两种NAT发生作用的时间也是不一样的,在图上可以看到,DNAT发生在NF_IP_PRE_ROUTINGNF_IP_LOCAL_OUT阶段,
而SNAT发生在NF_IP_POST_ROUTING阶段,其实也很好理解,仔细想想就可以知道为什么是这样了。

不过对于上图里,和实际不对应的地方,iptables的SNAT其实也是可以在INPUT里实现的,而图上并没有画出来。

Connection Tracking

最后再说一下Connection Tracking(连接跟踪),连接跟踪也是在netfilter上实现的,可以给iptables提供在连接的各个阶段对数据包进行操作的能力,也就是可以提供一个跟状态挂钩的服务(毕竟TCP链接是有状态的)。
数据包进入网络栈后,只经过一些基本的检查,以及raw表操作之后,很快就会被连接追踪给追踪了,根据收到的包,可以根据实际情况针对性的修改追踪中的各种链接状态,当然连接追踪也是可以跳过的,只需要在raw表中操作数据包将数据包添加NOTRACK标记,那么连接跟踪将会不处理数据包和其连接。

整体内容不是很多,也没有非常深入去了解所有的机制,特别是代码方面,但是一张图还是能提供非常多的信息,特别是对整体的架构了解帮助很大,具体到更多的应用,就额外再进行记录吧~

参考:

  1. https://www.digitalocean.com/community/tutorials/a-deep-dive-into-iptables-and-netfilter-architecture
  2. https://www.netfilter.org/documentation/HOWTO//netfilter-hacking-HOWTO-3.html