由Linux内核bug引起SSH登录缓慢问题的排查与解决

今年7月,有一位用户反馈,使用该镜像创建出的快杰云主机每次启动时,第一次SSH登录会很慢,有时候需几十秒甚至几分钟才能登录成功,影响了使用体验。经过排查,定位到是Linux内核随机数熵池初始化慢的原因,且在多个条件组合下才会触发。更深入调查则发现因为内核bug,凡使用了libssl 1.1.1的进程(如开启了https的nginx)都有类似问题,会对系统安全产生不少潜在影响。最终我们通过升级自主维护的内核,很快妥善修复了该问题,保证了快杰云主机的体验和安全性。

本文对排查过程加以梳理。

1

初步排查

该问题只在单个用户上出现过,且只影响启动后的首次SSH登录,一旦登录成功便恢复正常。现场捕获不易,不过我们设法将其复现。

ssh -v打开ssh用户端的冗余日志模式尝试登录问题主机,发现总是会卡在”debug1: pledge: network”处,根据提示,sshd已经完成了用户的身份认证过程。

可以看出,问题应当是发生在身份鉴定刚完成后,由此判断,问题有较大可能是发生在 /etc/pam.d/sshd 定义的PAM过程中。
motd检视/etc/pam.d/sshd文件,根据现象以及直觉,决定尝试先屏蔽几段配置,其中就包括motd行,motd(message of the day)是Ubuntu登录后呈现给用户看到的部分banner内容。随后重启主机,发现ssh登录变快,不再卡住。

查阅资料可知,motd机制下,pam_motd.so会依次执行 /etc/update-motd.d/ 目录下的全部脚本,而这些脚本的输出则会被拼凑输出到文件/run/motd.dynamic中,最终呈现在banner中。

因此,怀疑是这些脚本的执行过程中产生的卡顿,阅读这些脚本,执行断点echo 调试,最后发现,位于”50-landscape-sysinfo”脚本中的“/usr/bin/landscape-sysinfo”命令执行时就会造成卡顿。

landscape-sysinfo

该命令仅仅是一个用来搜集显示banner中系统资源使用情况的工具,出现此问题有点难以置信,可实际上登录进入后多次执行此命令也没有出现卡顿。

尝试进一步追踪此命令的执行,使用strace追踪此命令的执行,并记录日志。

分析日志可以发现,启动时,该命令被卡在了getrandom系统调用上,解除阻塞时间点为 23:10:48。

getrandom

etrandom封装了对 /dev/urandom 字符设备文件的读取操作,用于获取高质量的随机数,/dev/urandom 会以/dev/random 的值做为seed参考,/dev/random 值则来自硬件运行的噪音(随机质量很高)。这种机制也决定了/dev/urandom在操作系统刚启动时生成的随机数质量不高(刚启动,/dev/random中噪音不足,生成慢,随机性差,容易被预测,间接导致了/dev/urandom的起始seed质量低下),所以 /dev/urandom 内部对其质量设置了三种状态:

  • 0=未初始化,但是/dev/urandom已经可用;
  • 1=快速初始化,使用了少量熵数进行了快速初始化,在刚启动时就尽快可以被用起来,质量还行,但是仍然不被建议用于加密场景,通常发生在操作系统启动后的几秒内;
  • 2=完全初始化,随机数的质量达到最高,可以用于加密场景,操作系统启动后约几十秒-几分钟的时间才能达到。

在默认情况下,getrandom读取/dev/urandom前会去检测 /dev/urandom 的质量状态,如果尚未完全初始化,则会阻塞,直到其完全初始化,以此来保障通过此接口获得到的随机数质量高且速度快,为安全领域提供可靠的依赖。了解了getrandom接口的作用和表现后,再去翻看内核的启动日志,找到了时间相关性极高的点。

可以看到,23:10:48时 /dev/urandom 完全初始化后,随即getrandom的调用阻塞也被解除了,再多次重复验证后,关联性被确认。此时的结论以及建议解决办法为:原因:操作系统初始化随机数熵池速度较慢,导致ssh登录时使用到随机数的一条命令时被阻塞。

建议:禁用motd或者删除landscape-sysinfo来达到加速ssh登录的目的。

2

深入调查

初步调查的结论有点违反常理,禁用或者删除的措施也需谨慎。为此,我决定找出更多的证据,此外,也需要解释为什么旧版本的Ubuntu并没有此现象。尝试查看表现正常的主机上 landscape-sysinfo 的 strace 表现,查阅日志后注意到,此环境下的strace记录与问题主机中strace记录在调用模式上存在不同,表现正常的主机上landscape-sysinfo中没有这样的调用“getrandom(“xxx”, 32, 0) ”,注意第三个flag参数值,此flag用于表明使用getrandom的默认行为,即/dev/urandom未完全初始化时则阻塞。所有getrandom的地方都使用了flag GRND_NONBLOCK,即如果没有初始化完成不要阻塞,返回错误就好。至此,怀疑是landscape-sysinfo版本问题。landscape-sysinfo对比两台主机上的landscape-sysinfo版本,发现版本号确实不同,有问题的版本号较高,没问题的版本号较低。

将没问题的主机执行apt-get update & apt-get upgrade,升级后发现问题果然重现。得出临时结论:landscape-sysinfo新版本使用了getrandom的阻塞模式获取随机数,不要升级landscape-sysinfo的版本即可。

开始尝试在其它主机上进行复现和验证,却发现,在另一个高内核版本的镜像中,低版本的landscape-sysinfo也能复现此问题,strace追踪调用,发现其调用行为与高版本的landscape-sysinfo表现相似,鉴于此命令实际上是python3脚本,怀疑是其依赖的库升级导致。检查apt-get upgrade升级的package,找出与随机数关联度较大的几个包,几次排除尝试后,定位发现,其实是由于libssl1.1这个库的升级导致的问题,getrandom的调用也是源自于libssl1.1。

libssl1.1翻阅 。

可以看到,的确,libssl1.1.1的升级,重写了内部随机数的生成器,也符合前面的表现,更新为使用getrandom读取更加安全的随机数(代价是刚开机时使用就容易被阻塞)。继续尝试在其它主机上进行复现和验证,又发现,在某个低内核版本的Ubuntu主机上,安装的正是libssl1.1.1,却不能复现问题。按照预期,libssl1.1.1的升级就是为了更安全,而如果一开机就能立刻得到随机数,这根本就违背的getrandom接口的设计初衷,此时倾向于怀疑内核可能存在bug。

内核bug以libssl调用getrandom被阻塞为关键主题查阅资料,最终找到相关性较强的资料,其中CRNG指密码学强度的随机数发生器。根据此资料,证实了内核bug的猜测,内核在4.16时修正过这样一个bug:getrandom在快速初始化完成后就不再阻塞,这与getrandom的接口设计违背,容易造成安全问题(CVE-2018-1108)

验证主机的内核版本为4.15.0,与此情况符合,即很有可能是bug没有被修复,此时,开始尝试升级低内核版本主机的内核版本,如果此猜测正确,那么升级到高版本后应当同样会发生卡顿问题。在apt源上挑选了一个5.0版本的内核,升级后发现,居然也没有问题。翻阅内核日志,发现了一个新的现象,此前看到对于/dev/urandom的初始化,一般是会有一条“fast init done”日志,较长时间后会跟随一个“crng init done”日志,正好对应着/dev/urandom的两种质量状态。

而此内核版本下,则是在刚启动就立即出现了“crng done (trusting CPU’s manufacturer) ”的日志,明显表明熵池被极速的初始化了,自然不会出现卡顿问题。

查询此现象相关资料,找到了一个内核编译选项:CONFIG_RANDOM_TRUST_CPU。CONFIG_RANDOM_TRUST_CPU此选项通过参考x86指令集中的RDRAND来初始化随机数熵池,以此达到让getrandom不再blocking的目的,前提是需要操作者信任CPU制造商。RDRAND指令由Intel在IVB世代中首次引入x86中,AMD在2015年6月时跟进,由于此指令并非标准指令,因此操作系统使用前需要做额外的功能检测。

首次出现于4.19版本:检查高版本内核的两台主机,的确,有问题的主机此flag并没有enable,无问题的主机此flag显式的enable了。

而有问题主机使用的内核版本,取自于Ubuntu官方的最新主线分支编译,默认没有启动此flag做优化。结论此问题的出现需要同时满足以下几个条件:1. linux内核版本在4.17及以上2. linux内核编译选项 CONFIG_RANDOM_TRUST_CPU is not set,或者CPU非IVB及以上的x863. linux内核bug未被社区revert(4.x的最新社区版本几乎都被revert,5.x没有)4. libssl版本在1.1.1及以上影响面事实上,SSH登录卡顿仅仅是一种表象,这个问题的真实影响范围,可以扩展得非常大。凡是使用了libssl1.1.1来生成随机数的进程全都会受影响,导致重启后3-5分钟内会被随机数block。比如,服务器上跑着nginx(开启https),一般认为机器启动后,nginx马上启动就能提供服务了,但是受此问题影响,nginx会被卡住三五分钟。就是说,前三五分钟内的用户https请求全部会出现访问失败的现象。

问题修复

为了做到性能与安全兼顾,在编译4.19及更高版本的内核时,启用CONFIG_RANDOM_TRUST_CPU选项,我们采用此方法,enable选项并确保虚拟机可以访问RDRAND指令集,很快重新发布了云主机镜像。如果用户使用自定义内核,应尽量避开4.17-4.19之间的版本,或者妥善处理好CVE-2018-1108。

3

总结

提起云主机,首先会想到计算、存储、网络,甚少有人关注内核。然而,内核构建也是云主机的核心工作,对性能和稳定性至关重要。SSH登录缓慢起初是单一用户的反馈,且限于Ubuntu启动后的首次登录,但通过坚持排查和顺藤摸瓜,我们发现了潜在的影响面并予以修复,防患于未然。

Image placeholder
wiliams
未设置
  38人点赞

没有讨论,发表一下自己的看法吧

推荐文章
系统运行缓慢,CPU 100%,以及Full GC次数过多问题的排查思路

来源:http://t.cn/EI9JdBu处理过线上问题的同学基本上都会遇到系统突然运行缓慢,CPU100%,以及FullGC次数过多的问题。当然,这些问题的最终导致的直观现象就是系统运行缓慢,并且

Linux Kernel Linux内核项目

推荐课程:Linux开发工程师--学习猿地--送七个上线商业项目 Linux是最受欢迎的自由电脑操作系统内核。它是一个用C语言写成,符合POSIX标准的类Unix操作系统。Linux最早是由芬兰黑客林

一文学会Java死锁和CPU 100% 问题的排查技巧

00本文简介作为一名搞技术的程序猿或者是攻城狮,想必你应该是对下面这两个问题有所了解,说不定你在实际的工作或者面试就有遇到过:第一个问题:Java死锁如何排查和解决?第二个问题:服务器CPU占用率高达

重启大法失效?详述Oracle11g因JDBC bug引发异常Library Cache Lock等待处理事件

墨墨导读:在Oracle11g版本中可能出现由于JDBCbug导致sql绑定变量无法共享,过期游标过多的情况,此时如果发生大量并发业务,很有可能造成异常librarycachelock等待事件,造成数

华为“鸿蒙”所涉及的微内核到底是什么?一文带你认识微内核

微内核最近微内核的概念常常被大家提及,同时还有GoogleFuchisa这样的微内核新星,这里让我们一起来认识下微内核吧。背景庞大的UNIX家族计算机技术在二战后快速发展,构成计算机的主要基本单元从电

笨办法学 Linux Bash:Shell、`.profile`、`.bashrc`、`.bash_history`

Bash:Shell、.profile、.bashrc、.bash_history。 当使用CLI(命令行界面)来使用Linux时,你正在与一个名为shell的程序进行交互。所有你输入的都传递给she

回馈开源,我如何排查一个MySQL Bug

X-Engine是阿里巴巴自研的高性能低成本存储引擎,经过多年的努力,我们在集团内部以AliSQL(X-Engine)的形式(AliSQL是阿里的MySQL分支)支持了许多业务,为用户带来了显著的成本

《MySQL主从不一致情形与解决方法》

一、MySQL主从不同步情况1.1网络的延迟由于mysql主从复制是基于binlog的一种异步复制通过网络传送binlog文件,理所当然网络延迟是主从不同步的绝大多数的原因,特别是跨机房的数据同步出现

Java 程序员眼中的 Linux_1.0.Linux 介绍

Linux介绍 Linux这个名字 Linux的Wiki介绍:http://zh.wikipedia.org/zh/Linux Linux也称:GNU/Linux,而其中GNU的全称又是:Gnu’sN

[Java 程序员眼中的 Linux] Linux 下常用压缩文件的解压、压缩

Linux下常用压缩文件的解压、压缩 常用压缩包解压命令整理 Linux后缀为.tar.gz格式的文件-解压 命令:tarzxvfXXXXXX.tar.gz Linux后缀为.bz2格式的文件-解压

笨办法 学Linux 安装Linux

Linux学习起步 Windows,VirtualBox虚拟机(.ova格式的预配置映像) 学习Linux你需要什么 VitualBox,虚拟机播放器。 putty,终端模拟器。 预配置的Virtua

Linux/Unix 基础:什么是 Linux?

简单来讲,Linux是一个操作系统(OS)。我们都很熟悉其他操作系统,就像Microsoftwindows,AppleMacOS,iOS,Googleandroid,等等这些,linux就像它们一样,

Linux/Unix 基础:Linux 的历史

Linux的诞生 在1991年,来自芬兰Helsinki大学的学生LinusTorvalds认为市场上应该有一个比较统一的Unix版本,从此他就开始为这个项目奋斗。后来这个项目就成为了Linux操作系

别小瞧了 Linux,安卓、华为的自研系统,均源自 Linux!

众所周知,目前国内已有众多的国产系统,基本上均源自linux,以linux为基础进行二次开发。比如红旗linux、深度等等。但不知道为什么,一说起某系统是基于linux而来,很多网友就瞧不起,并且会觉

Linux Libertine Linux字体

课程推荐:Linux开发工程师--学习猿地精品在线课 软件简介 出于对GNU/Linux发行版中所附带的字体不满,PhilippH.Poll于2003年9月启动了LinuxLibertine开放性字体

utf8 加密与解密

utf8加密 functionUTF8Encoder(options){ varfatal=options.fatal; this.encode=function(output_byte_stream

utf8 加密与解密

utf8加密functionUTF8Encoder(options){ varfatal=options.fatal; this.encode=function(output_byte_stream,

序列密码的加密与解密

课程推荐:Python开发工程师--学习猿地--送9个上线商业项目 序列密码的加密与解密明文、密文和密钥序列都是有单独位组成,即 x{i},y{i},s_{i}\in\left{0,1\right}x

记一次隐藏很深的 JVM 线上惨案的分析、排查、解决!

1、本文背景本文会给大家讲解一个比较特殊的JVM优化案例,这个优化案例本身是因为新手工程师对JVM优化可能了解了一个半吊子,然后不知道从哪里找来了一个非常特殊的JVM参数错误的设置了一下,就导致线上系

RTSP、RTMP网络摄像头互联网无插件直播视频流媒体服务器EasyNVR在windows上无法启动问题排查

背景需求随着雪亮工程、明厨亮灶、手机看店、智慧幼儿园监控等行业开始将传统的安防摄像头进行互联网、微信直播,我们知道摄像头直播的春天了。将安防摄像头或NVR上的视频流转成互联网直播常用的RTSP、RTM

Oracle调度作业引起的空间骤增问题处理记录

1、 问题描述接到客户电话告知,说是近期数据库磁盘目录空间增长特别快, 1-2 天就满了。联系客户对数据库进行分析后,发现造成空间急剧增长的原因主要是 job 任务的 trace 文件产生的量太大造成

分析PHP URL中特殊字符引起的问题(+,\,=)

课程推荐:PHP开发工程师--学习猿地--送9个上线商业项目 PHP中URL中特殊字符引起的问题(+,,=) 前言,在做某个渠道的过程中,发现一个验签错误的问题。但是,当时验签在两个地方表现不一致,同

周末生产事故!一次心惊肉跳的服务器入侵排查….

近日接到客户求助,他们收到托管电信机房的信息,通知检测到他们的一台服务器有对外发送攻击流量的行为。希望我们能协助排查问题。 一、确认安全事件情况紧急,首先要确认安全事件的真实性。经过和服务器运维人员沟

事务注解(@Transactional)引起的数据覆盖故障

最近组织团队内技术培训,刘聪为分享的一个跟事务和写数据库相关的case(bug)很有代表性。用事务,要小心!一、故障现象车辆交付履约流程上两个节点(工程项目)A和B,A修改一条数据记录item(工单)

Linux Shell 脚本快速入门

shell脚本是在一个文件中写入一起执行的命令集。对于使用像dos操作系统的DOS,windows操作系统的bat,linux操作系统的files的人来说,这几乎都是相同的概念。你只需要把一串命令写