Linux中的contrack命令深入解析

在Linux网络管理和监控领域,conntrack命令是一个强大的工具,它提供了对netfilter连接跟踪系统的直接访问。

1. 简介

conntrack命令源于Linux的netfilter项目,这是一个内置于Linux内核中的网络包处理模块。Netfilter支持各种网络相关任务,如包过滤(防火墙)、网络地址转换(NAT)和连接跟踪。conntrack工具最初设计的目的是为了管理和监视netfilter的连接跟踪系统,这个系统记录了所有经过防火墙的网络连接的状态信息。

什么是连接追踪(Connection Tracking)?

连接追踪是网络防火墙功能中的一部分,用于记录网络连接的状态。它帮助防火墙做出智能决策,比如允许或拒绝特定连接。连接追踪支持多种协议,包括 TCP、UDP、ICMP 等。

底层原理

conntrack工具的底层原理基于netfilter的连接跟踪表,该表位于内核空间。每当网络包经过netfilter时,连接跟踪系统会检查包的信息,如源IP地址、目的IP地址、传输层协议(TCP/UDP)、端口等,并据此更新内部的连接跟踪表。这个表包含了所有活跃连接的状态信息,例如是否已建立连接、连接是否已关闭等。

安装 conntrack

在大多数 Linux 发行版中,conntrack 工具位于 conntrack-tools 包中。可以使用以下命令进行安装:

# Ubuntu/Debian
sudo apt-get install conntrack

# CentOS/RHEL
sudo yum install conntrack

2. 命令参数及结果解读

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

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

当你运行conntrack -L时,会看到类似以下的输出:

tcp 6 86387 ESTABLISHED src=127.0.0.1 dst=127.0.0.1 sport=55018 dport=2379 src=127.0.0.1 dst=127.0.0.1 sport=2379 dport=55018 [ASSURED] mark=0 use=1
udp 17 26 src=192.168.0.51 dst=192.168.0.1 sport=53452 dport=53 src=192.168.0.1 dst=192.168.0.51 sport=53 dport=53452 mark=0 use=1

每个字段的含义如下📝:

  1. 协议:表示连接使用的协议,如tcpudp等。
  2. 协议号:表示连接使用的协议号,如6代表tcp连接、17代表udp连接等。
  3. TCP状态计数器,可以理解为超时时间(Timeout):表示连接条目在连接跟踪表中保持的剩余时间(秒)。当这个时间到达0时,条目将被自动从跟踪表中移除。
    • 对于TCP连接,该数字表示连接跟踪条目在内核连接跟踪表中的剩余时间。这个计时器的值会根据连接的状态(如ESTABLISHED、TIME_WAIT等)和配置的超时设置变化。计时器的值为零时,连接跟踪条目会从表中删除。
    • 对于非TCP连接(如UDP),因为UDP是无连接的,所以这个计数器代表连接跟踪条目在没有任何新的数据包更新的情况下,还可以在连接跟踪表中存活多长时间。
  4. 连接状态:描述TCP连接的当前状态。
    • ESTABLISHED:已建立连接
    • TIME_WAIT:等待足够的时间以确保远程TCP接收到连接终止请求的确认)
    • CLOSE_WAIT:CLOSE_WAIT状态表示对端(远程主机)已经关闭了连接的一半(发送了一个FIN包),并且本地端(你的计算机)已经接收到这个关闭请求,但是本地应用程序还没有关闭(或者说还没有调用close来关闭连接)。简单来说,CLOSE_WAIT状态意味着TCP连接在等待本地应用程序去关闭连接。
    • SYN_SENT:客户端已发送一个连接请求(SYN包)给服务器,并等待服务器的确认。这表示客户端已经开始了TCP三次握手过程
    • SYN_RECE:服务器收到客户端的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:连接完全关闭,两端都释放了连接的资源。
  5. 源地址(src)、目的地址(dst):发送数据包的主机的IP地址。src=源IP dst=目的IP:表示数据包的源和目的IP地址。
  6. 源端口(sport)、目的端口(dport):发送数据包的主机的端口号。sport=源端口 dport=目的端口:表示数据包的源和目的端口号。
  7. [UNREPLIED] / [ASSURED]
    • [UNREPLIED]:表示从源到目标的连接请求尚未收到回复。
    • [ASSURED]:表示连接已经被确认,不会因为短时间内没有数据包而被清除。
  8. Mark(标记)mark字段用于表示特定的连接跟踪条目被打上的标记(或称为标签)
    • 这个标记是一个整数值,通常由防火墙规则(如iptables)设置,用于对特定的数据包或连接进行分类或执行特定的处理逻辑。
    • 可能的取值mark的取值范围是从04294967295(即2^32-1),其中0通常表示未被标记的连接。非零的值则根据实际的防火墙规则和策略而定,不同的值可以代表不同的分类或处理逻辑。例如,在某些配置中,mark可以用来区分经过VPN的流量、被特定规
  9. Use(使用)use字段表示当前有多少个内核组件正在引用这个连接跟踪条目。简而言之,它表明这个连接跟踪条目的“使用度”或“引用计数”。
    • 可能的取值use的取值是一个正整数,起始值至少为1,表示至少有一个引用(即连接跟踪本身)。如果有多个内核组件因为某些原因(如特定的路由或防火墙规则)同时需要跟踪这个连接,use的值会相应增加。一般而言,大多数情况下use的值会比较低,除非系统配置导致多个组件需要引用同一个连接跟踪条目。

3. 常用命令

查看当前连接追踪表

要查看当前系统中所有的连接追踪条目,可以使用以下命令:

sudo conntrack -L
查看所有TCP协议的连接
sudo conntrack -L -p tcp
查看所有UDP协议的连接
sudo conntrack -L -p udp
删除指定连接
sudo conntrack -D --src 192.168.1.2
显示具有特定状态的连接条目

只显示处于ESTABLISHED状态的TCP连接:

sudo conntrack -L -p tcp --state ESTABLISHED
删除所有处于特定状态的连接条目

删除所有处于TIME_WAIT状态的连接条目:

sudo conntrack -D --state TIME_WAIT
过滤并显示来自或发送到特定IP的连接条目

显示所有来自特定IP地址的连接条目:

sudo conntrack -L -s 192.168.1.3

显示所有发送到特定IP地址的连接条目:

sudo conntrack -L -d 192.168.1.10
使用源或目的端口过滤连接条目

显示所有使用特定源端口的连接条目:

sudo conntrack -L -p tcp --sport 22

显示所有使用特定目的端口的连接条目:

sudo conntrack -L -p tcp --dport 443
刷新连接追踪表(慎用)

如果需要清空所有的连接追踪条目,可以使用:

sudo conntrack -F
查看统计信息

查看连接追踪的统计信息,可以使用:

sudo conntrack -S

这会显示连接追踪的各种统计信息,如总条目数、TCP、UDP、ICMP 连接数等。

持续监控连接

实时监控连接追踪条目的变化,可以使用:

sudo conntrack -E
添加连接追踪条目

你可以手动添加一个连接追踪条目,例如:

sudo conntrack -I -p tcp --src 192.168.1.100 --sport 12345 --dst 192.168.1.200 --dport 80 --state ESTABLISHED
删除连接追踪条目

要删除一个特定的连接追踪条目,可以使用:

sudo conntrack -D -p tcp --src 192.168.1.100 --sport 12345 --dst 192.168.1.200 --dport 80

删除与特定源IP地址相关的所有连接条目:conntrack -D -s 192.168.1.100

删除与特定目的IP地址相关的所有连接条目:conntrack -D -d 192.168.1.100

利用NAT信息删除连接条目

删除所有源NAT(SNAT)到特定IP的连接:conntrack -D --src-nat 192.168.1.100

删除所有目的NAT(DNAT)到特定IP的连接:conntrack -D --dst-nat 192.168.1.100

导出连接追踪表

导出当前的连接追踪条目:

sudo conntrack -L > connections.txt

3. 配置 conntrack 参数

查看当前conntrack的最大值:

cat /proc/sys/net/netfilter/nf_conntrack_max
262144

修改conntrack的最大值:

# 临时生效
echo 2097152 > /proc/sys/net/netfilter/nf_conntrack_max

# 临时生效
sudo sysctl -w net.netfilter.nf_conntrack_max=2097152

# 永久生效
echo 'net.netfilter.nf_conntrack_max=2097152' | sudo tee -a /etc/sysctl.conf
sudo sysctl -p

4. 参考资料

https://segmentfault.com/a/1190000044768772

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐