升级OpenSSH及其OpenSSL的正确姿势(修改版)
2019-04-02 11:48:27
基本照抄https://blog.51cto.com/techsnail/2138927 补充了一些细节修改了一点地方
OpenSSH升级思路
要升级openssh,我们需要先搞懂openssl是怎么安装的。
我使用的操作系统是centos 6.5的,我以安装openssh 7.9.p1为例。
从openssh官网下载openssh 7.9p1源码包,查看里面的INSTALL文件,里面有对它的依赖关系做说明。
openssh 7.9p1对下列软件的依赖是必选的:
openssh依赖的软件(必选)
备注
Zlib
要求1.1.4或1.2.1.2或更新的版本(1.2.x早期的版本有问题)。
libcrypto
(LibreSSL或OpenSSL)
OpenSSH依赖于libcrypto,而libcrypto可以由LibreSSL或OpenSSL提供。如果是使用的OpenSSL,要求OpenSSL的版本要大于等于0.9.8f并小于1.1.0。由于API不同,现在还不支持OpenSSL 1.1.x版本。
LibreSSL/OpenSSL应该编译成位置无关的库(position-independent library),比如使用-fPIC选项,否则OpenSSH会无法链接它;如果你必须使用一个非位置无关(non-position-independent)的libcrypto,那么你在编译OpenSSH时必须加上–without-pie选项。
openssh 7.9p1对下列软件的依赖是可选的:
openssh依赖的软件(可选)
备注
PAM
如果操作系统支持PAM(Pluggable Authentication Modules),那么OpenSSH就可以被编译成支持PAM功能的。大多数的Linux发行版,自然也包括RedHat/CentOS系统,都是支持PAM的。所以,如果我们要编译出一个可以替换操作系统自带OpenSSH的完整功能的OpenSSH,自然也是要支持PAM的。
其它软件:
NB
PRNGD
EGD
GNOME
S/Key
LibEdit
LDNS
Autoconf
Basic Security Module (BSM)
这些就不展开来说了。
基本上来说,要编译出一个功能类似于操作系统自带的OpenSSH软件,我们至少需要先准备好Zlib、OpenSSL(或LibreSSL)和PAM软件。下面,我们就逐个逐个地来进行安装。
安装Zlib
Zlib用于提供压缩和解压缩功能。操作系统已经自带了zlib,版本也符合要求。实际上,openssl和openssh都依赖于zlib。执行下面的命令,安装zlib开发包:
[root@centos6 ~]# yum install zlib-devel -y
安装PAM
PAM(Pluggable Authentication Modules,可插拔认证模块)用于提供安全控制。操作系统也已经自带了PAM,版本也是可以的。执行下面的命令,安装PAM开发包:
[root@centos6 ~]# yum install pam-devel -y
安装tcp_wrappers
tcp_wrappers是一种安全工具,通常,我们在/etc/hosts.allow或/etc/hosts.deny文件中配置的过滤规则就是使用的tcp_wrappers的功能了。openssh在编译时的确是可以选择支持tcp_wrappers的,但我不知道为什么它的安装要求里面没有体现。操作系统自带的tcp_wrappers的版本是可以的。执行下面的命令,安装tcp_wrappers开发包:
[root@centos6 ~]# yum install tcp_wrappers-devel -y
安装OpenSSL
由于openssh 7.9p1要求OpenSSL的版本大于等于0.9.8f并小于1.1.0,因此,当前(2017年6月)符合要求的最新OpenSSL版本为l-1.0.2r。
首先,从openssl官网下载源码包openssl-fips-2.0.16.tar.gz,将其安装到/opt/fips-2.0.16目录下。
编译安装FIPS模块:
[root@centos6 ~]# wget https://www.openssl.org/source/openssl-fips-2.0.16.tar.gz
[root@centos6 ~]# yum install gcc gcc+
[root@centos6 ~]# export FIPSDIR=/opt/fips-2.0.16
[root@centos6 ~]# tar -xvf openssl-fips-2.0.16.tar.gz
[root@centos6 ~]# cd openssl-fips-2.0.16
[root@centos6 openssl-fips-2.0.16]# ./config
[root@centos6 openssl-fips-2.0.16]# make
[root@centos6 openssl-fips-2.0.16]# make install
说明:
在编译前先设定环境变量FIPSDIR,这是用于指定FIPS模块的安装目录,这是fips软件特有的安装特性。软件编译时会检测该环境变量是否存在。若不指定,默认会安装在/usr/local/ssl/fips2.0目录。
从openssl官网下载源码包openssl-l-1.0.2r.tar.gz,将其安装到/opt/openssll-1.0.2r目录下。将openssl安装到专门的目录,这是为了避免对操作系统自带的openssl造成影响。
编译安装OpenSSL:
[root@centos6 ~]#wget https://www.openssl.org/source/openssl-1.0.2r.tar.gz
[root@centos6 ~]# tar -xvf openssl-l-1.0.2r.tar.gz
[root@centos6 ~]# cd openssl-l-1.0.2r
[root@centos6 openssl-l-1.0.2r]# ./config --prefix=/opt/openssll-1.0.2r --openssldir=/opt/openssll-1.0.2r/openssl fips --with-fipsdir=/opt/fips-2.0.16 zlib-dynamic shared -fPIC
[root@centos6 openssl-l-1.0.2r]# make depend
[root@centos6 openssl-l-1.0.2r]# make
[root@centos6 openssl-l-1.0.2r]# make test
[root@centos6 openssl-l-1.0.2r]# make install
下面是编译时使用到的选项:
–prefix:指定openssl的安装目录。按本例中的安装方式,安装完成后该目录下会包含bin(含二进制程序)、lib(含动态库文件)、include/openssl(含报头文件)及openssl(–openssldir选项指定的)这些子目录。
–openssldir:指定openssl文件的安装目录。按本例中的安装方式,安装完成后该目录下会包括certs(存放证书文件)、man(存放man文件)、misc(存放各种脚本)、private(存放私钥文件)这些子目录及openssl.cnf配置文件。
fips:集成FIPS模块。
–with-fipsdir:指向FIPS模块的安装目录位置。
zlib-dynamic:编译支持zlib压缩/解压缩,让openssl加载zlib动态库。该选项只在支持加载动态库的操作系统上才支持。这是默认选项。
shared:除了静态库以外,让openssl(在支持的平台上)也编译生成openssl动态库。
-fPIC:将openssl动态库编译成位置无关(position-independent)的代码。
安装完成后,将OpenSSL的库文件目录添加到/etc/ld.so.conf文件中,并加载到系统内存缓存中:
[root@centos6 openssl-l-1.0.2r]# echo ‘/opt/openssll-1.0.2r/lib’ >> /etc/ld.so.conf
[root@centos6 openssl-l-1.0.2r]#mv /usr/bin/openssl /usr/bin/openssl.bak
[root@centos6 openssl-l-1.0.2r]#mv /usr/include/openssl /usr/include/openssl.bak
[root@centos6 openssl-l-1.0.2r]#ln -s /opt/openssl1.0.2r/bin/openssl /usr/bin/openssl
[root@centos6 openssl-l-1.0.2r]#ln -s /opt/openssl1.0.2r/include/openssl/ /usr/include/openssl
[root@centos6 openssl-l-1.0.2r]#ldconfig -v
[root@centos6 openssl-l-1.0.2r]#openssl verssion -a
安装OpenSSH
从openssl官网下载源码包openssh-7.9p1.tar.gz,将其安装到/opt/openssh-7.9p1目录下。将openssh安装到专门的目录,这是为了避免与操作系统自带的openssh造成不必要的冲突,增加复杂度。
编译安装OpenSSH:
[root@centos6 ~]# wget https://cdn.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-7.9p1.tar.gz
[root@centos6 ~]# tar -xvf openssh-7.9p1.tar.gz
[root@centos6 ~]# cd openssh-7.9p1
[root@centos6 openssh-7.9p1]# ./configure --prefix=/opt/openssh-7.9p1 --with-ssl-dir=/opt/openssl1.0.2r --with-pam–with-tcp-wrappers
[root@centos6 openssh-7.9p1]# make
[root@centos6 openssh-7.9p1]# make install
下面是编译时使用到的选项:
–prefix:指定安装目录
–with-ssl-dir=DIR:指向LibreSSL/OpenSSL库的安装目录的所在路径。
–with-pam:启用PAM支持。根据OpenSSH的安装说明,如果在编译时启用了PAM,那么在安装完成后,也必须在sshd服务的配置文件sshd_config中启用它(使用UsePAM指令)。
根据OpenSSH的安装说明,如果有启用PAM,那么就需要手工安装一个给sshd程序使用的PAM配置文件,否则安装好OpenSSH后你可能会无法使用密码登录系统。在编译时,我使用 --with-pam 选项启用了对PAM的支持,但是,编译OpenSSH时并没有编译选项让你指定PAM配置文件的位置,那么我们要怎么提供这个配置文件呢?
事实上,OpenSSH有另外一个编译选项**–with-pam-service=_name_可以指定PAM服务名,它的默认值是sshd。而操作系统自带的PAM软件默认将所有PAM配置文件都放置在/etc/pam.d目录下。结合这两个信息,就可确定OpenSSH的PAM配置文件应为/etc/pam.d/sshd**文件。而这个文件原来就有了,所以我们不用额外手工创建一个。
设置PATH路径:
[root@centos6 ~]#mv /usr/bin/ssh-agent /usr/bin/ssh-agent.bak
[root@centos6 ~]#mv /usr/bin/ssh-keyscan /usr/bin/ssh-keyscan.bak
[root@centos6 ~]#mv /usr/bin/ssh-add /usr/bin/ssh-add.bak
[root@centos6 ~]#mv /usr/bin/ssh-keygen /usr/bin/ssh-keygen.bak
[root@centos6 ~]#mv /usr/sbin/sshd /usr/sbin/sshd.bak
[root@centos6 ~]#ln -s /opt/openssh7.9p1/bin/ssh-agent /usr/bin/ssh-agent
[root@centos6 ~]#ln -s /opt/openssh7.9p1/bin/ssh-keyscan /usr/bin/ssh-keyscan
[root@centos6 ~]#ln -s /opt/openssh7.9p1/bin/ssh-add /usr/bin/ssh-add
[root@centos6 ~]#ln -s /opt/openssh7.9p1/bin/ssh-keygen /usr/bin/ssh-keygen
[root@centos6 ~]#ln -s /opt/openssh7.9p1/sbin/sshd /usr/sbin/sshd
此时,使用ssh -V命令就可以看到新版本号了:
[root@centos6 ~]# ssh -V
OpenSSH_7.9p1, OpenSSL 1.0.2r-fips 26 Feb 2019
[root@centos6 ~]# sshd -V
unknown option – V
OpenSSH_7.9p1, OpenSSL 1.0.2r-fips 26 Feb 2019
usage: sshd [-46DdeiqTt] [-C connection_spec] [-c host_cert_file]
[-Elog_file] [-f config_file] [-g login_grace_time]
[-hhost_key_file] [-o option] [-p port] [-u len]
配置OpenSSH
前面已经安装好了openssh,但是我们还需要配置它,以保证sshd服务可以启起来。
我们可以先看一下原有的sshd服务(属于openssh-server软件包)都有哪些配置文件:
[root@centos6 ~]# rpm -ql openssh-server | grep -i --color etc
/etc/pam.d/ssh-keycat
/etc/pam.d/sshd
/etc/rc.d/init.d/sshd
/etc/ssh/sshd_config
/etc/sysconfig/sshd
[root@centos6 ~]#mv /etc/ssh/sshd_config /etc/ssh/sshd_config.bak
[root@centos6 ~]#ln -s /opt/openssh7.9p1/etc/sshd_config /etc/ssh/sshd_config
可以看到,sshd服务的配置文件为/etc/ssh/sshd_config,它的pam配置文件为/etc/pam.d/sshd和/etc/pam.d/ssh-keycat,启动脚本文件为/etc/rc.d/init.d/sshd,启动脚本里面有引用到文件/etc/sysconfig/sshd。
参照系统原有的配置文件修改我们软件的sshd_config配置文件,这是sshd服务的配置文件(红色字体的为新增或修改的部分):
[root@centos6 ~]# vim /opt/openssh7.9p1/etc/sshd_config
Protocol 2
SyslogFacility AUTHPRIV
PermitRootLogin yes
AuthorizedKeysFile .ssh/authorized_keys
PasswordAuthentication yes
ChallengeResponseAuthentication no
#GSSAPIAuthentication yes //该选项目前还不支持
#GSSAPICleanupCredentials yes //该选项目前还不支持
UsePAM yes
AcceptEnv LANG LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_MESSAGES
AcceptEnv LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT
AcceptEnv LC_IDENTIFICATION LC_ALL LANGUAGE
AcceptEnv XMODIFIERS
X11Forwarding yes
Subsystem sftp /opt/openssh7.9p1/libexec/sftp-server
注意,UsePAM一定要启用,OpenSSH的安装说明里有提到,如果编译时启用了PAM支持,那么就必须在sshd_config文件中启用它。
拷贝系统原有的配置文件/etc/sysconfig/sshd到我们软件下面,这个配置文件用于设置启动sshd服务所需的环境变量,在sshd服务的启动脚本里有调用到该配置文件:
[root@centos6 ~]# cp -a /etc/sysconfig/sshd /opt/openssh7.9p1/etc/sshd
接下来要修改sshd服务的启动脚本/etc/rc.d/init.d/sshd。先将启动脚本备份一份为sshd.old,并添加至chkconfig管理:
[root@centos6 ~]# cp /etc/rc.d/init.d/sshd /etc/rc.d/init.d/sshd.bak
[root@centos6 ~]# chkconfig --add sshd.bak
再根据我们的OpenSSH的安装路径,来修改原有的启动脚本(红色字体为有新增或修改的部分):
[root@centos6 ~]# vim /etc/rc.d/init.d/sshd
### BEGIN INIT INFO
# Provides: sshd
# Required-Start: $local_fs $network $syslog
# Required-Stop: $local_fs $syslog
# Should-Start: $syslog
# Should-Stop: $network $syslog
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Start up the OpenSSH server daemon
# Description: SSH is a protocol for secure remote shell access.
# This service starts up the OpenSSH server daemon.
### END INIT INFO
. /etc/rc.d/init.d/functions
[ -f /opt/openssh7.9p1/etc/sshd ] && . /opt/openssh7.9p1/etc/sshd
RETVAL=0
prog=“sshd”
lockfile=/var/lock/subsys/$prog
KEYGEN=/opt/openssh7.9p1/bin/ssh-keygen
SSHD=/opt/openssh7.9p1/sbin/sshd
RSA1_KEY=/etc/ssh/ssh_host_key #和老版本的公用 否则会报错
RSA_KEY=/etc/ssh_host_rsa_key #生成 SSH2 RSA 主机键: [失败]
DSA_KEY=/etc/ssh_host_dsa_key
PID_FILE=/var/run/sshd.pid # PID文件的所在路径,这个变量的值不要改
…
[ -x $SSHD ] || exit 5
[ -f /opt/openssh7.9p1/etc/sshd_config ] || exit 6
# Create keys if necessary
if [ “x${AUTOCREATE_SERVER_KEYS}” != xNO ]; then
do_rsa_keygen
if [ “x${AUTOCREATE_SERVER_KEYS}” != xRSAONLY ]; then
do_rsa1_keygen #我没有注释
do_dsa_keygen
由于OpenSSH依赖的OpenSSL已不支持rsa1,所以我将启动脚本中生成rsa1秘钥的指令注释掉了。
我这里没有注释,从启动报错来看支持rsa,不打开都启动不了
接下来,关键的一步来了,我们要关闭旧的sshd服务,启动新的sshd服务。这个操作如果失败了,不会导致现有的ssh远程连接断开。所以我们可以先关闭旧的sshd程序,再启动新的sshd程序:
[root@centos6 ~]# service sshd.bak stop
[root@centos6 ~]# service sshd start
如果新的sshd服务启动成功了,我们可以先简单测试下,比如,看看普通用户和root用户是否能正常通过ssh登录。如果没有没有问题,我们可以在测测其它的,比如scp、sftp是否正常等。当然,如果有条件的话,可以使用漏洞扫描工具扫一下,看看有没有什么我们没有注意到的地方。
参考https://blog.51cto.com/techsnail/2138927
评论(0)