连接跟踪是很多网络服务和应用的基础。例如,kubernetes的service,ServiceMesh sidecar,4层负载均衡软件LVS/IPVS,容器网络,OpenvSwitch,OpenStack安全组等等都是依赖连接跟踪。
概念
顾名思义,连接跟踪就是跟踪或维护网络连接及其状态的。
![](https://img-blog.csdnimg.cn/img_convert/ff5d4b913e45312af1ed54bf427176d0.webp?x-oss-process=image/format,png)
机上连接跟踪示例
上图中,Linux主机的IP地址是10.1.1.2,包含3个连接:
1、10.1.1.2:55667 <-> 10.2.2.2.:80:本地发起的连接,用于访问外部HTTP/TCP服务。
2、10.3.3.3:23456 <-> 10.3.3.2.:21:外部连接访问该节点的FTP/TCP服务。
3、10.1.1.2:33987 <-> 10.4.4.4.:53:本地发起的连接,用于访问外部DNS/UDP服务。
Conntrack模块负责发现和记录这些连接及其状态,包括:
提取数据包的五元组,区分数据包和相关连接。
为所有连接维护一个“数据库”(连接跟踪表),存储连接的创建时间、发送的数据包、发送的字节信息等。
回收陈旧的连接信息(GC)。
为上层功能服务,例如NAT。
但是请注意,“连接跟踪”中的术语“连接”不同于我们常在TCP/IP栈中所指的“连接”概念。简而言之:
在TCP/IP协议栈中,“连接”是4层概念。TCP是一种面向连接的协议,所有的报文都需要得到确认(ACK),并且有重传机制。UDP是一种无连接协议,不需要确认(ACK),也不需要重传。
在连接跟踪中,五元组唯一地定义数据流,数据流表示连接。
后面我们将看到即使ICMP(3层协议)也有连接数据。但并不是所有的协议都有连接跟踪。
我们所说的“连接”,在大多数情况下是指后者,即“连接跟踪”上下文中的“连接”。
理论
有了上述概念,让我们来分析连接跟踪的基本理论。要跟踪一个节点上所有连接的状态,我们需要:
1、读取(或过滤)通过该节点的每个数据包,并分析数据包。
2、设置一个“数据库”记录这些连接的状态。
3、根据数据包提取信息,及时更新连接状态到数据库(连接跟踪表)。
例如:
1、当读取一个TCP SYC数据包时,我们将确认这是在尝试新的连接,我们需要创建一个新的连接跟踪记录。
2、当得到一个属于现有连接的数据包时,我们需要更新连接跟踪的统计信息,例如发送的字节数、发送的数据包数、超时值等。