nf_conntrack连接跟踪模块

本文深入解析iptables中的nf_conntrack模块,介绍如何通过该模块跟踪连接的不同状态,包括NEW、ESTABLISHED、RELATED和INVALID。此外,还介绍了如何配置连接跟踪的最大连接数及各种连接状态的超时时间。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

nf_conntrack连接跟踪模块

在iptables里,包是和被跟踪连接的四种不同状态有关的。它们分别是NEW,ESTABLISHED,RELATED和INVALID。后面我们会深入地讨论每一个状态。使用iptables的state模块可以匹配操作这几种状态,我们能很容易地控制“谁或什么能发起新的会话”。为什么需要这种状态跟踪机制呢?比如你的80端口开启,而你的程序被植入反弹式木马,导致服务器主动从80端口向外部发起连接请求,这个时候你怎么控制呢。关掉80端口,那么你的网站也无法正常运行了。但有了连接跟踪你就可以设置只允许回复关于80端口的外部请求(ESATBLISHED状态),而无法发起向外部的请求(NEW状态)。所以有了连接跟踪就可以做到在这种层面上的限制,慢慢往下看就明白了各状态的意义。

所有在内核中由Netfilter的特定框架做的连接跟踪称作conntrack(connection tracking)。conntrack可以作为模块安装,也可以作为内核的一部分。大部分情况下,我们想要也需要更详细的连接跟踪,这是相比于缺省的conntrack而言。也因为此,conntrack中有许多用来处理TCP,UDP或ICMP协议的部件。这些模块从数据包中提取详细的、唯一的信息,因此能保持对每一个数据流的跟踪。这些信息也告知conntrack流当前的状态。例如,UDP流一般由他们的目的地址、源地址、目的端口和源端口唯一确定。

在以前的内核里,我们可以打开或关闭重组功能。然而连接跟踪被引入内核后,这个选项就被取消了。因为没有包的重组,连接跟踪就不能正常工作。现在重组已经整合入conntrack,并且在conntrack启动时自动启动。不要关闭重组功能,除非你要关闭连接跟踪。

除了本地产生的包由OUTPUT链处理外,所有连接跟踪都是在PREROUTING链里进行处理的,意思就是, iptables会在PREROUTING链里从新计算所有的状态。如果我们发送一个流的初始化包,状态就会在OUTPUT链里被设置为NEW,当我们收到回应的包时,状态就会在PREROUTING链里被设置为ESTABLISHED。如果第一个包不是本地产生的,那就会在PREROUTING链里被设置为NEW状态。综上,所有状态的改变和计算都是在nat表中的PREROUTING链和OUTPUT链里完成的。

conntrack默认最大跟踪65536个连接,查看当前系统设置最大连接数

[root@server ~]# cat /proc/sys/net/netfilter/nf_conntrack_max
65536

查看连接跟踪有多少条目

[root@server ~]# cat /proc/sys/net/netfilter/nf_conntrack_count
1

当服务器连接多于最大连接数时会出现kernel: ip_conntrack: table full, dropping packet的错误。

解决方法,修改conntrack最大跟踪连接数:

[root@server ~]# vim /etc/sysctl.conf
[root@server ~]# sysctl -p
net.nf_conntrack_max = 100000

查看established连接状态最多保留几天,默认是432000秒,就是5天;如果觉得时间太长可以修改。还有各种tcp连接状态的保留时间,都可以修改的。

[root@server ~]# cat /proc/sys/net/netfilter/nf_conntrack_tcp_timeout_established
432000  

连接跟踪(conntrack)记录

IP_conntrack模块根据IP地址可以实时追踪本机TCP/UDP/ICMP的连接详细信息并保存在内存中“/proc/net/nf_conntrack”文件中(Centos5中使用的是/proc/net/ip_conntrack)。查看这个文件的记录会有如下信息:

ipv4     2 tcp      6 89  SYN_SENT src=101.81.225.225 dst=112.74.99.130 sport=33952 dport=80 
src=112.74.99.130 dst=101.81.225.225 sport=80 dport=33952 [UNREPLIED] mark=0 secmark=0 use=2
1
2
ipv4     2 tcp      6 89  SYN_SENT src=101.81.225.225 dst=112.74.99.130 sport=33952 dport=80 
src=112.74.99.130 dst=101.81.225.225 sport=80 dport=33952 [UNREPLIED] mark=0 secmark=0 use=2

IP_conntrack模块维护的所有信息都包含在这个例子中了,通过它们就可以知道某个特定的连接处于什么状态。首先显示的是IP类型,然后是协议,这里是tcp,接着是十进制的6(tcp的协议类型代码是6)。之后的89是这条conntrack记录的生存时间(TTL),它会有规律地被消耗,直到收到这个连接的更多的包。那时,这个值就会被设为当时那个状态的缺省值。接下来的是这个连接在当前时间点的状态。上面的例子说明这个包处在状态 SYN_SENT,这个值是iptables显示的,以便我们好理解,而内部用的值稍有不同。SYN_SENT说明我们正在观察的这个连接只在一个方向发送了一TCP SYN包。再下面是源地址、目的地址、源端口和目的端口。最后,是希望接收的应答包的信息,他们的地址和端口和前面是相反的。其中有个特殊的词[UNREPLIED],说明这个连接还没有收到任何回应。

当一个连接在两个方向上都有传输时,conntrack记录就删除[UNREPLIED]标志,然后重置。在末尾有[ASSURED]的记录说明两个方向已没有流量。

ipv4     2 tcp      6 431962 ESTABLISHED src=101.81.225.225 dst=112.74.99.130 sport=33952 dport=80 
src=112.74.99.130 dst=101.81.225.225 sport=80 dport=33952 [ASSURED] mark=0 secmark=0 use=2
1
2
ipv4     2 tcp      6 431962 ESTABLISHED src=101.81.225.225 dst=112.74.99.130 sport=33952 dport=80 
src=112.74.99.130 dst=101.81.225.225 sport=80 dport=33952 [ASSURED] mark=0 secmark=0 use=2

这样的记录是确定的,在连接跟踪表满时,是不会被删除的,没有[ASSURED]的记录就要被删除。连接跟踪表能容纳多少记录是被一个变量控制的,默认值取决于你的内存大小,128MB可以包含8192条目录,256MB是16376条,在拥有较大内存的机器中默认65536条。对于一个高并发的web服务器来说,如果你的请求数大过/proc/sys/net/netfilter/nf_conntrack_max文件中定义的数目,那么就会出现用户连接失败并且报错,报错信息如下:

nf_conntrack: table full, dropping packet.
1
nf_conntrack: table full, dropping packet.

而我们第一时间想到的办法就是关闭防火墙或是增大默认连接数,修改默认最大值,如下:

[root@localhost ~]# echo "100000" > /proc/sys/net/netfilter/nf_conntrack_max
1
[root@localhost ~]# echo "100000" > /proc/sys/net/netfilter/nf_conntrack_max

但不要盲目增大nf_conntrack_max的值-理解Linux内核内存分配

连接追踪模块属于内核的,所以我们知道所有的连接跟踪信息都是保存于内存中的,因此会考虑单纯放大这个nf_conntrack_max参数会占据多少内存,会权衡内存的占用,如果系统没有太大的内存,就不会将此值设置的太高。但是如果你的系统有很大的内存呢?比如有8G的内存,分个1G给连接跟踪也不算什么啊,这是合理的,然而在传统的32位架构Linux中是做不到,为什么?首先32位架构中最大寻址能力是4G,而Linux内存管理是虚拟内存的方式,4G内存分给内存的是1G,其他3G是理论上分给单个进程的,每个进程认为自己有3G内存可用,最后是根据每个进程实际使用的内存映射到物理内存中去。

内存越来越便宜的今天,Linux的内存映射方式确实有点过时了。然而事实就摆在那里,nf_conntrack处于内核空间,它所需的内存必须映射到内核空间,而传统的32位Linux内存映射方式只有1G属于内核,这1G的地址空间中,前896M是和物理内存一一线性映射的,后面的若干空洞之后,有若干vmalloc的空间,这些vmalloc空间和一一映射空间相比,很小很小,算上4G封顶下面的很小的映射空间,一共可以让内核使用的地址空间不超过1G。对于ip_conntrack来讲,由于其使用slab分配器,因此它还必须使用一一映射的地址空间,这就是说,它最多只能使用不到896M的内存!

为何Linux使用如此“落后”的内存映射机制这么多年还不改进?其实这种对内核空间内存十分苛刻的设计在64位架构下有了很大的改观,也可以放心根据内存调整最大连接追踪条目了。但问题依然存在,即使64位架构,内核也无法做到透明访问所有的物理内存,它同样需要把物理内存映射到内核地址空间后才能访问,对于一一映射,这种映射是事先确定的,对于大小有限(实际上很小)非一一映射空间,需要动态创建页表,页目录等。所以条目太多就会消耗性能且会产生内存碎片。另外如果不需要用到连接跟踪功能可以选择在Iptables中关闭,以此来提高系统的网络连接性能(因为开启会产生大量的IO操作)。卸载ip_conntrack模块如下,必须要先关闭防火墙才能卸载。另外注意当你试图查看iptables规则之后,就会激活ip_conntrack模块,无法真正卸载掉哦。

$ service iptables stop
$ modprobe -r nf_conntrack
1
2
$ service iptables stop
$ modprobe -r nf_conntrack

查看实时连接信息

查看ip_conntrack实时连接状态信息,安装iptstate工具

yum -y install iptstate     

执行命令

[root@server ~]# iptstate  

如下所示

相关的内核参数

[root@server ~]# sysctl -a | grep conntrack
net.netfilter.nf_conntrack_acct = 0
net.netfilter.nf_conntrack_buckets = 16384
net.netfilter.nf_conntrack_checksum = 1
net.netfilter.nf_conntrack_count = 1
net.netfilter.nf_conntrack_events = 1
net.netfilter.nf_conntrack_events_retry_timeout = 15
net.netfilter.nf_conntrack_expect_max = 256
net.netfilter.nf_conntrack_generic_timeout = 600
net.netfilter.nf_conntrack_helper = 1
net.netfilter.nf_conntrack_icmp_timeout = 30
net.netfilter.nf_conntrack_log_invalid = 0
net.netfilter.nf_conntrack_max = 65536
net.netfilter.nf_conntrack_tcp_be_liberal = 0
net.netfilter.nf_conntrack_tcp_loose = 1
net.netfilter.nf_conntrack_tcp_max_retrans = 3
net.netfilter.nf_conntrack_tcp_timeout_close = 10
net.netfilter.nf_conntrack_tcp_timeout_close_wait = 60
net.netfilter.nf_conntrack_tcp_timeout_established = 432000
net.netfilter.nf_conntrack_tcp_timeout_fin_wait = 120
net.netfilter.nf_conntrack_tcp_timeout_last_ack = 30
net.netfilter.nf_conntrack_tcp_timeout_max_retrans = 300
net.netfilter.nf_conntrack_tcp_timeout_syn_recv = 60
net.netfilter.nf_conntrack_tcp_timeout_syn_sent = 120
net.netfilter.nf_conntrack_tcp_timeout_time_wait = 120
net.netfilter.nf_conntrack_tcp_timeout_unacknowledged = 300
net.netfilter.nf_conntrack_timestamp = 0
net.netfilter.nf_conntrack_udp_timeout = 30
net.netfilter.nf_conntrack_udp_timeout_stream = 180
net.nf_conntrack_max = 65536

也可以使用 dmesg 查看。

[root@server ~]# dmesg | tail -f
[    3.656918] ppdev: user-space parallel port driver
[    3.680022] alg: No test for __gcm-aes-aesni (__driver-gcm-aes-aesni)
[    3.772029] alg: No test for crc32 (crc32-pclmul)
[    3.785294] intel_rapl: no valid rapl domains found in package 0
[    7.120138] EXT4-fs (vda1): resizing filesystem from 786176 to 5242304 blocks
[    7.422160] EXT4-fs (vda1): resized filesystem to 5242304
[ 1994.617368] nf_conntrack version 0.5.0 (16384 buckets, 65536 max)
[ 3657.011241] nr_pdflush_threads exported in /proc is scheduled for removal
[ 4538.293958] Netfilter messages via NETLINK v0.30.
[ 4538.300128] ctnetlink v0.93: registering with nfnetlink.
转自:https://awen.me/post/59062.html?from=timeline
<think>好的,我现在需要帮助用户在Linux系统中使用modprobe加载nf_conntracknf_nat内核模块。首先,我得回顾一下相关的知识,确保自己对这些模块和modprobe命令的理解正确。 首先,我记得nf_conntrack模块是用于连接跟踪的,它维护一个连接状态表,供其他模块如防火墙或NAT使用。而nf_nat模块则负责网络地址转换,通常在需要NAT功能时使用。这两个模块通常是相互依赖的,加载顺序可能有讲究。 接下来,用户的问题是关于如何通过命令行加载这两个模块。根据之前的引用内容,用户可能之前尝试过移除这些模块,现在需要重新加载。modprobe命令是用来加载内核模块的,它会自动处理依赖关系,所以可能需要先加载依赖的模块。 根据引用[1],用户之前卸载了xt_NOTRACK、nf_conntrack_netbios_ns、nf_conntrack_ipv4、xt_state和nf_conntrack模块。因此,重新加载的时候,可能需要先加载基础模块,比如nf_conntrack,然后再加载依赖它的模块,比如nf_nat。 不过,在Linux中,通常nf_nat模块依赖于nf_conntrack,所以使用modprobe应该会自动处理这些依赖。也就是说,用户可能只需要运行modprobe nf_conntrack,然后再modprobe nf_nat,或者可能直接加载nf_nat,因为modprobe会自动加载依赖项。 但需要确认的是,某些系统上模块可能有不同的名称或依赖结构。例如,nf_conntrack_ipv4可能已经被更新为基于nf_conntrack的通用模块,尤其是在较新的内核版本中。因此,可能需要检查当前内核版本和模块的实际名称。 另外,根据引用[4],当卸载了相关模块后,使用iptables时会出现nat表不存在的问题,这提示nf_nat模块可能没有被加载,导致iptables无法使用NAT功能。所以加载这两个模块后,应该能恢复nat表的功能。 接下来,我需要验证一下正确的命令步骤。通常加载模块的命令是: sudo modprobe nf_conntrack sudo modprobe nf_nat 不过,可能由于依赖关系,加载nf_nat时会自动加载nf_conntrack,所以可能只需要加载nf_nat即可。但为了明确,分开加载可能更稳妥。 此外,可以使用lsmod | grep nf_conntrack和lsmod | grep nf_nat来检查模块是否已经加载。如果未加载,再执行相应的modprobe命令。 可能遇到的问题包括模块不存在或已被禁用。例如,某些内核可能将这些模块编译为内置(built-in)而非可加载模块,这时modprobe会失败。但这种情况较少见,尤其是对于标准发行版。 总结步骤应该是: 1. 加载nf_conntrack模块。 2. 加载nf_nat模块。 3. 验证是否加载成功。 此外,可能需要确认模块的配置参数,比如引用[2]提到的sysctl设置,但用户的问题仅是加载模块,可能不需要涉及这些设置。 另外,根据引用[3],nf_conntrack模块在2.6.15之后引入,用户可能使用的是较新的内核,所以模块名称应该正确。 现在需要将这些步骤以清晰的中文回答呈现,并按照用户的要求,使用正确的LaTeX格式,同时生成相关问题。 最后,确保回答中引用了正确的引用来源,比如引用[1]、[3]中提到的模块加载和卸载的相关内容。</think>要在Linux系统中加载`nf_conntrack`和`nf_nat`内核模块,可通过以下步骤实现: ### 1. 加载模块的命令 - **加载`nf_conntrack`模块**: ```bash sudo modprobe nf_conntrack ``` 该命令会加载连接跟踪模块,用于跟踪网络连接状态[^3]。 - **加载`nf_nat`模块**: ```bash sudo modprobe nf_nat ``` `nf_nat`模块依赖`nf_conntrack`,因此需先加载后者(`modprobe`会自动处理依赖,但显式加载更稳妥)。 ### 2. 验证模块加载状态 - 使用以下命令检查模块是否加载成功: ```bash lsmod | grep -E "nf_conntrack|nf_nat" ``` 若输出包含`nf_conntrack`和`nf_nat`,则表明加载成功。 ### 3. 加载依赖的其他模块(可选) 若需使用NAT功能(如iptables的`nat`表),可能需要加载相关辅助模块: ```bash sudo modprobe nf_nat_ipv4 # IPv4 NAT支持 ``` ### 4. 持久化配置(重启后生效) 若需开机自动加载模块,可将模块名添加到`/etc/modules-load.d/`配置文件中: ```bash echo "nf_conntrack" | sudo tee -a /etc/modules-load.d/nf.conf echo "nf_nat" | sudo tee -a /etc/modules-load.d/nf.conf ``` ### 注意事项 - 若模块加载失败,可能是内核未编译该模块模块名称不匹配(需检查内核版本)[^4]。 - 加载后可通过`sysctl`调整`nf_conntrack`参数(如哈希表大小)[^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值