标签:库文件 else $1 还需 other 指令 create end star
客户linux主机ssh存在高危漏洞,需要进行升级修复。
linux联网后,直接命令行:
[root@gw ~]# yum update openssl -y
此命令只是小版本的升级,比如将openssl从1.0.1e-43版本升级到1.0.1e-57版本,但好多时候我们需要升级的是大版本,而不是这种小的修复。
yum remove openssl命令执行时,可以看到,非常非常多的软件是依赖于openssl软件。openssl是一个非常基础的软件。编译安装一个新版本的openssl覆盖掉操作系统自带的openssl。这就会导致那些依赖于openssl的软件的openssl相关的功能变得不可用。
ssh命令是openssh软件的一部分。因为上面提出的现象我们不直接升级操作系统的openssl,但是我们可以另外编译一个openssl,放到单独的应用目录中,与操作系统的openssl互不影响。再基于新编译出来的openssl,将新的openssh软件编译出来。 而操作系统的openssh是可以被替换的。如果你尝试执行 yum remove openssh* 命令就可以看到,没有其它软件依赖于openssh。此外,openssh软件提供了sshd服务。所以,我们只要还要配置并搭建好sshd服务,就可以替代操作系统自带的openssh了。
接下来我们分析,如何升级openssh及其所依赖的openssl。
从openssh官网下载openssh 7.9.p1源码包,查看里面的INSTALL文件,里面有对它的依赖关系做说明 可以依据blfs下载(http://www.linuxfromscratch.org/blfs/news.html)
openssh7.9p1下载安装说明,可参考解压后的install文件(http://www.linuxfromscratch.org/blfs/view/8.4/postlfs/openssh.html)
1,提前检查必须安装的(Zlib、libcrypto或者(LibreSSL或OpenSSL))
2,还有一些是可选的安装,例如PAM软件等
1. Prerequisites ---------------- A C compiler. Any C89 or better compiler should work. Where supported, configure will attempt to enable the compiler‘s run-time integrity checking options. Some notes about specific compilers: - clang: -ftrapv and -sanitize=integer require the compiler-rt runtime (CC=clang LDFLAGS=--rtlib=compiler-rt ./configure) You will need working installations of Zlib and libcrypto (LibreSSL / OpenSSL) Zlib 1.1.4 or 1.2.1.2 or greater (earlier 1.2.x versions have problems): http://www.gzip.org/zlib/ libcrypto (LibreSSL or OpenSSL >= 1.0.1 < 1.1.0) LibreSSL http://www.libressl.org/ ; or OpenSSL http://www.openssl.org/ LibreSSL/OpenSSL should be compiled as a position-independent library (i.e. with -fPIC) otherwise OpenSSH will not be able to link with it. If you must use a non-position-independent libcrypto, then you may need to configure OpenSSH --without-pie. Note that because of API changes, OpenSSL 1.1.x is not currently supported. The remaining items are optional. NB. If you operating system supports /dev/random, you should configure libcrypto (LibreSSL/OpenSSL) to use it. OpenSSH relies on libcrypto‘s direct support of /dev/random, or failing that, either prngd or egd PRNGD: If your system lacks kernel-based random collection, the use of Lutz Jaenicke‘s PRNGd is recommended. http://prngd.sourceforge.net/ EGD: If the kernel lacks /dev/random the Entropy Gathering Daemon (EGD) is supported only if libcrypto supports it. http://egd.sourceforge.net/ PAM: OpenSSH can utilise Pluggable Authentication Modules (PAM) if your system supports it. PAM is standard most Linux distributions, Solaris, HP-UX 11, AIX >= 5.2, FreeBSD and NetBSD. Information about the various PAM implementations are available: Solaris PAM: http://www.sun.com/software/solaris/pam/ Linux PAM: http://www.kernel.org/pub/linux/libs/pam/ OpenPAM: http://www.openpam.org/ If you wish to build the GNOME passphrase requester, you will need the GNOME libraries and headers. GNOME: http://www.gnome.org/ Alternatively, Jim Knoble <jmknoble@pobox.com> has written an excellent X11 passphrase requester. This is maintained separately at: http://www.jmknoble.net/software/x11-ssh-askpass/ LibEdit: sftp supports command-line editing via NetBSD‘s libedit. If your platform has it available natively you can use that, alternatively you might try these multi-platform ports: http://www.thrysoee.dk/editline/ http://sourceforge.net/projects/libedit/ LDNS: LDNS is a DNS BSD-licensed resolver library which supports DNSSEC. http://nlnetlabs.nl/projects/ldns/ Autoconf: If you modify configure.ac or configure doesn‘t exist (eg if you checked the code out of git yourself) then you will need autoconf-2.69 to rebuild the automatically generated files by running "autoreconf". Earlier versions may also work but this is not guaranteed. http://www.gnu.org/software/autoconf/ Basic Security Module (BSM): Native BSM support is known to exist in Solaris from at least 2.5.1, FreeBSD 6.1 and OS X. Alternatively, you may use the OpenBSM implementation (http://www.openbsm.org). makedepend: https://www.x.org/archive/individual/util/ If you are making significant changes to the code you may need to rebuild the dependency (.depend) file using "make depend", which requires the "makedepend" tool from the X11 distribution.
Zlib用于压缩和解压缩的功能。操作系统已经自带了zlib,可以查看是否符合要求。实际上,openssl和openssh都依赖于zlib。执行下面的命令,安装zlib开发包:
rpm -qa|grep zlib
yum -y install zlib-devel
PAM(Pluggable Authentication Modules,可插拔认证模块)用于提供安全控制。操作系统也已经自带了PAM,版本也是可以的。执行下面的命令,安装PAM开发包:
rpm -qa|grep pam yum -y install pam-devel
tcp_wrappers是一种安全工具,通常,我们在/etc/hosts.allow或/etc/hosts.deny文件中配置的过滤规则就是使用的tcp_wrappers的功能了。openssh在编译时的确是可以选择支持tcp_wrappers的。执行下面的命令,安装tcp_wrappers开发包:
rpm -qa|grep tcp_wrappers yum install tcp_wrappers-devel -y
由于OpenSSH 7.9p1要求OpenSSL的版本> = 1.0.1 <1.1.0,因此,当前符合要求的最新OpenSSL版本为1.0.2q https://www.openssl.org/source/old/1.0.2/。
首先,从openssl官网下载源码包openssl-fips-2.0.16.tar.gz(https://www.openssl.org/source/old/fips/)将其安装到/opt/fips-2.0目录下。
编译安装FIPS宏(https://bbs.csdn.net/wap/topics/390830236):
# export FIPSDIR=/opt/fips-2.0 --指定另外的安装目录,默认会安装在/usr/local/ssl/fips2.0目录 # tar -xvf openssl-fips-2.0.16.tar.gz # cd openssl-fips-2.0.16 # ./config # make # make install
从openssl官网下载源码包openssl-1.0.2q.tar.gz,将其安装到/opt/openssl1.0.q_2019目录下。将openssl安装到专门的目录,这是为了避免对操作系统自带的openssl造成影响。
编译安装OpenSSL
# tar -xvf openssl-1.0.2q.tar.gz # cd openssl-1.0.2q # ./config --prefix=/opt/openssl1.0.2q_2019 --openssldir=/opt/openssl1.0.2q_2019/openssl fips --with-fipsdir=/opt/fips-2.0.16 zlib-dynamic shared -fPIC # make depend # make # make test # 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文件中,并加载到系统内存缓存中:
# echo ‘/opt/openssl1.0.2q_2019/lib‘ >> /etc/ld.so.conf # ldconfig
从openssl官网下载源码包openssh-7.9p1.tar.gz,将其安装到/opt/openssh7.9.p1_2019目录下。将openssh安装到专门的目录,这是为了避免与操作系统自带的openssh造成不必要的冲突。
编译安装OpenSSH:
# tar -xvf openssh-7.9p1.tar.gz # cd openssh-7.9p1 # ./configure --prefix=/opt/openssh7.9.p1_2019 --with-ssl-dir=/opt/openssl1.0.2q_2019 --with-pam --with-tcp-wrappers # make # 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路径:
# echo ‘export PATH=/opt/openssh7.9.p1_2019/bin:/opt/openssh7.9.p1_2019/sbin:$PATH‘ >> /etc/profile.d/path.sh # . /etc/profile.d/path.sh
此时,使用ssh -V命令就可以看到新版本号了
ssh -V
前面已经安装好了openssh,但是我们还需要配置它,以保证sshd服务可以启起来。我们可以先看一下原有的sshd服务(属于openssh-server软件包)都有哪些配置文件:
# 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
可以看到,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服务的配置文件(红色字体的为新增或修改的部分):
# vim /opt/openssh7.9.p1_2019/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.9.p1_2019/libexec/sftp-server
注意,UsePAM一定要启用,OpenSSH的安装说明里有提到,如果编译时启用了PAM支持,那么就必须在sshd_config文件中启用它。
拷贝系统原有的配置文件/etc/sysconfig/sshd到我们软件下面,这个配置文件用于设置启动sshd服务所需的环境变量,在sshd服务的启动脚本里有调用到该配置文件:
# cp -a /etc/sysconfig/sshd /opt/openssh7.9.p1_2019/etc/sshd
接下来要修改sshd服务的启动脚本/etc/rc.d/init.d/sshd。先将启动脚本备份一份为sshd.old,并添加至chkconfig管理:
# cp /etc/rc.d/init.d/sshd /etc/rc.d/init.d/sshd.old # chkconfig --add sshd.old
再根据我们的OpenSSH的安装路径,来修改原有的启动脚本(红色字体为有新增或修改的部分):
[root@gw ~]# 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.9.p1_2019/etc/sshd ] && . /opt/openssh7.9.p1_2019/etc/sshd RETVAL=0 prog="sshd" lockfile=/var/lock/subsys/$prog KEYGEN=/opt/openssh7.5.p1_20170617/bin/ssh-keygen SSHD=/opt/openssh7.5.p1_20170617/sbin/sshd RSA1_KEY=/etc/ssh/ssh_host_key RSA_KEY=/opt/openssh7.9.p1_2019/etc/ssh_host_rsa_key DSA_KEY=/opt/openssh7.9.p1_2019/etc/ssh_host_dsa_key PID_FILE=/var/run/sshd.pid # PID文件的所在路径,这个变量的值不要改 runlevel=$(set -- $(runlevel); eval "echo \$$#" ) fips_enabled() { if [ -r /proc/sys/crypto/fips_enabled ]; then cat /proc/sys/crypto/fips_enabled else echo 0 fi } do_rsa1_keygen() { if [ ! -s $RSA1_KEY -a `fips_enabled` -eq 0 ]; then echo -n $"Generating SSH1 RSA host key: " rm -f $RSA1_KEY if test ! -f $RSA1_KEY && $KEYGEN -q -t rsa1 -f $RSA1_KEY -C ‘‘ -N ‘‘ >&/dev/null; then chmod 600 $RSA1_KEY chmod 644 $RSA1_KEY.pub if [ -x /sbin/restorecon ]; then /sbin/restorecon $RSA1_KEY.pub fi success $"RSA1 key generation" echo else failure $"RSA1 key generation" echo exit 1 fi fi } do_rsa_keygen() { if [ ! -s $RSA_KEY ]; then echo -n $"Generating SSH2 RSA host key: " rm -f $RSA_KEY if test ! -f $RSA_KEY && $KEYGEN -q -t rsa -f $RSA_KEY -C ‘‘ -N ‘‘ >&/dev/null; then chmod 600 $RSA_KEY chmod 644 $RSA_KEY.pub if [ -x /sbin/restorecon ]; then /sbin/restorecon $RSA_KEY.pub fi success $"RSA key generation" echo else failure $"RSA key generation" echo exit 1 fi fi } do_dsa_keygen() { if [ ! -s $DSA_KEY -a `fips_enabled` -eq 0 ]; then echo -n $"Generating SSH2 DSA host key: " rm -f $DSA_KEY if test ! -f $DSA_KEY && $KEYGEN -q -t dsa -f $DSA_KEY -C ‘‘ -N ‘‘ >&/dev/null; then chmod 600 $DSA_KEY chmod 644 $DSA_KEY.pub if [ -x /sbin/restorecon ]; then /sbin/restorecon $DSA_KEY.pub fi success $"DSA key generation" echo else failure $"DSA key generation" echo exit 1 fi fi } do_restart_sanity_check() { $SSHD -t RETVAL=$? if [ $RETVAL -ne 0 ]; then failure $"Configuration file or keys are invalid" echo fi } start() { [ -x $SSHD ] || exit 5 [ -f /opt/openssh7.9.p1_2019/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 fi fi echo -n $"Starting $prog: " $SSHD $OPTIONS && success || failure RETVAL=$? [ $RETVAL -eq 0 ] && touch $lockfile echo return $RETVAL } stop() { echo -n $"Stopping $prog: " killproc -p $PID_FILE $SSHD RETVAL=$? # if we are in halt or reboot runlevel kill all running sessions # so the TCP connections are closed cleanly if [ "x$runlevel" = x0 -o "x$runlevel" = x6 ] ; then trap ‘‘ TERM killall $prog 2>/dev/null trap TERM fi [ $RETVAL -eq 0 ] && rm -f $lockfile echo } reload() { echo -n $"Reloading $prog: " killproc -p $PID_FILE $SSHD -HUP RETVAL=$? echo } restart() { stop start } force_reload() { restart } rh_status() { status -p $PID_FILE openssh-daemon } rh_status_q() { rh_status >/dev/null 2>&1 } case "$1" in start) rh_status_q && exit 0 start ;; stop) if ! rh_status_q; then rm -f $lockfile exit 0 fi stop ;; restart) restart ;; reload) rh_status_q || exit 7 reload ;; force-reload) force_reload ;; condrestart|try-restart) rh_status_q || exit 0 if [ -f $lockfile ] ; then do_restart_sanity_check if [ $RETVAL -eq 0 ] ; then stop # avoid race sleep 3 start else RETVAL=6 fi fi ;; status) rh_status RETVAL=$? if [ $RETVAL -eq 3 -a -f $lockfile ] ; then RETVAL=2 fi ;; *) echo $"Usage: $0 {start|stop|restart|reload|force-reload|condrestart|try-restart|status}" RETVAL=2 esac exit $RETVAL
|
由于OpenSSH依赖的OpenSSL已不支持rsa1,所以我将启动脚本中生成rsa1秘钥的指令注释掉了。
接下来,关键的一步来了,我们要关闭旧的sshd服务,启动新的sshd服务。这个操作如果失败了,不会导致现有的ssh远程连接断开。所以我们可以先关闭旧的sshd程序,再启动新的sshd程序:
# service sshd.old stop
# service sshd start
如果新的sshd服务启动成功了,我们可以先简单测试下,比如,看看普通用户和root用户是否能正常通过ssh登录。如果没有没有问题,我们可以在测测其它的,比如scp、sftp是否正常等。当然,如果有条件的话,可以使用漏洞扫描工具扫一下,看看有没有什么我们没有注意到的地方。
最后,就可以删除掉旧sshd服务的启动脚本了,以免冲突:
# rm -f /etc/init.d/sshd.old
总结
现在,所有操作都完成了。总的来说,整个升级过程应该还是挺明了的,不会有太多把系统搞挂的风险,可重复操作性强,重复升级也没有问题,也不会影响系统中的其它软件。
当然,也有可以继续完善的地方,可能有两个方面吧。
一是,openssl和openssh的编译选项基本来说我也只是使用了必要的选项,由于不知道操作系统自带的openssl和openssh原本的编译选项是什么,所以我们编译出来的openssl和openssh软件在功能特性上只是尽可能地接近原有的,安全性和性能可能也是有差异的。
二是,我复用了操作系统原有的sshd服务的配置文件和启动脚本,这可能无法充分利用新版本openssh的特性。openssl和openssh本来也是挺复杂的东西,一时半会可能也很难完全弄明白。
但是,不管怎么说,这种升级方式,应该会比强制升级openssl和openssh的方式好很多。
标签:库文件 else $1 还需 other 指令 create end star
原文地址:https://www.cnblogs.com/ocp-100/p/10677387.html