nf_conntrack连接跟踪模块

2023-10-29 10:10

本文主要是介绍nf_conntrack连接跟踪模块,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

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

这篇关于nf_conntrack连接跟踪模块的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/299936

相关文章

Python的time模块一些常用功能(各种与时间相关的函数)

《Python的time模块一些常用功能(各种与时间相关的函数)》Python的time模块提供了各种与时间相关的函数,包括获取当前时间、处理时间间隔、执行时间测量等,:本文主要介绍Python的... 目录1. 获取当前时间2. 时间格式化3. 延时执行4. 时间戳运算5. 计算代码执行时间6. 转换为指

Python正则表达式语法及re模块中的常用函数详解

《Python正则表达式语法及re模块中的常用函数详解》这篇文章主要给大家介绍了关于Python正则表达式语法及re模块中常用函数的相关资料,正则表达式是一种强大的字符串处理工具,可以用于匹配、切分、... 目录概念、作用和步骤语法re模块中的常用函数总结 概念、作用和步骤概念: 本身也是一个字符串,其中

Python中的getopt模块用法小结

《Python中的getopt模块用法小结》getopt.getopt()函数是Python中用于解析命令行参数的标准库函数,该函数可以从命令行中提取选项和参数,并对它们进行处理,本文详细介绍了Pyt... 目录getopt模块介绍getopt.getopt函数的介绍getopt模块的常用用法getopt模

python logging模块详解及其日志定时清理方式

《pythonlogging模块详解及其日志定时清理方式》:本文主要介绍pythonlogging模块详解及其日志定时清理方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地... 目录python logging模块及日志定时清理1.创建logger对象2.logging.basicCo

Qt spdlog日志模块的使用详解

《Qtspdlog日志模块的使用详解》在Qt应用程序开发中,良好的日志系统至关重要,本文将介绍如何使用spdlog1.5.0创建满足以下要求的日志系统,感兴趣的朋友一起看看吧... 目录版本摘要例子logmanager.cpp文件main.cpp文件版本spdlog版本:1.5.0采用1.5.0版本主要

MySQL中的交叉连接、自然连接和内连接查询详解

《MySQL中的交叉连接、自然连接和内连接查询详解》:本文主要介绍MySQL中的交叉连接、自然连接和内连接查询,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、引入二、交php叉连接(cross join)三、自然连接(naturalandroid join)四

python连接本地SQL server详细图文教程

《python连接本地SQLserver详细图文教程》在数据分析领域,经常需要从数据库中获取数据进行分析和处理,下面:本文主要介绍python连接本地SQLserver的相关资料,文中通过代码... 目录一.设置本地账号1.新建用户2.开启双重验证3,开启TCP/IP本地服务二js.python连接实例1.

Ubuntu中远程连接Mysql数据库的详细图文教程

《Ubuntu中远程连接Mysql数据库的详细图文教程》Ubuntu是一个以桌面应用为主的Linux发行版操作系统,这篇文章主要为大家详细介绍了Ubuntu中远程连接Mysql数据库的详细图文教程,有... 目录1、版本2、检查有没有mysql2.1 查询是否安装了Mysql包2.2 查看Mysql版本2.

Python3.6连接MySQL的详细步骤

《Python3.6连接MySQL的详细步骤》在现代Web开发和数据处理中,Python与数据库的交互是必不可少的一部分,MySQL作为最流行的开源关系型数据库管理系统之一,与Python的结合可以实... 目录环境准备安装python 3.6安装mysql安装pymysql库连接到MySQL建立连接执行S

Spring Boot 整合 MyBatis 连接数据库及常见问题

《SpringBoot整合MyBatis连接数据库及常见问题》MyBatis是一个优秀的持久层框架,支持定制化SQL、存储过程以及高级映射,下面详细介绍如何在SpringBoot项目中整合My... 目录一、基本配置1. 添加依赖2. 配置数据库连接二、项目结构三、核心组件实现(示例)1. 实体类2. Ma