[转帖]一个Linux 内核 bug 导致的 TCP连接卡死

一个,linux,内核,bug,导致,tcp,连接,卡死 · 浏览次数 : 0

小编点评

## 问题分析: 1. 客户端从服务器拖数据,偶尔出现 TCP 连接卡死。 2. 服务器不遵守 TCP 重传逻辑,客户端不停地发 dup ack,但是服务端不响应这些dup ack仍然发新的包(从server抓包可以看到),直到服务端不再发任何新包,最终连接闲置过久被reset,客户端抛连接异常。 ## 问题原因: * 服务器可能不设置 `net_write_timeout` 参数,导致重传包无法正常发送并导致连接卡死。 * 重传包可能被内核其它环节吃掉了,因为内核在发送 buffer 满的时候忽略要发的包,进入静默为了解决这个问题。 ## 解决方案: 1. 降低 `net_write_timeout` 参数,让重传包尽快被发送并处理。 2. 加入更严格的条件来修复卡死的逻辑,确保重传包能够顺利发送并处理。 3. 确保服务器设置了 `net_write_timeout` 参数,并测试其有效性。 ## 其他建议: * 用户可以尝试升级内核到带有 2019-07-20 fix 版本的内核版本,因为此版本修复了该问题。 * 可以参考相关案例和文档,进一步理解该问题并解决问题。

正文

https://plantegg.github.io/2022/10/10/Linux%20BUG%E5%86%85%E6%A0%B8%E5%AF%BC%E8%87%B4%E7%9A%84%20TCP%E8%BF%9E%E6%8E%A5%E5%8D%A1%E6%AD%BB/

 

问题描述

客户端从 server 拖数据,偶尔会出现 TCP 连接卡死,卡死的现象就是 server 不遵循 TCP 重传逻辑,客户端不停地发 dup ack,但是服务端不响应这些dup ack仍然发新的包(从server抓包可以看到),直至服务端不再发任何新包,最终连接闲置过久被reset,客户端抛连接异常.

image-20230515162204533

Client MySQL JDBC 协议拉取 Server 3306端口 数据,频繁出现卡死与超时,Client端Java 报错:Application was streaming results when the connection failed. Consider raising value of ‘net_write_timeout’ on the server. - com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Application was streaming results when the connection failed. Consider raising value of ‘net_write_timeout’ on the server.

分析

服务端抓包可以看到:这个 TCP 流, 17:40:40 后 3306 端口不做任何响应,进入卡死状态,在卡死前有一些重传

image.png

同时通过观察这些连接的实时状态:

image-20220922092105581

rto一直在增加,但是这个时候 server 上抓不到任何包,说明内核在做 rto 重传,但是重传包没有到达本机网卡,应该还是被内核其它环节吃掉了。

再观察 netstat -s 状态,重传的时候,TCPWqueueTooBig 值会增加,也就是重传->TCPWqueueTooBig->重传包未发出->循环->相当于 TCP 连接卡死、静默状态

image-20220922092321039

顺着 TCPWqueueTooBig 查看内核代码提交记录, 红色部分是修 CVE-2019-11478 添加的代码,引入了这个 卡死 的bug,绿色部分增加了更严格的条件又修复了卡死的 bug

image.png

原因

2019-05 为了解决 CVE-2019-11478 增加了这个commit:f070ef2ac66716357066b683fb0baf55f8191a2e,这部分代码在发送 buffer 满的时候忽略要发的包,进入静默

为了解决这个问题 2019-07-20 fix 版本:https://github.com/torvalds/linux/commit/b617158dc096709d8600c53b6052144d12b89fab

4.19.57 是 2019-07-03 发布,完美引入了这个 bug

快速确认:netstat -s | grep TCPWqueueTooBig 如果不为0 就出现过 TCP 卡死,同时还可以看到 tb(待发送队列) 大于 rb(发送队列 buffer)

重现条件

必要条件:合并了 commit:f070ef2ac66716357066b683fb0baf55f8191a2e 的内核版本

提高重现概率的其它非必要条件:

  1. 数据量大—拖数据任务、大查询;
  2. 有丢包—链路偏长连接,丢包概率大;
  3. 多个任务 —一个失败整个任务失败,客户体感强烈
  4. Server 设置了小buffer,出现概率更高

在这四种情况下出现概率更高。用户单个小查询SQL 睬中这个bug后一般可能就是个连接异常,重试就过去了,所以可能没有抱怨。 得这四个条件一起用户的抱怨就会凸显出来。

解决

升级内核到带有2019-07-20 fix 版本:https://github.com/torvalds/linux/commit/b617158dc096709d8600c53b6052144d12b89fab

相关资料

https://www.secrss.com/articles/11570

https://access.redhat.com/solutions/4302501

https://access.redhat.com/solutions/5162381

databricks 的相同案例: https://www.databricks.com/blog/2019/09/16/adventures-in-the-tcp-stack-performance-regressions-vulnerability-fixes.html

6月第一个人报了这个bug:https://lore.kernel.org/netdev/CALMXkpYVRxgeqarp4gnmX7GqYh1sWOAt6UaRFqYBOaaNFfZ5sw@mail.gmail.com/

Hi Eric, I now have a packetdrill test that started failing (see below). Admittedly, a bit weird test with the SO_SNDBUF forced so low. Nevertheless, previously this test would pass, now it stalls after the write() because tcp_fragment() returns -ENOMEM. Your commit-message mentions that this could trigger when one sets SO_SNDBUF low. But, here we have a complete stall of the connection and we never recover.
I don’t know if we care about this, but there it is :-)

一个 zero windows 下卡死的内核bug

与[转帖]一个Linux 内核 bug 导致的 TCP连接卡死相似的内容:

[转帖]一个Linux 内核 bug 导致的 TCP连接卡死

https://plantegg.github.io/2022/10/10/Linux%20BUG%E5%86%85%E6%A0%B8%E5%AF%BC%E8%87%B4%E7%9A%84%20TCP%E8%BF%9E%E6%8E%A5%E5%8D%A1%E6%AD%BB/ 问题描述 客户端从 se

[转帖]手把手教你在QEMU上运行RISC-V Linux

https://kernel.0voice.com/forum.php?mod=viewthread&tid=3080 嵌入式Linux内核 发布于 2023-3-15 14:44:37 阅读 46只看楼主 今天教大家在QEMU模拟器上运行一个RISC-V Linux 一个RISC-V Linux包

[转帖]linux中内核的一个不错的参数somaxconn

最近发现很多内核优化参数都记不住了,写下文章来备记,方便以后查看. 编辑 /etc/sysctl.conf 文件,在里面加入如下内容:(有注释) #设置系统对最大跟踪的TCP连接数的限制(CentOS 5.6无此参数) net.ipv4.ip_conntrack_max = 25000000 #最大

[转帖]使用 Crash 工具分析 Linux dump 文件

前言 Linux 内核(以下简称内核)是一个不与特定进程相关的功能集合,内核的代码很难轻易的在调试器中执行和跟踪。开发者认为,内核如果发生了错误,就不应该继续运行。因此内核发生错误时,它的行为通常被设定为系统崩溃,机器重启。基于动态存储器的电气特性,机器重启后,上次错误发生时的现场会遭到破坏,这使得

[转帖]Linux内核参数之nf_conntrack

https://www.jianshu.com/p/d2b28703e376 问题描述 近日线下测试环境的一个cloudstack计算节点上的虚拟机出现频繁的丢包情况,经过排查日志发现这个计算节点的包被丢弃,日志信息如下: Oct 29 16:18:14 a2 kernel: __ratelimit

[转帖]Linux内核参数之nf_conntrack

https://www.jianshu.com/p/d2b28703e376 问题描述 近日线下测试环境的一个cloudstack计算节点上的虚拟机出现频繁的丢包情况,经过排查日志发现这个计算节点的包被丢弃,日志信息如下: Oct 29 16:18:14 a2 kernel: __ratelimit

[转帖]Linux内核线程kthread简介【最好的一篇!】

https://zhuanlan.zhihu.com/p/581587583 Linux内核可以看作一个服务进程(管理软硬件资源,响应用户进程的种种合理以及不合理的请求)。内核需要多个执行流并行,为了防止可能的阻塞,支持多线程是必要的。内核线程就是内核的分身,一个分身可以处理一件特定事情。内核线程的

[转帖]Linux内核简介、子系统及分类

一、内核简介 内核:在计算机科学中是一个用来管理软件发出的数据I/O(输入与输出)要求的计算机程序,将这些要求转译为数据处理的指令并交由中央处理器(CPU)及计算机中其他电子组件进行处理,是现代操作系统中最基本的部分。它是为众多应用程序提供对计算机硬件的安全访问的一部分软件,这种访问是有限的,并由内

[转帖]Linux流控框架:TC和Netfilter

https://www.jianshu.com/p/de30bac5b893 Linux内核内置了一个Traffic Control框架,可以实现流量限速,流量整形,策略应用(丢弃,NAT等)。从这个框架你能想到别的什么吗?或许现在不能,但是我会先简单说一下,和TC框架比较相似的是Netfilter

[转帖]Linux 内核 | 网络流量限速方案大 PK

https://maimai.cn/article/detail?fid=1674483493&efid=UXVPILU_JTlqLrYhTkDStA 网络流量限速是一个经久不衰的话题,Linux 内核中已经实现了若干种流量限速的方式。 最简单的方式是通过定期采集速率,在超过指定的速率后直接丢包,但