Linux - 升级OpenSSH 以及 OpenSSL的思路

背景

  1. 安全审计问题(更新版本来升级漏洞),必须升级系统SSH服务版本。
  2. 个人爱好。

问题

  1. 查看最新版本的OpenSSH软件包里的说明文件(INSTALL),它告诉我们需要依赖其他软件包,例如OpenSSL,PAM,ZLIB等。
  2. 如果升级小版本也可以修复主要漏洞(特别的人对“大版本漏洞少”存在误解):yum update openssl -y
  3. 操作系统本身有很多应用依赖于当前的OpenSSL编译的,如果你升级大版本,可能很多程序不能用,跨大版本是不可行的。
  4. 如果你需要升级大版本,请升级操作系统版本。
  5. 单独安装一个OpenSSL,然后依赖此来升级SSH服务。

准备信息

  1. 下载安装包:openssh-7.9p1.tar.gz
  2. 依赖Zlib Zlib 1.1.4 or 1.2.1.2 or greater (earlier 1.2.x versions have problems):

    DownLoad OldDownLoad New

  3. 依赖libcrypto (LibreSSL or OpenSSL >= 1.0.1 < 1.1.0)

    DownLoad LibreSSL or DownLoad OpenSSL

  4. 依赖FIPS

    DownLoad FIPS: openssl-fips-2.0.16.tar.gz

注意:1.0.x版本最新的是openssl-1.0.2q.tar.gz

注意:说明文档里面说不支持1.1.x版本的OpenSSL

补充:openssl与openssl-fips有什么区别

联邦信息处理标准(Federal Information Processing Standards,FIPS)是一套描述文件处理、加密算法和其他信息技术标准(在非军用政府机构和与这些机构合作的政府承包商和供应商中应用的标准)的标准。

安装zlib

安装PAM

PAM(Pluggable Authentication Modules,可插拔认证模块)用于提供安全控制。

# 操作系统也已经自带了PAM,版本满足要求
pam-1.1.8-22.el7.x86_64
# 安装开发包
yum install pam-devel -y

安装OpenSSL

编译安装FIPS模块

export FIPSDIR=/opt/fips-2.0.16
tar -xvf openssl-fips-2.0.16.tar.gz
cd openssl-fips-2.0.16
./config
make
make install

注意:在编译前先设定环境变量FIPSDIR,这是用于指定FIPS模块的安装目录,这是fips软件特有的安装特性。软件编译时会检测该环境变量是否存在。若不指定,默认会安装在/usr/local/ssl/fips2.0目录。

编译安装OpenSSL

tar zxvf openssl-1.0.2q.tar.gz
cd openssl-1.0.2q
mkdir /opt/openssl-1.0.2q_20190131
./config --prefix=/opt/openssl-1.0.2q_20190131 --openssldir=/opt/openssl-1.0.2q_20190131/openssl fips --with-fipsdir=/opt/fips-2.0.16 zlib-dynamic shared -fPIC
make depend
make
make test
make install
/opt/openssl-1.0.2q_20190131/bin/openssl version -a

# 说明如下
--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/openssl-1.0.2q_20190131/lib' >> /etc/ld.so.conf
ldconfig

安装OpenSSH

编译安装

从openssl官网下载源码包openssh-7.9p1.tar.gz,将其安装到/opt/openssh-7.9.p1_20190131目录下。

将openssh安装到专门的目录,这是为了避免与操作系统自带的openssh造成不必要的冲突,增加复杂度。

[root@node1 opt]# cd /opt
[root@node1 opt]# tar -xvf openssh-7.9p1.tar.gz
[root@node1 opt]# cd openssh-7.9p1/
[root@node1 openssh-7.9p1]# ./configure --prefix=/opt/openssh-7.9.p1_20190131 --with-ssl-dir=/opt/openssl-1.0.2q_20190131 --with-pam --with-tcp-wrappers
[root@node1 openssh-7.9p1]# make
[root@node1 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@node1 profile.d]# echo 'export PATH=/opt/openssh-7.9.p1_20190131/bin:/opt/openssh-7.9.p1_20190131/sbin:$PATH' >> /etc/profile.d/path.sh
# 加载PATH
[root@node1 profile.d]# . /etc/profile.d/path.sh
# 验证版本
[root@node1 profile.d]# ssh -V
OpenSSH_7.9p1, OpenSSL 1.0.2q-fips  20 Nov 2018

修改配置

# 可以先看一下原有的sshd服务(属于openssh-server软件包)都有哪些配置文件:
rpm -ql openssh-server | grep -i --color etc
/etc/pam.d/sshd       # pam配置文件
/etc/ssh/sshd_config  # sshd服务的配置文件
/etc/sysconfig/sshd   # 启动脚本文件?

# 参照系统原有的配置文件修改我们编译出来的的sshd_config配置文件:
vi /opt/openssh-7.9.p1_20190131/etc/sshd_config
# 放开注释或添加如下内容
PermitRootLogin yes
PubkeyAuthentication yes
PasswordAuthentication yes

开机启动

# 查看当前系统自启动服务列表
[root@node1 init.d]# systemctl list-unit-files |grep sshd
anaconda-sshd.service                         static
sshd-keygen.service                           static
sshd.service                                  enabled
sshd@.service                                 static
sshd.socket                                   disabled
[root@node1 init.d]#

# 关闭当前系统上的老版本SSH服务
systemctl disable sshd.service

# 创建新服务的配置文件:/usr/lib/systemd/system/ssh.service,内容如下
[Unit]
Description=OpenSSH daemon
After=network.target sshd-keygen.service

[Service]
Type=sample # 这里需要设置成sample或者删除这一项。
ExecStart=/opt/openssh7.9.p1_20190131/sbin/sshd

[Install]
WantedBy=multi-user.target

# 添加到系统自启动列表里面
systemctl daemon-reload
systemctl enable ssh.service

# 从自启动列表中删除
systemctl disable ssh.service

# 启动 关闭 重启服务
systemctl stop ssh
systemctl start ssh
systemctl restart ssh

# 注意,连接的时候需要关闭SeLinux,关于如何添加Selinux策略待学习。
setenforce 0