ip_conntrack内置于Linux协议栈的Netfilter框架,其实现比较复杂,然而其逻辑却很简单。ip_conntrack追踪每一个流,一个流由五元组来定义,五元组这个网络基本术语就不解释了。因此ip_conntrack必然能对“哪里是一个流的开始”做出判断,虽然这种判断不总是精确的,详见《
linux之ip_conntrack容易混淆的问题点滴》。
ip_conntrack会为每一个到来的包绑定一个流,如果找不到遵照五元组可以绑定的流,则会认为这是个流头,那么就会根据该包所携带的五元组信息创建一个新的流,整个场景可以由下面的流程图展示出来:
有了一个基本的认识,再遇到问题的时候就可以用知道的知识来解决了,比如《 iptables和策略路由实现VPN感兴趣流的截获》一文中的问题,要截获一个特定的流,然而由于拓扑复杂,还要支持任意点到任意点的互通,仅仅根据IP层的信息就很难分辨出一个双向的数据流是由哪里发起的,因此就必然要使用ip_conntrack。ip_conntrack有一个match,那就是ctdir,它可以分辨出方向信息,然而它是如何做到的呢?通过上图就可以看出,ip_conntrack保存了一个哈希表,其中的表项内容就是一个五元组,然而两个方向的五元组信息是分开存放的,这就便于根据单独的五元组进行查找,虽然它们分开存放,属于同一个流的双向两个五元组又由同一个nf_conn结构(不同内核版本名字可能不同)统一了起来。如此一来就很容易辨别方向了。流量截获的mangle规则如下图所示:
以下是策略路由规则:
上述的流量截获方法其实就是使用ip_conntrack机制为IP数据报增加了方向的特征,然后你可以很方便的根据方向信息区分不同的流量,最终使用策略路由将数据包导向特定的目的地。
ip_conntrack虽然功能强大,然而却也带来不少争议,幸运的是关于这些争议的不好的方面都是有解决办法的。
ip_conntrack会为每一个到来的包绑定一个流,如果找不到遵照五元组可以绑定的流,则会认为这是个流头,那么就会根据该包所携带的五元组信息创建一个新的流,整个场景可以由下面的流程图展示出来:
有了一个基本的认识,再遇到问题的时候就可以用知道的知识来解决了,比如《 iptables和策略路由实现VPN感兴趣流的截获》一文中的问题,要截获一个特定的流,然而由于拓扑复杂,还要支持任意点到任意点的互通,仅仅根据IP层的信息就很难分辨出一个双向的数据流是由哪里发起的,因此就必然要使用ip_conntrack。ip_conntrack有一个match,那就是ctdir,它可以分辨出方向信息,然而它是如何做到的呢?通过上图就可以看出,ip_conntrack保存了一个哈希表,其中的表项内容就是一个五元组,然而两个方向的五元组信息是分开存放的,这就便于根据单独的五元组进行查找,虽然它们分开存放,属于同一个流的双向两个五元组又由同一个nf_conn结构(不同内核版本名字可能不同)统一了起来。如此一来就很容易辨别方向了。流量截获的mangle规则如下图所示:
以下是策略路由规则:
上述的流量截获方法其实就是使用ip_conntrack机制为IP数据报增加了方向的特征,然后你可以很方便的根据方向信息区分不同的流量,最终使用策略路由将数据包导向特定的目的地。
ip_conntrack虽然功能强大,然而却也带来不少争议,幸运的是关于这些争议的不好的方面都是有解决办法的。