linux熵池耗尽,导致oracle数据库连接失败
今天接到某业务开发人员的报错信息:
随后又接到应用运维人员的报错信息:
连接失败,errorCode 17002, state 08006
两位同学的反馈,问题都指向数据库,应用无法连接数据库。
赶紧检查数据库状态……
结果:
数据库监听正常
集群状态正常
数据库日志没有报错
会话远没达到配置上线
数据库没有死锁
系统资源都比较空闲,没有压力
数据库一切正常……
根据错误代码,进行查询,发现可能是linux系统熵池不够,导致连接无法建立,原因是oracle 11g JDBC在建立连接时需要大约40个字节随机数据来加密session token之类的连接字符串,而这个随机数据源默认用的是/dev/random,通过搜集键盘,鼠标,中断,磁盘操作来产生随机数据,可以通过以下命令查看当前的熵值:
cat /proc/sys/kernel/random/entropy_avail
结果发现,熵值最低时为100多,最高时只有300多。
熵池上限大小
cat /proc/sys/kernel/random/poolsize
4096
明显熵池不够,我们有以下几种解决方法:
1)把随机源由/dev/random修改为/dev/urandom,即在执行java程序加入命令行参数:
-Djava.security.egd=file:///dev/urandom
2)安装一个提供熵的程序包
yum install haveged
service haveged start
chkconfig --level 2345 haveged on
或
yum install rng-tools
service rngd start
chkconfig --level 2345 rngd on
安装后,熵值飙升到3000多,业务重启后,连接数据恢复正常
那么,究竟是什么程序频繁消耗熵值呢?
我们查看一下熵值随时间的变化情况
cat /proc/sys/kernel/random/entropy_avail && date
发现每次在0秒时,下降比较大
想起前段时间部署了oracle数据采集脚本,使用python+cx_oracle连接数据库,每分钟执行一次。
linux熵池原理
Linux内核采用熵来描述数据的随机性。熵(entropy)是描述系统混乱无序程度的物理量,一个系统的熵越大则说明该系统的有序性越差,即不确定性越大。在信息学中,熵被用来表征一个符号或系统的不确定性,熵越大,表明系统所含有用信息量越少,不确定度越大。
计算机本身是可预测的系统,因此,用计算机算法不可能产生真正的随机数。但是机器的环境中充满了各种各样的噪声,如硬件设备发生中断的时间,用户点击鼠标的时间间隔等是完全随机的,事先无法预测。Linux内核实现的随机数产生器正是利用系统中的这些随机噪声来产生高质量随机数序列。
内核维护了一个熵池用来收集来自设备驱动程序和其它来源的环境噪音。理论上,熵池中的数据是完全随机的,可以实现产生真随机数序列。为跟踪熵池中数据的随机性,内核在将数据加入池的时候将估算数据的随机性,这个过程称作熵估算。熵估算值描述池中包含的随机数位数,其值越大表示池中数据的随机性越好。
linux熵池与oracle数据库的关系
默认情况下,Oracle JDBC 11g似乎会使用/dev/random。而使用/dev/random生成随机数时,依赖熵池。如果熵池空了或不够用,对/dev/random的读取就会堵塞,直到熵池够用为止。但是有文章中说,urandom的随机性弱于random(也有反对者)。
那怎么让熵池增加呢?熵池小会有什么其他后果吗?
熵池本质上是若干字节。/proc/sys/kernel/random/entropy_avail 中存储了熵池现在的大小,/proc/sys/kernel/random/poolsize是熵池的最大容量,单位都是bit。如果entropy_avail的值小于要产生的随机数bit数,那么/dev/random就会堵塞。
熵池怎么增加?
只有少数驱动程序会填充熵池,首先是键盘和鼠标。
实际上是从各种noice source中获取数据,noice source可能是 键盘事件、鼠标事件、设备时钟中等。
linux内核从2.4升级到2.6时,处于安全性的考虑,废弃了一些source。source减少了,熵池补给的速度当然也变慢,进而不够用。
具体方法参考文中前半部分
熵斥堵塞会有什么后果?
其实,通过消耗熵池,可以构造DOS攻击。原理很简单,熵池空了,依赖随机数的业务(SSL,加密等)就不能正常进行。