追踪网络流量就这么简单 | 进阶篇 | conntrack

前面文章中,通过iptables LOG方式记录了凡事经过表链的数据包都进行追踪了,这样会发现日志量非常多不方便排查问题,于是我们又有了新的需求,如何针对指定的网络状态跟踪或过滤呢?

阅读本篇文章前,建议先浏览之前的iptables相关文章后, 理解会为更佳~

conntrack是个啥?

那么介绍下今天的主角,内核 Netfilter 框架conntrack状态机制,也可以称为它是一种连接跟踪机制。

conntrack连接跟踪,实际上是一个内核模块 nf_conntrack ,可以使用命令 lsmod | grep nf_conntrack 来检查内核模块是否加载。

在加载 nf_conntrack模块后,连接跟踪机制就开始工作,它会判断每个经过的数据包是否属于已有的连接,如果不属于任何已存在的连接,那么 nf_conntrack模块就会为其新建一个 conntrack 条目,如果连接已经存在,则更新对应 conntrack 条目的状态、老化时间等信息。

在iptables里,数据包在连接跟踪连接中有五种不同状态:

  • NEW**:**尝试建立一个新的连接。
  • ESTABLISHED**:**已经存在的连接。
  • RELATED**:**分配给一个正在发起新连接的数据包。当一个连接和某个已处于ESTABLISHED状态的连接有关系时,就被认为是RELATED的了。换句话说,一个连接要想是RELATED的,首先要有一个ESTABLISHED的连接。这个ESTABLISHED连接再产生一个主连接之外的连接,这 个新的连接就是RELATED的了,当然前提是conntrack模块要能理解RELATED。
  • INVALID**:**报文是无效的,例如它不符合TCP状态图。
  • UNTRACKED**:**一种特殊状态,可以由管理员分配,可以绕过对特定数据包的连接跟踪。

连接跟踪模块目前只支持以下六种协议TCPUDPICMPDCCPSCTPGRE

大家可以根据Netfilter框架数据流图加深理解,图中名为 conntrack 的方块则代表conntrack钩子函数。

除了本地产生的包由OUTPUT链处理外,所有连接跟踪都是在PREROUTING链里进行处理的,意思就是: iptables会在PREROUTING链里重新计算所有的状态。如果我们发送一个流的初始化包,状态就会在OUTPUT链里被设置为NEW,当我们收到回应的包时,状态就会在PREROUTING链里被设置为ESTABLISHED

如果第一个包不是本地产生的,那就会在PREROUTING链里被设置为NEW状态。综上,所有状态的改变和计算都是在nat表中的PREROUTING链和OUTPUT链里完成的。

好啦,我们已经把理论知识搞明白了,那就实战。不服就干!

conntrack工具使用

conntrack在用户态中也有一套命令程序,使用 conntrack 命令程序,需要安装conntrack-tools 安装包。

conntrack-tools包括:conntrack、conntrackd、nfct。

  • conntrack:从用户空间查看和管理内核的连接跟踪表
  • conntrackd:可以用在热备场景下在多台机器直接实时同步连接跟踪表。
  • nfct:目前只支持nfnetlink_cttimeout。从长远来看,希望通过提供类似于nftables的语法来替代conntrack。

下面使用 conntrack 命令跟踪服务端IP 172.27.247.29,端口是 80的网络连接请求。

我们可以使用如下参数来进行过滤

shell 复制代码
conntrack -E -d 172.27.247.29 -p tcp --dport 80

下面将conntrack所跟踪的日志,进行解析

图1

图2

conntrack命令支持多种参数,用于执行不同的操作:

  • -L, --list:列出连接跟踪表中的所有条目。
  • -G, --get:获取单个连接跟踪条目的信息。
  • -D, --delete:从连接跟踪表中删除条目。
  • -I, --create:创建一个新的连接跟踪条目。
  • -U, --update:更新已存在的连接跟踪条目。
  • -E, --event:监听连接跟踪事件。
  • -d, 目标IP。
  • -p, 协议。
  • --dport,目标端口。

连接状态,描述TCP连接的当前状态:

  • ESTABLISHED:已建立连接。
  • TIME_WAIT:等待足够的时间以确保远程TCP接收到连接终止请求的确认。
  • CLOSE_WAIT:CLOSE_WAIT状态表示对端(远程主机)已经关闭了连接的一半(发送了一个FIN包),并且本地端(你的计算机)已经接收到这个关闭请求,但是本地应用程序还没有关闭(或者说还没有调用close来关闭连接)。简单来说,CLOSE_WAIT状态意味着TCP连接在等待本地应用程序去关闭连接。
  • SYN_SENT:客户端已发送一个连接请求(SYN包)给服务器,并等待服务器的确认。这表示客户端已经开始了TCP三次握手过程。
  • SYN_RECV:服务器收到客户端的SYN包,并回应一个SYN+ACK包,等待客户端的确认。这个状态表示服务器端已经响应了连接请求,正在进行三次握手的第二步。
  • FIN_WAIT_1:当一方(通常是客户端)决定关闭连接,并发送一个FIN包给对方,等待对方的确认。这标志着连接关闭过程的开始。
  • FIN_WAIT_2:在发送FIN包并收到ACK包后,连接进入FIN_WAIT_2状态。在这个状态下,连接的关闭一方等待对方的FIN包。
  • CLOSE_WAIT:当一方收到另一方的FIN包,即对方请求关闭连接时,它会发送一个ACK包作为回应,并进入CLOSE_WAIT状态。在这个状态下,等待本地应用程序关闭连接。
  • CLOSING:在同时关闭的情况下,当双方几乎同时发送FIN包时,连接会进入CLOSING状态,表示双方都在等待对方的FIN包的确认。
  • LAST_ACK:当处于CLOSE_WAIT状态的一方发送FIN包,并等待对方的最终ACK包时,连接进入LAST_ACK状态。
  • TIME_WAIT:在收到对方的FIN包并发送ACK包后,连接进入TIME_WAIT状态。这个状态持续一段时间(2倍的MSL,最大报文生存时间),以确保对方收到了最终的ACK包。这也允许老的重复数据包在网络中消失。
  • CLOSED:连接完全关闭,两端都释放了连接的资源。

conntrack配合iptables使用

在iptables里,与连接跟踪是使用 --state匹配操作,我们能很容易地控制 "谁或什么能发起新的会话"。这样便让 iptables 成为了有状态的防火墙。

案例1:通过 conntrack中 NEW 状态来限制网络连接访问web服务

NEW 表示一个新的 TCP/UDP 连接的第一个数据包(如 TCP SYN 包),可预防CC攻击。

shell 复制代码
iptables -A INPUT -m state --state NEW -s 117.128.29.83 -p tcp --dport 80 -j DROP

案例2: 入栈目的为80端口的网络请求,跳过连接跟踪机制。

shell 复制代码
iptables -t raw -A PREROUTING -i eth0 -p tcp --dport 80 --syn -j NOTRACK

案例3: 对连接跟踪事件进行筛选,仅处理带有 ASSURED 标记或 DESTROY 事件的连接。

shell 复制代码
iptables -I PREROUTING -t raw -j CT --ctevents assured,destroy
  • assured: 稳定连接,通常表示双向流量已确认。
  • destroy: 连接被销毁(如超时、主动关闭)。

技术文章持续更新,请大家多多关注呀~~

搜索微信公众号,关注我【 帽儿山的枪手 】

相关推荐
Two_brushes.1 小时前
【Linux】线程机制深度实践:创建、等待、互斥与同步
linux·运维·服务器·多线程
设计师小聂!3 小时前
Linux系统中部署Redis详解
linux·运维·数据库·redis
kfepiza3 小时前
Debian-10编译安装Mysql-5.7.44 笔记250706
linux·数据库·笔记·mysql·debian·bash
xchenhao3 小时前
基于 Flutter 的开源文本 TTS 朗读器(支持 Windows/macOS/Android)
android·windows·flutter·macos·openai·tts·朗读器
努力做小白4 小时前
Linux驱动11 --- buildroot&杂项驱动开发方法
linux·运维·驱动开发·单片机·嵌入式硬件
哈哈浩丶5 小时前
Linux驱动开发1:设备驱动模块加载与卸载
linux·运维·驱动开发
Bulestar_xx5 小时前
20250711_Sudo 靶机复盘
linux·安全·web安全
一位搞嵌入式的 genius5 小时前
暑期自学嵌入式——Day01(C语言阶段)
linux·嵌入式c语言
yqcoder6 小时前
7. TCP 和 UDP 的区别
网络·网络协议·http