Linux内核采用熵来描述数据的随机性。熵(entropy)是描述系统混乱无序程度的物理量,一个系统的熵越大则说明该系统的有序性越差,即不确定性越大。在信息学中,熵被用来表征一个符号或系统的不确定性,熵越大,表明系统所含有用信息量越少,不确定度越大。
计算机本身是可预测的系统,因此,用计算机算法不可能产生真正的随机数。但是机器的环境中充满了各种各样的噪声,如硬件设备发生中断的时间,用户点击鼠标的时间间隔等是完全随机的,事先无法预测。Linux内核实现的随机数产生器正是利用系统中的这些随机噪声来产生高质量随机数序列。
内核维护了一个熵池用来收集来自设备驱动程序和其它来源的环境噪音。理论上,熵池中的数据是完全随机的,可以实现产生真随机数序列。为跟踪熵池中数据的随机性,内核在将数据加入池的时候将估算数据的随机性,这个过程称作熵估算。熵估算值描述池中包含的随机数位数,其值越大表示池中数据的随机性越好。
CentOS 7系统中安装好openjdk和Tomcat后,启动过程很慢,长达数分钟,日志如下:
tomcat启动耗时278084ms折合278秒,对于刚刚安装的干净tomcat,这肯定是不对劲的。
其中有一条日志引起了笔者的注意:
显然tomcat执行到这里时出问题了,google了一下,经过一番搜索明白了其中的缘由。
在tomcat官方wiki文档的 HowToFasterStartUp 章节中,Entropy Source部分有一段这样的说明:
从这里我们得知Tocmat的Session ID是通过SHA1PRNG算法计算得到的,计算Session ID的时候必须有一个密钥,为了提高安全性Tomcat在启动的时候会通过随机生成一个密钥,它强依赖于获取熵池中的随机数来进行创建。
那么什么是 /dev/random ?什么是 熵池 ?
/dev/random
从维基百科得知,在UNIX *** 作系统(包括类UNIX系统)中, /dev/random 是一个特殊的设备文件,可以用作随机数生成器或伪随机数生成器。
Linux内核中的是第一个以 背景噪声 产生真正的随机数产生的实现,它允许程序访问来自设备驱动程序或其它来源的背景噪声。
Linux上有两个通用的随机设备: /dev/random 和 /dev/urandom 。其中 /dev/random 的随机性最好,因为它是一个阻塞的设备。而 /dev/random 的一个副本是 /dev/urandom (“unblocked”,非阻塞的随机数生成器),它会重复使用熵池中的数据以产生伪随机数据。这表示对 /dev/urandom 的读取 *** 作不会产生阻塞,但其输出的熵可能小于 /dev/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减少了,熵池补给的速度当然也变慢,进而不够用。
其实,通过消耗熵池,可以构造DDOS攻击。原理很简单,熵池空了,依赖随机数的业务(SSL,加密等)就不能正常进行。
通过以上信息,笔者得知该问题是由于熵池不足导致的。 怎么解决?
使用非阻塞性的生成器 /dev/urandom 代替 /dev/random 。
1、可在JVM环境中配置
通过配置发生器指定熵收集守护进程
修改 $JAVA_PATH/jre/lib/security/java.security 中参数 securerandom.source 为:
2、也可在Tomcat环境中配置
通过配置JRE使用非阻塞的Entropy Source获取熵
在 $TOMCAT_HOME/bin/catalina.sh 中加入:
这个系统属性egd表示熵收集守护进程(entropy gathering daemon)。
1、[硬件随机数生成器]安装并使用rng-tools作为额外的熵随机数生成器(推荐)
cat /dev/random 命令会消耗熵池, rngd 守护进程会补充熵池,可使用如下命令来测试随机数生成的情况:
2、[软件随机数生成器]在rng-tools仍不满足的情况下,可使用haveged作为额外的熵随机数生成器
要检查是否需要 Haveged,可使用下面命令查看当前收集到的熵:
如果结果比较低 (<1000),建议安装 haveged,否则加密程序会处于等待状态,直到系统有足够的熵。
安装 haveged 之后,可以再次查看系统熵看下有无提升。
因为方法一存在一定的不安全性,且需要对环境进行配置,为了满足熵的需要,这里笔者选择了第二种方法,使用rng-tools作为额外的熵随机数生成器,同以上 *** 作后顺利解决了问题。
*** 作后重启tomcat日志如下,启动速度快了两个数量级:
参考文档:
https://stackoverflow.com/questions/40383430/tomcat-takes-too-much-time-to-start-java-securerandom
https://bugs.java.com/bugdatabase/view_bug.do?bug_id=6202721
http://openjdk.java.net/jeps/123
https://zh.wikipedia.org/zh-hans//dev/random
https://wiki.apache.org/tomcat/HowTo/FasterStartUp
https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/6/html/security_guide/sect-security_guide-encryption-using_the_random_number_generator
https://wiki.archlinux.org/index.php/Rng-tools
https://wiki.archlinux.org/index.php/Haveged
https://www.digitalocean.com/community/tutorials/how-to-setup-additional-entropy-for-cloud-servers-using-haveged
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)