一、背景
公司生产环境上线,所有服务器上线前,都要经过系统安全检测。这个过程中发现很多系统安全问题是由于OpenSSH和OpenSSL版本太低导致的。在负责漏洞修复的过程中,遇到了很多坑,这里将升级OpenSSH和OpenSSL的步骤和遇到的问题进行一下总结分享下,希望对大家有所帮助
二、系统及版本说明
操作系统:CentOS6.5,CentOS7.3,CentOS7.0
OpenSSH升级版本:openssh-7.9p1
OpenSSL升级版本:openssl-1.1.1a
三、升级OpenSSL
1.yum -y install gcc-c++ //首先安装gcc-c++,不然通过./config编译时会报错,同时避免rpm -e卸载openssl导致yum命令不可用
2.openssl version //查看版本
3.rpm -qa | grep openssl //查看rpm包安装的openssl
\千万不要执行这个卸载命令,会删除 /usr/lib64/libssl.so.10和/usr/lib64/libcrypto.so.10,导致yum命令和ping不能用,ssh连接也会直接失败。影响非常严重
## 4、 rpm -e rpm -qa | grep openssl --nodeps //卸载通过rpm包安装的openssl
4.cd /usr/local/src //进入源文件目录
5.rz //通过rz命令上传下载好的openssl-1.1.1a.tar.gz包
6.tar -zxvf openssl-1.1.1a.tar.gz //解压
7.cd openssl-1.1.1a
8.编译安装
./config --prefix=/usr --shared && make && make install
9.添加软链接
ln -s /usr/lib64/libcrypto.so.1.0.0 /usr/lib64/libcrypto.so.10 ln -s /usr/lib64/libssl.so.1.0.0 /usr/lib64/libssl.so.10
如果执行了 rpm -e rpm -qa | grep openssl --nodeps 命令,则一定要重建软链接。
但是一定要先进入/usr/lib64目录里面查看libcrypto.so.1和libssl.so.1.是什么版本的
,我在新机器安装中,里面是libssl.so.1.0.2k,如果直接使用上面的语句创建链接,就会创建无效的链接,yum命令还是不能用。
版本检测
openssl version
问题记录:
问题一、libcrypto.so.10: cannot open shared object file: No such file or directory
[root@localhost kibana]# openssl version /usr/libexec/pk-command-not-found: error while loading shared libraries: libcrypto.so.10: cannot open shared object file: No such file or directory
解决:
执行添加软链接操作
ln -s /usr/lib64/libcrypto.so.1.0.0 /usr/lib64/libcrypto.so.10 ln -s /usr/lib64/libssl.so.1.0.0 /usr/lib64/libssl.so.10
问题二、openssl命令不能识别
[root@localhost openssl-1.1.1a]# openssl version -bash: openssl: command not found
分析原因:
命令无效,一般是软件的/bin目录没有追加入到环境变量的path下的路径后面,或者程序安装时可执行文件没有加入到/usr/bin/目录下。
通过以下命令全局搜索openssl文件:
find / -name openssl
确实没有在/usr/bin下发现可执行的openssl文件,所以openssl命令无法执行。
产生原因,是自己通过源码编译安装最新的openssl时,没有先通过rpm -e rpm -qa | grep openssl --nodeps卸载老版本rpm安装的openssl。之后检测出漏洞后,只是直接使用了rpm -qa | grep openssl --nodeps卸载老版本,
导致/usr/bin/目录下的openssl文件也被删除。
修复办法:
cd openssl-1.1.1a make && make install openssl version
如果发现openssl命令还是无法识别,那么就直接删除openssl-1.1.1a文件夹重新编译安装。这里要注意,通过源码编译安装的程序,要先使用make uninstall卸载程序。
操作命令如下:
cd openssl-1.1.1a make uninstall cd .. rm -fr openssl-1.1.1a tar -zxvf openssl-1.1.1a.tar.gz cd openssl-1.1.1a ./config --prefix=/usr --shared && make && make install ln -s /usr/lib64/libcrypto.so.1.0.0 /usr/lib64/libcrypto.so.10 ln -s /usr/lib64/libssl.so.1.0.0 /usr/lib64/libssl.so.10 openssl version -a
四、升级OpenSSH
这部分的操作非常非常重要,一定要非常小心。因为OpenSSH控制着服务器的远程登录连接。稍有不慎,就会造成远程连接失败。笔者就在升级腾讯云服务器上的OpenSSH时,由于操作失误,导致SSH连接不上,最后不得不一键重装系统,这是非常惨痛的教学。
这里给大家一点忠告:网上的博客教程一定要先在测试机上实践,注意系统版本和软件版本的一致性,稍有不同就可能产生不一样的结果,所以一定要谨慎,不然那坑可能你伤不起。
下面进入正题:
1.环境检查
官方给出的文档中提到的先决条件openssh安装依赖zlib1.1.4并且openssl>=1.0.1版本就可以了。
[root@zabbix-serv ~]# openssl version OpenSSL 1.0.1e-fips 11 Feb 2013 [root@zabbix-serv ~]# rpm -q zlib zlib-1.2.3-29.el6.x86_64 [root@zabbix-serv ~]# rpm -q zlib-devel zlib-devel-1.2.3-29.el6.x86_64 [root@zabbix-serv ~]#ssh -V //查看ssh的版本
2.安装依赖包
yum install -y gcc openssh-clients openssl-devel pam-devel rpm-build pam-devel
3.备份ssh配置文件
#####cp -r /etc/ssh/ /home/ssh-bak
这一步非常非常重要,这个目录下的信息控制着ssh连接的秘钥和配置信息。
网上很多备份的做法使用的是移动命令
mv /etc/ssh/ /home/ssh-bak //推荐 (##############推荐####################)
而我这里为什么使用复制命令,而不是移动命令呢?
我们在编译安装openssh的时候,执行make && make install命令的时候,系统会自动去检查/etc/ssh/目录下的文件,如果文件存在,是不会生产新文件覆盖原来的配置文件和秘钥的。
如果这里使用了移动命令,就会在/etc/ssh/生成新的内容。
当然,你也可以先使用移动命令,安装完openssl后,再删除/etc/ssh/里面的所有内容,然后将mv命令备份的文件全部移动回来。本质是保证配置文件和秘钥和原来保持一致。
这一步是升级OpenSSH后,ssh远程连接能正常进行的重要前提。
吃到了苦头,如果不用编译安装sshd新生成的sshd_config的配置文件,很容易出现配置项不兼容的情况。导致ssh连接失败。
所以,这里推荐使用mv /etc/ssh/ /home/ssh-bak 备份。
4.卸载老的OpenSSH
rpm -qa | grep openssh rpm -e `rpm -qa | grep openssh` --nodeps //下面是执行卸载操作的提升信息 warning: /etc/ssh/ssh_config saved as /etc/ssh/ssh_config.rpmsave warning: /etc/ssh/moduli saved as /etc/ssh/moduli.rpmsave
注意:
(1)命令执行过程中的提示信息一定不要忽视,上面执行卸载命令时,提示信息很明显,告诉我们将原来的ssh_config配置文件保存到了ssh_config.rpmsave文件中,将原来的moduli保存到了moduli.rpmsave文件中。
(2)由于升级ssh过程中,很容易出现一些奇葩问题导致ssh连接断开,建议操作过程中先多开2,3个连接,防止出现意外。
5.解压、编译、安装
cd /usr/local/src/ && tar zxvf openssh-7.9p1.tar.gz && cd openssh-7.9p1 ./configure --prefix=/usr --sysconfdir=/etc/ssh --with-pam --with-zlib --with-md5-passwords --with-tcp-wrappers && make && make install
在执行make install命令时,出现了如下提示,正如前面所说,升级过程中,如果/etc/ssh/已经存在的配置文件,是不会被覆盖的。
/etc/ssh/ssh_config already exists, install will not overwrite /etc/ssh/sshd_config already exists, install will not overwrite /etc/ssh/moduli already exists, install will not overwrite
6.修改配置
根据步骤4卸载操作中的提示,将原来的配置文件还原即可。
mv /etc/ssh/ssh_config /etc/ssh/ssh_config.back mv /etc/ssh/ssh_config.rpmsave /etc/ssh/ssh_config mv /etc/ssh/moduli /etc/ssh/ssh_config.back mv /etc/ssh/moduli.rpmsave /etc/ssh/moduli
网上很多教程说要对/etc/ssh/sshd_config配置文件进行修改,这里是升级操作,尽可能保证配置文件的原生性就好。
这里简单介绍下里面的一些核心配置项:
PermitRootLogin yes //允许root用户远程登录
PermitEmptyPasswords no //不允许使用空密码远程登录
如果执行了mv /etc/ssh/ /home/ssh-bak操作,那么这里一定修改新生成的sshd_config里面的PermitRootLogin yes 属性。
7.关闭selinux
vi etc/selinux/config
SELINUX=disabled
使用这种方式对selinux关闭,要重启服务器才能生效。
这里由于ssh配置没有完成,显然是不适合做重启服务器操作的。
可以先通过命令临时关闭selinux
setenforce 0 getenforce
这里对selinux的安全级别进行下说明:
目前 SELinux 支持三种模式,分别如下:
•enforcing:强制模式,代表 SELinux 运作中,且已经正确的开始限制 domain/type 了;
•permissive:宽容模式:代表 SELinux 运作中,不过仅会有警告讯息并不会实际限制 domain/type 的存取。这种模式可以运来作为 SELinux 的 debug 之用;
•disabled:关闭,SELinux 并没有实际运作。
【问题】通过上面的学习我们知道,如果将启动着的SELinux改为禁用,需要重启电脑,我们不想重启电脑又不想开启SELinux该怎么办呢?
【答案】将强制模式改为宽松模!
[root@www ~]# setenforce [0|1]
选项与参数:
0 :转成 permissive 宽容模式;
1 :转成 Enforcing 强制模式
范例一:将 SELinux 在 Enforcing 与 permissive 之间切换与查看
[root@www ~]# setenforce 0 [root@www ~]# getenforce Permissive [root@www ~]# setenforce 1 [root@www ~]# getenforce Enforcing
8.服务自启配置
cp contrib/redhat/sshd.init /etc/init.d/sshd chkconfig --add sshd chkconfig sshd on service sshd start service sshd restart chkconfig --list sshd ssh -V
9.检查root用户远程ssh登录是否正常
如果能正常登陆,说明我们的升级操作成功了。
问题记录:
问题一、执行configure编译时,出现OpenSSL headers missing……
configure: error: *** OpenSSL headers missing - please install first or check config.log ***
解决:
该问题是由于没有安装openssl-devel
yum install -y openssl-devel yum install -y openssh-clients
如果安装失败,可以尝试如下命令使用rpm包安装:
cd /media/RHEL-7.0\ Server.x86_64/Packages/ rpm -ivh --nodeps libsepol-devel-2.1.9-3.el7.x86_64.rpm rpm -ivh --nodeps openssl-devel-1.0.1e-34.el7.x86_64.rpm rpm -ivh --nodeps zlib-devel-1.2.7-13.el7.x86_64.rpm
需要安装系统的时候将ios中rpm的镜像文件保存在本机的media目录下。
问题二、
WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED
解决:
这个问题虽然只是通过ssh远程连接的一个警告问题,但是如果不解决,是无法进行远程连接的。
问题的本质是升级OpenSSH的过程中,删除了服务器/etc/ssh/目录下的秘钥。重新生成的秘钥和正在进行远程连接的服务器在初次ssh连接目标服务器记录的hostname信息匹配不上,导致识别不了。
打个比方,服务器A初次通过ssh登录到服务器B,这时会和服务器B下的秘钥文件进行一些认证,通过后,会在服务器A下的~/.ssh/known_hosts文件下记录服务器B的ip以及对应加密后的hostname信息。
现在服务器B中的秘钥变化了,那么服务A在~/.ssh/known_hosts文件下记录的服务器B的hostname信息显然是错误的了。
解决:
vi ~/.ssh/known_hosts
然后删除掉服务器B对应的那行信息。
这样服务器A再次进行SSH登录服务器B时,相当于初次认证,通过后,会在服务器A的~/.ssh/known_hosts文件中,生成新的服务器B的ip和加密后的hostname信息。
不过显然,这不是非常优雅的做法,升级过程,尽量不要造成其他的影响,保证/etc/ssh/下配置文件和秘钥的原生性。
问题三、linux版本差异导致安装过程中产生的问题
在CentOS Linux release 7.3.1611 (Core) 下升级OpenSSH时,
编译通过后,执行安装时
make && make install
出现如果警告信息:
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @ WARNING: UNPROTECTED PRIVATE KEY FILE! @ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ Permissions 0640 for '/etc/ssh/ssh_host_ecdsa_key' are too open. It is required that your private key files are NOT accessible by others. This private key will be ignored. Error loading host key "/etc/ssh/ssh_host_ecdsa_key": bad permissions Could not load host key: /etc/ssh/ssh_host_ecdsa_key @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @ WARNING: UNPROTECTED PRIVATE KEY FILE! @ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ Permissions 0640 for '/etc/ssh/ssh_host_ed25519_key' are too open. It is required that your private key files are NOT accessible by others. This private key will be ignored. Error loading host key "/etc/ssh/ssh_host_ed25519_key": bad permissions Could not load host key: /etc/ssh/ssh_host_ed25519_key [root@localhost openssh-7.9p1]# cat /etc/redhat-release CentOS Linux release 7.3.1611 (Core) [root@localhost openssh-7.9p1]# ssh -V OpenSSH_7.9p1, OpenSSL 1.1.1a 20 Nov 2018
简单的来说,
由于备份过程中,采用了mv命令,导致/etc/ssh/目录下的秘钥都重新生成。但是生成的秘钥权限太高,导致私有秘钥被忽略。
解决:
如果编译过程没有注意查看警告信息,
可以在ssh连接失败后,通过systemctl status sshd 命令,查看目标服务器ssh连接失败的原因。
发现是秘钥权限的原因,那么我们直接根据提示修改秘钥的权限就OK了。
#秘钥读写权限修改,如果没有mv /etc/ssh目录的内容,不会覆盖原始内容,可以不用执行 cd /etc/ssh ll //查看文件权限 chmod 600 ssh_host_*
五、结束语
在linux下进行程序安装时,一定要注意提示语,特别是警告部分信息。
出现错误,一定要学会找日志分析问题,大部分异常,都能通过分析错误日志信息找到解决的方向。
软件升级时,一定要进行配置文件的备份,防止出现意外。
安装程序时,不要在原生的配置文件上进行修改,先对原始配置文件复制备份
cp source.conf source.conf.default
后续补充,在之后的新机器的部署上,还是出现了问题。
主要集中在一下几个方面:
1、执行了rpm -e rpm -qa | grep openssh --nodeps卸载命令,导致yum命令不可用,影响非常严重
这里注意,一定要事先多开几个链接,以防一个连接断开后,还可以使用其他连接去拯救一下。
2、没有删除/etc/ssh里面的所有文件,而新编译安装ssh生成的sshd_config文件不会覆盖老的文件,而老文件中,默认开启的几项认证在新的ssh版本中,不支持或已经废弃,导致出现了问题。
3、忘了修改/etc/ssh下的秘钥的读写权限。
4、忘了关闭防火墙
5、出现登录不上的情况,一定要使用/var/log/message查看日志分析原因。