运维排查篇 | Linux 连接跟踪表满了怎么处理

news2024/9/24 20:07:05

nf_conntrack (在老版本的 Linux 内核中叫 ip_conntrack )是一个内核模块,用于跟踪一个网络连接的状态

一旦内核 netfilter 模块 conntrack 相关参数配置不合理,导致 nf_conntrack table full ,就会出现丢包、连接无法建立的问题

这个问题其实是老问题了,之前也听说过,但都是左耳进右耳出,直到上周线上出现故障了,才真正的对这个问题有了一个较为全面的了解

于是我把我真实遇到的情况总结成今天这篇文章,让大家对这个问题产生的原因和背后细节有一个较好的了解

1.案例现象

上周周末,我们打算对 A 服务进行压测,在压测过程中测试小伙伴反馈后端服务挂了

登上机器查看一下服务器负载,发现正常,没有出现因负载过高导致服务器宕机的情况

然后查看 A 服务的日志,没有看到相关的请求记录,没有发现异常

接下来打算查看一下系统日志(/var/log/messages)

这时候才发现了不对劲,系统日志上记录了大量错误信息,如下:

Feb 18 14:02:17 localhost kernel: nf_conntrack: table full, dropping packet
Feb 18 14:02:17 localhost kernel: nf_conntrack: table full, dropping packet
Feb 18 14:02:17 localhost kernel: nf_conntrack: table full, dropping packet
Feb 18 14:02:17 localhost kernel: nf_conntrack: table full, dropping packet
Feb 18 14:02:22 localhost kernel: nf_conntrack: table full, dropping packet
Feb 18 14:02:22 localhost kernel: nf_conntrack: table full, dropping packet

看打印出来的信息应该是这个压测时候的高并发连接触发了 nf_conntrack 保护机制——table 满了之后就开始 drop packet

2.定位问题

根据系统日志可以基本定位到是 nf_conntrack 的问题,我们先来看看什么是 nf_conntrack

何为 nf_conntrack

nf_conntrack 从名字上看是 connection tracking ,它是一个内核模块,用于跟踪网络连接的状态

下面这个网站记录了有关这个模块的相关参数的含义,有兴趣的可以上去看看

https://www.kernel.org/doc/Documentation/networking/nf_conntrack-sysctl.txt

nf_conntrack 与 iptables 有关,用来计算服务器上的 iptables 规则,最常见的两个使用场景是 iptables 的 nat 模块和 state 模块

我们知道,iptables 中 nat 模块的作用就是根据规则来修改目的地址或源地址

但光修改地址还不行,我们还需要到达的包能够路由到发请求的服务器,这时候就需要通过 nf_conntrack 来找到 nat 修改前那个连接的记录

而 state 模块通过 nf_conntrack 记录的连接状态(NEW/ESTABLISHED/RELATED/INVALID 等)来匹配防火墙过滤规则

我们可以先看看 conntrack 的跟踪信息记录,我们可以在/proc/net/nf_conntrack中看到已经被跟踪的连接

cat /proc/net/nf_conntrack
ipv4     2 tcp      6 431930 ESTABLISHED src=192.168.149.131 dst=192.168.149.130 sport=11638 dport=4505 src=192.168.149.130 dst=192.168.149.131 sport=4505 dport=11638 [ASSURED] mark=0 zone=0 use=2

可以看出,2 是 ipv4 的协议代码(网络层),6 是 tcp 的协议代码(传输层),这里 conntrack 可以跟踪 tcp/udp/icmp等各种协议类型

ipv4     2  
tcp      6

431930 则是该连接的生命周期(默认是五天),在收到新包之前该值会逐渐变小,如果收到新包,该值会被重置一下,然后又开始重新计时

431930

ESTABLISHED 是连接状态,不是所有协议都有(例如 udp)

ESTABLISHED

接下来就是四元组,第一个地址四元组(源地址和目标地址以及端口)是在原始方向上记录的地址,即发起方发送的地址

src=192.168.149.131 dst=192.168.149.130 sport=11638 dport=4505

第二个四元组是 conntrack 希望在收到来自对等方的答复时看到的内容

src=192.168.149.130 dst=192.168.149.131 sport=4505 dport=11638

最后的 ASSURED 就是该状态已经确认

[ASSURED]

nf_conntrack 是如何存储连接信息的

上面部分介绍了 nf_conntrack 模块的作用——追踪连接

接下来该介绍 nf_conntrack 模块是怎么存储这些 track 信息的

我们首先需要知道nf_conntrack将每一条连接信息都 track 到一个哈希表里面(hash table),一条 conntrack 连接信息也称条目(entry)

哈希表中的最小存储单位称作 哈希桶(bucket),哈希表的大小称作 HASHSIZE,所以哈希表有 HASHSIZE个 bucket

bucket 的大小对应 nf_conntrack 模块中的nf_conntrack_buckets

而每个 bucket 包含一个链表(link list),每个链表都能够存放若干条 entry(bucket size

nf_conntrack_max 则表示系统最大允许连接跟踪数,即 entry 的个数

#nf_conntrack_max等于 bucket 个数乘上每个 bucket 的大小
nf_conntrack_max = HASHSIZE * bucket size

在这里插入图片描述
当有新的数据包到来时,内核是如何判断这条连接信息是否被 track 到的

  • 内核提取此数据包信息(源目IP,port,协议号)进行 hash 计算得到一个 hash 值,在哈希表中以此 hash 值做索引,索引结果为数据包所属的 bucket。这一步 hash 计算时间固定并且很短
  • 遍历 hash 得到所属的 bucket,查找是否有匹配的 entry。这一步是比较耗时的操作,bucket size 越大,遍历时间越长
  • 如果没有匹配到,则就新建

理想情况下,每个 bucket 下 link list 只存储一条 entry(即 bucket size = 1),这样查询效率是最高的,每次查询追踪记录的时候都是完美的 O(1) 的效率

但如果一个 bucket 存放一个 entry,这样会导致内存消耗非常大

官方指出:每个 entry 会占用大概 300 字节的空间,如果一个 bucket 存放一个 entry,那么整个哈希表的大小就等于总 entry 的大小

假设一个 bucket 存放一个 entry,我们设置 nf_conntrack_max == 12262144,就意味着哈希表可以存放12262144条 entry

这样我们会需要12262144308字节= 12262144308/(1024*1024) = 3508.22753906MB ,大约3个G的内存

一般服务器配置高点的,32G内存或者64G,光是给 connection track 就达到了 3G,更何况其中有些连接还是没有实际意义的已经被释放掉的 time_wait 的连接

那么一个 bucket 里应该存放多少条 entry 呢?

我们看下官方的解释,官方一般推荐一个 bucket 里存放四条 entry

在这里插入图片描述

nf_conntrack_max = nf_conntrack_buckets *4

如果一个 bucket 存放过多的 entry,就意味着每个 bucket 中的 link list 会非常长,会影响 hash 查询效率

所以一个 bucket 里存放四条 entry,兼顾时间和存储空间

3.解决问题

回到遇到的问题,既然报错是nf_conntrack: table full, dropping packet

那就意味着系统的连接跟踪表满了,我们有如下几种方法可选,请大家可以结合自己服务器情况来选择使用

  • 关闭防火墙

对不直接暴露在公网,也不使用 NAT 转发的服务器来说,关闭 Linux 防火墙是最简单的办法,还能避免防火墙/ netfilter 成为网络瓶颈

#以 CentOS 7 为例
systemctl stop firewalld
systemctl disable firewalld
  • 修改 iptables 规则

对于需要防火墙的机器,可以设置 NOTRACK 规则,减少要跟踪的连接数

对于一些不需要 track 的连接,针对对应的 iptables 规则加一个 notrack 的动作

# 表示凡是不跟踪的连接统统放行
# iptables 处理规则的顺序是从上到下,如果这条加的位置不对,可能导致请求无法通过防火墙
iptables -I INPUT 1 -m state --state UNTRACKED -j ACCEPT
-j notrack

把不需要 track 的 iptables 直接 notrack,那自然就不会去占 hashtable 空间了,更不会报错了

  • 优化内核参数

一般来讲有下面两个逻辑:

  1. 哈希表扩容(nf_conntrack_bucketsnf_conntrack_max
  2. 让哈希表里面的元素尽快释放(超时相关参数)

对于nf_conntrack_bucketsnf_conntrack_max的值,官方给了一个推荐大小

nf_conntrack_buckets - INTEGER
the default size is calculated by dividing total memory
by 16384 to determine the number of buckets but the hash table will
never have fewer than 32 and limited to 16384 buckets. For systems
with more than 4GB of memory it will be 65536 buckets.
This sysctl is only writeable in the initial net namespace.

nf_conntrack_max - INTEGER
Size of connection tracking table. Default value is
nf_conntrack_buckets value * 4

可以看到nf_conntrack_max与宿主机的内存相关,有个默认算法

#其中 x 为 CPU架构,值为 32 或 64 
CONNTRACK_MAX = RAMSIZE (in bytes) / 16384 / (x / 32)

假设宿主机架构为 64 位且内存为 64GB,所以nf_conntrack_max值如下:

CONNTRACK_MAX = 64 * 1024 * 1024 * 1024 / 16384 / (64 / 32) = 2097152

又因为nf_conntrack_max = nf_conntrack_buckets value * 4

nf_conntrack_buckets = 2097152 / 4 = 524288
nf_conntrack_max = 2097152 

nf_conntrack_buckets = 524288

PS:要根据自身服务器配置情况来进行配置,切勿一刀切!

对于超时时间,下列给出一些官方默认参数供大家参考,结合自身服务器情况进行修改

nf_conntrack_tcp_timeout_established:默认 432000 秒(5天)

代表 nf_conntrack 的 TCP 连接记录时间默认是五天,五天后该记录就被删除掉

攻击者可以根据这个参数,与你的服务器三次握手一建立就关闭 socket,分分钟把你的连接跟踪表打爆

net.netfilter.nf_conntrack_icmp_timeout:默认 30s

谁家 ping 等 30s 才算超时?

nf_conntrack_tcp_timeout_syn_sent:默认 120s

谁家程序的 connect timeout 需要 120s

nf_conntrack_tcp_timeout_last_ack:默认 30s

被动关闭方发 FIN 后如果一直收不到对面的 ACK 或 RST,会不断重发,直到超时才 CLOSE

nf_conntrack_tcp_timeout_time_wait:默认 120s

大家都知道 TIME_WAIT其实就是为了四次挥手的时候让数据包能够收收尾,现在网络环境好了,可以设置成 60s,没必要对 TIME_WAIT 的连接跟踪这么长时间

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/367293.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

电子技术——反馈放大器的分析方法总结

电子技术——反馈放大器的分析方法总结 第一种也是最简单的估算方法,直接拿出反馈网络,计算 β\betaβ 则假设在 AβA\betaAβ 无限大的情况下有 Af≃1/βA_f \simeq 1/\betaAf​≃1/β 。开环法。比第一种方法更能精确的估计 AAA 和 β\betaβ 的值。系…

js的异步方法:promise与定时器相遇,碰到的火花

前言: 我们在项目中长使用的异步方法 promise与定时器 在一起后,他们的顺序是什么样呢?这里来说一说。 案例1: console.log(异步打印顺序:);console.log(1);setTimeout(()>{console.log(2);},2000)setTim…

APP 兼容性测试是什么?10年阿里测试老鸟告诉你......

1、APP 兼容性测试认识 随着 APP 应用范围越来越广,用户群体越来越大,终端设备的型号也越来越多,移动终端碎片化加剧,使得 APP 兼容性测试成为测试质量保障必须要考虑的环节。 APP 兼容性测试通常会考虑:操作系统、厂…

firefly开发板RK3588非默认外设使能(串口uart、IIC、adc等)设备树修改详细步骤

sdk获取和内核编译,参考上一篇博文:rk3588内核裁剪 一、相关文件 文件1: rk3588_repo_sdk_v1.0.2a/kernel/arch/arm64/boot/dts/rockchip/rk3588-firefly-itx-3588j.dtsi此文件是针对firefly的板级设备树文件。 文件2: rk3588…

C#底层库--MySQL数据库脚本构建类(自动构建insert、update)

系列文章 C#底层库–记录日志帮助类 本文链接:https://blog.csdn.net/youcheng_ge/article/details/124187709 C#底层库–MySQL数据库脚本构建器(推荐阅读) 本文链接:https://blog.csdn.net/youcheng_ge/article/details/129179…

华为云计算之远程复制

实验环境说明身份管理IP业务IP主设备192.168.43.50H2:192.168.43.55从设备192.168.43.100P2:192.168.43.105存储的管理端口为8088登录到存储设备查看是否导入License访问https://192.168.43.50:8088,登录到主设备在设置中查看是否有添加远程设…

【AI绘图学习笔记】生成函数

生成模型学习笔记 (文章中大部分内容从网上学习笔记中摘录,推荐阅读原文,吴恩达深度学习课程笔记暂时停更一段时间,学习AI绘图原理是为了搞定毕业设计,等忙完再回头把基础补完,推荐读物《深度学习》花书&a…

我劝你千万不要去做CSGO游戏搬砖项目

尽管童话姐姐本人做CSGO游戏搬砖都快三年了,带的搬砖学员也好几百人了。但今天还是要跟未入行或者还在考虑是否入行的朋友们敲个警钟。 随着做这个的人越来越多,网上关于这个项目的文章,视频,硬广、软广也越来越多。就拿我朋友圈发…

高精度工业检测利器,维视智造BT-12C080双远心镜头

T-12C080 双远心镜头BT-12 系列标准 C 接口双远心镜头,与 1/2″(对角线 8mm)及以下成像靶面工业相机完美搭配,其结构稳定、外观轻巧,大景深,适用于较大视场下的高精度工业检测场景。产品亮点更轻巧与1/2″&…

【Database-01】达梦数据库Docker版下载安装

1、前往达梦数据库官网下载 https://www.dameng.com/1.1、选择数据库 - 数据库产品系 1.2、选择 达梦数据库管理系统(DM8) 1.3、点击试用下载 1.4、注册达梦账户 1.5、选择DM8 Docker镜像 https://www.dameng.com/list_103.html1.6、或者使用以下网址也…

雷达、定位、跟踪等信号处理邻域SCI期刊整理及推荐

雷达邻域SCI期刊整理及推荐:题名、刊物信息、撰写特点、审稿周期及投稿难度总结 定位/跟踪邻域SCI期刊整理及推荐:题名、刊物信息、撰写特点、审稿周期及投稿难度总结 估计/滤波/融合等信号处理邻域SCI期刊整理及推荐:题名、刊物信息、撰写…

Python数据分析与应用 | 数据分析工具Pandas

Pandas的数据结构分析 Pandas中有两个主要的数据结构:Series和DataFrame。 Series,一维的数据结构DataFrame,二维的,表格型的数据结构Series Series是一个类似一维数组的对象,它能够保存任何类型的数据,主要由一组数据和与之相关的索引两部分构成。左边是索引(index)…

树莓派——智能家居第一步

辛辛苦苦配了成功让树莓派开始工作了,开始搞智能家居!大体思路:基于工厂模式,分模块来实现上图分为三部分:主控、外设、控制主控我采用的是树莓派的4b4G版本,外设包括四个区域的灯(我的和上图有…

【Python】特征衍生

特征衍生1. 单变量特征衍生1.1 数据重编码1.2 高阶多项式2. 双变量特征衍生2.1 四则运算2.2 多项式衍生2.2.1 导包 & 数据2.2.2 二阶衍生2.2.3 三阶衍生3. 交叉组合3.1 导包 & 数据3.2 生成衍生列和名称3.3 独热编码1. 单变量特征衍生 1.1 数据重编码 连续变量 标准化…

对程序员来说最重要的小事——整洁代码

文章目录为什么要写整洁代码命名名副其实做有意义的区分类名、方法名函数短小只做一件事注释注释类型好注释坏注释格式目的垂直格式横向格式团队规则总结为什么要写整洁代码 现在阅读这篇博客的你不论是刚入行的新人还是开发了很多年的老鸟一定碰到过"祖传代码"&…

【原创】java+swing+mysql户籍管理系统设计与实现

户籍管理系统感觉跟学生管理系统有些类似,一个是对学生进行信息的管理,一个是对社会人员进行信息管理,难度系数基本一样,今天我们就来介绍一下使用javaswing和mysql进行户籍管理系统的开发。 功能分析: 户籍管理&…

【java 8】方法引用与构造器引用

📋 个人简介 💖 作者简介:大家好,我是阿牛,全栈领域优质创作者。😜📝 个人主页:馆主阿牛🔥🎉 支持我:点赞👍收藏⭐️留言&#x1f4d…

INT3断点和硬件断点

Ollydbg动态调试的时候需要打一些断点,断点分为INT3断点和硬件断点,本文是区分两个断点的文章。 目录 INT3断点 好处 坏处 硬件断点 原理 优点 缺点 INT3断点 OD中使用F2快捷键设置的断点就是INT3断点 打INT3断点的时候,断点处就会被…

Unity学习笔记--在Editor下实现一个有下拉菜单的文件路径记忆功能(保姆级教程)

目录前言需求分析知识前提一、下拉菜单的实现二、选取对应文件夹路径三、写入到.txt文件完整代码前言 最近需要在Unity编辑器下实现一个面板,有一个下拉菜单,其他人可以往这个下拉菜单里面添加一些文件夹路径,保证下次进来的时候能够直接通过…

Linux SPI-NAND 驱动开发指南

文章目录Linux SPI-NAND 驱动开发指南1 概述1.1 编写目的1.2 适用范围1.3 相关人员3 流程设计3.1 体系结构3.2 源码结构3.3 关键数据定义3.3.1 flash 设备信息数据结构3.3.2 flash chip 数据结构3.3.3 aw_spinand_chip_request3.3.4 ubi_ec_hdr3.3.5 ubi_vid_hdr3.4 关键接口说…