客戶linux主機ssh存在高危漏洞,須要進行升級修復。html
linux聯網後,直接命令行:linux
[root@gw ~]# yum update openssl -y
此命令只是小版本的升級,好比將openssl從1.0.1e-43版本升級到1.0.1e-57版本,但好多時候咱們須要升級的是大版本,而不是這種小的修復。git
yum remove openssl命令執行時,能夠看到,很是很是多的軟件是依賴於openssl軟件。openssl是一個很是基礎的軟件。編譯安裝一個新版本的openssl覆蓋掉操做系統自帶的openssl。這就會致使那些依賴於openssl的軟件的openssl相關的功能變得不可用。shell
ssh命令是openssh軟件的一部分。由於上面提出的現象咱們不直接升級操做系統的openssl,可是咱們能夠另外編譯一個openssl,放到單獨的應用目錄中,與操做系統的openssl互不影響。再基於新編譯出來的openssl,將新的openssh軟件編譯出來。 而操做系統的openssh是能夠被替換的。若是你嘗試執行 yum remove openssh* 命令就能夠看到,沒有其它軟件依賴於openssh。此外,openssh軟件提供了sshd服務。因此,咱們只要還要配置並搭建好sshd服務,就能夠替代操做系統自帶的openssh了。vim
接下來咱們分析,如何升級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)bash
1,提早檢查必須安裝的(Zlib、libcrypto或者(LibreSSL或OpenSSL))session
2,還有一些是可選的安裝,例如PAM軟件等app
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
通常出現這個-bash: make: command not found提示,是由於安裝系統的時候使用的是最小化mini安裝,系統沒有安裝make、vim等經常使用命令,直接yum安裝下便可。 yum -y install gcc automake autoconf libtool make
因爲OpenSSH 7.9p1要求OpenSSL的版本> = 1.0.1 <1.1.0,所以,當前符合要求的最新OpenSSL版本爲1.0.2l 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):
mkdir /opt/fips-2.0
# 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.2l.tar.gz,將其安裝到/opt/openssl1.0.2l_2019目錄下。將openssl安裝到專門的目錄,這是爲了不對操做系統自帶的openssl形成影響。
編譯安裝OpenSSL
mkdir /opt/openssl1.0.2l_2019
# tar -xvf openssl-1.0.2l.tar.gz # cd openssl-1.0.2l # ./config --prefix=/opt/openssl1.0.2l_2019 --openssldir=/opt/openssl1.0.2l_2019/openssl fips --with-fipsdir=/opt/fips-2.0 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.2l_2019/lib' >> /etc/ld.so.conf # ldconfig
從openssl官網下載源碼包openssh-7.9p1.tar.gz,將其安裝到/opt/openssh7.9.p1_2019目錄下。將openssh安裝到專門的目錄,這是爲了不與操做系統自帶的openssh形成沒必要要的衝突。
編譯安裝OpenSSH:
mkdir /opt/openssh7.9.p1_2019
# tar -xvf openssh-7.9p1.tar.gz # cd openssh-7.9p1 # ./configure --prefix=/opt/openssh7.9.p1_2019 --with-ssl-dir=/opt/openssl1.0.2l_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的安裝路徑,來修改原有的啓動腳本(紅色字體爲有新增或修改的部分-注:linux7以後沒有這個文件,能夠本身新建一個啓動文件,手動添加這個服務,開機自啓動等啓動sshd):
修改配置文件權限 chmod u+x /etc/rc.d/init.d/sshdnew 添加sshd服務 chkconfig --add sshdnew
設置開機自啓動
chkconfig sshdnew on 驗證開機啓動 chkconfig --list|grep sshdnew service sshdnew start systemctl is-active sshdnew
vim /etc/rc.d/init.d/sshd #!/bin/bash # # sshd Start up the OpenSSH server daemon # # chkconfig: 2345 55 25 # description: SSH is a protocol for secure remote shell access. \ # This service starts up the OpenSSH server daemon. # # processname: sshd # config: /etc/ssh/ssh_host_key # config: /etc/ssh/ssh_host_key.pub # config: /etc/ssh/ssh_random_seed # config: /etc/ssh/sshd_config # pidfile: /var/run/sshd.pid ### 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 # source function library . /etc/rc.d/init.d/functions # pull in sysconfig settings [ -f /opt/openssh7.9.p1_2019/etc/sshd ] && . /opt/openssh7.9.p1_2019/etc/sshd RETVAL=0 prog="sshd" lockfile=/var/lock/subsys/$prog # Some functions to make the below more readable KEYGEN=/opt/openssh7.9.p1_2019/bin/ssh-keygen SSHD=/opt/openssh7.9.p1_2019/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 ]; 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_rsa1_keygen # 註釋掉這條語句 do_rsa_keygen do_dsa_keygen 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
root輸入密碼登陸拒毫不成功能夠:
在$SSHD $OPTIONS && success || failure這句話前面加一句: OPTIONS="-f /etc/ssh/sshd_config" 配置以下: echo -n $"Starting $prog:" OPTIONS="-f /opt/ssh7.9/etc/sshd_config" --同上目錄/opt/openssh7.9.p1_2019/etc/sshd_config
$SSHD $OPTIONS && success || failure 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軟件在功能特性上只是儘量地接近原有的,安全性和性能可能也是有差別。
複用了操做系統原有的sshd服務的配置文件和啓動腳本,這可能沒法充分利用新版本openssh的特性。openssl和openssh原本也是挺複雜的東西,一時半會可能也很難徹底弄明白。
這種升級方式,應該會比強制升級openssl和openssh的方式好不少。
參考https://blog.51cto.com/techsnail/2138927,獨指蝸牛 只作平常積累,不作商業用途,侵權即刪。