暂无图片
暂无图片
1
暂无图片
暂无图片
暂无图片

OpenSSH9.8p1 RPM包制作

watson 2024-07-21
756

写本篇目的

近期,业务环境中的OpenSSH暴露了一个远程代码执行漏洞(CVE-2024-6387,又被称为regreSSHion),影响版本8.5p1<=版本<9.8p1,该漏洞影响基于glibc的Linux系统上的OpenSSH Server。未经身份验证的攻击者可以通过恶意构造的SSH客户端请求,利用此漏洞在OpenSSH服务器上执行任意代码。该漏洞利用复杂但影响面很广,故本篇主要提供一种制作openssh RPM包的思路及方法,适用情况请自行测试。如需要基于openEuler 20.03的安装包请点击原文连接。

使用源码制作opensshRPM包

以编译制作openssh-9.8p1版本的RPM包为例

原理介绍

RPM打包的时候需要编译源码,需要把编译好的配置文件、二进制命令文件等放到合适的位置,还要根据需要对RPM的包进行测试,这些都需要先有一个“工作空间”。rpmbuild命令使用一套标准化的“工作空间”:

 $ rpmdev-setuptree

rpmdev-setuptree这个命令就是安装 rpmdevtools 带来的。可以看到运行了这个命令之后,在"/root"目录(非root用户为"/home/用户名"目录)下多了一个 rpmbuild 的文件夹,目录结构如下:

 $ tree rpmbuild rpmbuild ├── BUILD ├── RPMS ├── SOURCES ├── SPECS └── SRPMS

内容相关的说明如下:

目录宏代码名称功能
~/rpmbuild/BUILD%_builddir构建目录源码包被解压至此,并在该目录的子目录完成编译
~/rpmbuild/RPMS%_rpmdir标准 RPM 包目录生成/保存二进制 RPM 包
~/rpmbuild/SOURCES%_sourcedir源代码目录保存源码包(如 .tar 包)和所有 patch 补丁
~/rpmbuild/SPECS%_specdirSpec 文件目录保存 RPM 包配置(.spec)文件
~/rpmbuild/SRPMS%_srcrpmdir源代码 RPM 包目录生成/保存源码 RPM 包(SRPM)

SPECS 下是RPM包的配置文件,是RPM打包的“图纸”,这个文件会告诉rpmbuild命令如何去打包。“宏代码”这一列就可以在SPEC文件中用来代指所对应的目录,类似于编程语言中的宏或全局变量。

打包流程

打包的过程主要分为如下步骤:

  1. 把源代码放到%_sourcedir中。

  2. 进行编译,编译的过程是在%_builddir中完成的,一般情况下,源代码是压缩包格式,需要先进行解压。

  3. 进行“安装”,类似于预先组装软件包,把软件包应该包含的内容(比如二进制文件、配置文件、man文档等)复制到%buildrootdir中,并按照实际安装后的目录结构组装,比如二进制命令可能会放在/usr/bin下,那么就在%buildrootdir下也按照同样的目录结构放置。

  4. 做一些必要的配置,比如在实际安装前的准备,安装后的清理等等。这些都是通过配置在SPEC文件中来告诉rpmbuild命令。

  5. 检查软件是否正常运行。

  6. 生成的RPM包放置到%rpmdir,源码包放置到%srcrpmdir下。

在SPEC文件中,各个阶段说明如下:

阶段读取的目录写入的目录具体动作
%prep%_sourcedir%_builddir读取位于 %sourcedir 目录的源代码和 patch 。之后,解压源代码至%builddir 的子目录并应用所有 patch。
%build%_builddir%_builddir编译位于 %_builddir 构建目录下的文件。通过执行类似 ./configure && make的命令实现。
%install%_builddir%_buildrootdir读取位于 %builddir 构建目录下的文件并将其安装至 %buildrootdir 目录。这些文件就是用户安装 RPM 后,最终得到的文件。
%check%_builddir%_builddir检查软件是否正常运行。通过执行类似 make test 的命令实现。
bin%_buildrootdir%_rpmdir读取位于 %buildrootdir 最终安装目录下的文件,以便最终在 %rpmdir 目录下创建 RPM 包。在该目录下,不同架构的 RPM 包会分别保存至不同子目录, noarch 目录保存适用于所有架构的 RPM 包。这些 RPM 文件就是用户最终安装的 RPM 包。
src%_sourcedir%_srcrpmdir创建源码 RPM 包(简称 SRPM,以.src.rpm 作为后缀名),并保存至%_srcrpmdir 目录。SRPM 包通常用于审核和升级软件包。

打包选项

通过rpmbuild命令构建软件包。rpmbuild构建软件包一般可以通过构建SPEC文件、tar文件、source文件实现。

rpmbuild命令格式为:rpmbuild [option...]

rpmbuild常用打包选项如下:

option取值说明
-ba specfile通过specfile文件构建源码包和二进制包。
-bb specfile通过specfile文件构建二进制包。
-bs specfile通过specfile文件构建源码包

本地构建RPM操作步骤

用户可以直接使用DNF工具安装 rpmdevtools,其中包含 rpm-build 等命令以及相关依赖(例如make、gdb)。使用如下命令:

 dnf install rpmdevtools* -y

接下来以在openEuler 20.03 (LTS-SP4)版本的系统上本地构建openssh-9.8p1版本的RPM包为例进行演示。

构建工作空间

使用rpmdev-setuptree命令构建rpmbuild工作空间

 [root@localhost ~]# rpmdev-setuptree [root@localhost ~]# tree ~/rpmbuild/ /root/rpmbuild/ ├── BUILD ├── RPMS ├── SOURCES ├── SPECS └── SRPMS

安装依赖环境

 [root@localhost SPECS]# yum install gtk2-devel imake krb5-devel libXt-devel openssl-devel pam-devel

下载源码

直接下载官方最新的openssh版本源码,使用如下命令:

 [root@localhost ~]# cd ~/rpmbuild/SOURCES/ [root@localhost SOURCES]# wget https://cdn.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-9.8p1.tar.gz [root@localhost SOURCES]# wget https://src.fedoraproject.org/repo/pkgs/openssh/x11-ssh-askpass-1.2.4.1.tar.gz/8f2e41f3f7eaa8543a2440454637f3c3/x11-ssh-askpass-1.2.4.1.tar.gz

不下载x11-ssh-askpass包在构建时会报错error: Bad source: /root/rpmbuild/SOURCES/x11-ssh-askpass-1.2.4.1.tar.gz: No such file or directory

准备SPEC文件

~/rpmbuild/SPECS目录下准备spec文件,命令如下:

 #解压下班的openssh软件包源码,复制出官方提供的spec文件,rpm-build需要根据这个文件来制作rpm包 [root@localhost SOURCES]# tar -zxvf openssh-9.8p1.tar.gz [root@localhost SOURCES]# cp openssh-9.8p1/contrib/redhat/openssh.spec ../SPECS/

编辑SPEC文件

默认openssh源码中是没有ssh-copy-id相关参数的,如果直接编译安装,会发现安装后没有ssh-copy-id命令,因此如果需要用到该命令,需要修改编译参数控制文件openssh.spec

...... %install rm -rf $RPM_BUILD_ROOT mkdir -p -m755 $RPM_BUILD_ROOT%{_sysconfdir}/ssh mkdir -p -m755 $RPM_BUILD_ROOT%{_libexecdir}/openssh mkdir -p -m755 $RPM_BUILD_ROOT%{_var}/empty/sshd  make install DESTDIR=$RPM_BUILD_ROOT  install -d $RPM_BUILD_ROOT/etc/pam.d/ install -d $RPM_BUILD_ROOT/etc/rc.d/init.d install -d $RPM_BUILD_ROOT%{_libexecdir}/openssh install -m644 contrib/redhat/sshd.pam  $RPM_BUILD_ROOT/etc/pam.d/sshd install -m755 contrib/redhat/sshd.init $RPM_BUILD_ROOT/etc/rc.d/init.d/sshd #添加如下行内容,大约282行处 install -m755 contrib/ssh-copy-id $RPM_BUILD_ROOT/usr/bin/ssh-copy-id ......  %attr(0755,root,root) %{_bindir}/ssh-keygen #添加如下行内容,大约363行处 %attr(0755,root,root) %{_bindir}/ssh-copy-id

构建RPM包

构建源码、二进制和包含调试信息的软件包,在spec文件所在目录执行如下命令:

[root@localhost SPECS]# rpmbuild -ba openssh.spec

执行成功后,查看结果,使用如下命令:

 [root@localhost SPECS]# tree ~/rpmbuild/*RPMS /root/rpmbuild/RPMS └── x86_64    ├── openssh-9.8p1-1.x86_64.rpm    ├── openssh-askpass-9.8p1-1.x86_64.rpm    ├── openssh-askpass-gnome-9.8p1-1.x86_64.rpm    ├── openssh-clients-9.8p1-1.x86_64.rpm    ├── openssh-debuginfo-9.8p1-1.x86_64.rpm    ├── openssh-debugsource-9.8p1-1.x86_64.rpm    └── openssh-server-9.8p1-1.x86_64.rpm /root/rpmbuild/SRPMS └── openssh-9.8p1-1.src.rpm  1 directory, 8 files

对openssh原配置相关文件进行备份

对openssh原配置相关文件进行备份,因为安装新的软件包后,相关文件会被覆盖,如配置文件/etc/ssh/sshd_config及认证文件/etc/pam.d/sshd

 [root@localhost SPECS]# cp -ar /etc/ssh/ /etc/ssh_8.2p1 [root@localhost SPECS]# cp -p /etc/pam.d/sshd /etc/pam.d/sshd_8.2p1

使用构建的RPM包进行升级测试

在对原openssh配置相关文件备份后使用构建后的新版本OpenSSH_9.8p1软件包进行升级安装

 #进入到构建的RPM包目录,使用yum localhost 命令进行安装升级 [root@localhost SPECS]# cd /root/rpmbuild/RPMS/x86_64 [root@localhost x86_64]# yum localinstall openssh* -y  #升级后查看,可以确认升级后openssh相关包版本为OpenSSH_9.8p1 [root@localhost x86_64]# rpm -qa | grep openssh openssh-server-9.8p1-1.x86_64 openssh-askpass-9.8p1-1.x86_64 openssh-9.8p1-1.x86_64 openssh-askpass-gnome-9.8p1-1.x86_64 openssh-debugsource-9.8p1-1.x86_64 openssh-debuginfo-9.8p1-1.x86_64 openssh-clients-9.8p1-1.x86_64 [root@localhost x86_64]# ssh -V OpenSSH_9.8p1, without OpenSSL

备份升级后的pam相关的sshd文件,然后使用升级前的备份文件

#使用备份文件恢复/etc/pam.d/sshd文件内容mv /etc/pam.d/sshd  /etc/pam.d/sshd_9.8p1mv /etc/pam.d/sshd_8.2p1  /etc/pam.d/sshd

在重启一下ssh服务试试,确认均正常

 [root@localhost pam.d]# systemctl restart sshd [root@localhost pam.d]# systemctl status sshd ● sshd.service - SYSV: OpenSSH server daemon    Loaded: loaded (/etc/rc.d/init.d/sshd; generated)    Active: active (running) since Fri 2024-07-05 20:27:18 CST; 5s ago      Docs: man:systemd-sysv-generator(8)  Process: 14831 ExecStart=/etc/rc.d/init.d/sshd start (code=exited, status=0/SUCCESS)  Main PID: 14840 (sshd)    Tasks: 1    Memory: 292.0K    CGroup: /system.slice/sshd.service            └─14840 sshd: /usr/sbin/sshd [listener] 0 of 10-100 startups  Jul 05 20:27:18 localhost systemd[1]: Starting SYSV: OpenSSH server daemon... Jul 05 20:27:18 localhost sshd[14831]: Starting sshd: Jul 05 20:27:18 localhost sshd[14839]: Unable to load host key "/etc/ssh/ssh_host_rsa_key": unknown or unsupported key type Jul 05 20:27:18 localhost sshd[14839]: Unable to load host key: /etc/ssh/ssh_host_rsa_key Jul 05 20:27:18 localhost sshd[14839]: Unable to load host key "/etc/ssh/ssh_host_ecdsa_key": unknown or unsupported key type Jul 05 20:27:18 localhost sshd[14839]: Unable to load host key: /etc/ssh/ssh_host_ecdsa_key Jul 05 20:27:18 localhost sshd[14840]: Server listening on 0.0.0.0 port 22. Jul 05 20:27:18 localhost sshd[14840]: Server listening on :: port 22. Jul 05 20:27:18 localhost sshd[14831]: [ OK ] Jul 05 20:27:18 localhost systemd[1]: Started SYSV: OpenSSH server daemon.

最后进行连接测试确认无问题,能正常ssh登录。验证ssh相关命令,确认存在ssh-copy-id命令

 [root@localhost SPECS]# ss ss           ssh         ssh-add     ssh-agent   ssh-copy-id sshd         ssh-keygen   ssh-keyscan


一键构建openssh RPM工具推荐

除了上述自己通过rpmdevtools工具构建RPM的方式外,这里在推荐一个开源工具。使用该工具只需要执行脚本就行了,几乎属于一键构建。

github地址:https://github.com/boypt/openssh-rpms

支持的发行版(已完成测试)

  • CentOS 5/6/7/8/Stream 8/9

  • Amazon Linux 1/2/2023

  • UnionTech OS Server 20

  • openEuler 22.03 (LTS-SP1)

  • AnolisOS 7.9/8.6

上面是官方的说法,此次我基于openEuler 20.03 (LTS-SP4)构建的RPM也是可以使用的,其他的发行版请自行测试

准备编译环境

 yum groupinstall -y "Development Tools" yum install -y imake rpm-build pam-devel krb5-devel zlib-devel libXt-devel libX11-devel gtk2-devel perl perl-IPC-Cmd  # For CentOS5 only: yum install -y gcc44

工具下载

 [root@localhost opt]# wget https://github.com/boypt/openssh-rpms/archive/refs/heads/main.zip [root@localhost opt]# unzip main.zip

解压后文件结构是这样子的

 [root@localhost opt]# tree openssh-rpms-main/ openssh-rpms-main/ ├── amzn1 │   ├── BUILD │   ├── RPMS │   ├── SOURCES │   │   └── sshd.pam.amzn1 │   ├── SPECS │   │   └── openssh.spec │   └── SRPMS ├── amzn2 │   ├── BUILD │   ├── RPMS │   ├── SOURCES │   │   └── sshd.pam.amzn2 │   ├── SPECS │   │   └── openssh.spec │   └── SRPMS ├── amzn2023 │   ├── BUILD │   ├── RPMS │   ├── SOURCES │   │   └── sshd.pam.amzn2023 │   ├── SPECS │   │   └── openssh.spec │   └── SRPMS ├── compile.sh ├── docker │   ├── Dockerfile.amazonlinux │   ├── Dockerfile.centos │   ├── Dockerfile.centos-stream │   ├── modify_dnf_source.pl │   └── modify_yum_source.sh ├── docker.README.md ├── downloads │   └── x11-ssh-askpass-1.2.4.1.tar.gz ├── el5 │   ├── BUILD │   ├── RPMS │   ├── SOURCES │   │   └── sshd.pam.el5 │   ├── SPECS │   │   └── openssh.spec │   └── SRPMS ├── el6 │   ├── BUILD │   ├── RPMS │   ├── SOURCES │   │   └── sshd.pam.el6 │   ├── SPECS │   │   └── openssh.spec │   └── SRPMS ├── el7 │   ├── BUILD │   ├── RPMS │   ├── SOURCES │   │   └── sshd.pam.el7 │   ├── SPECS │   │   └── openssh.spec │   └── SRPMS ├── pullsrc.sh ├── README.md └── version.env  38 directories, 23 files

说明:

1、compile.sh:编译脚本,执行生成RPM包用的,特殊说明了下,要是5版本的系统需要./compile.sh el52、其中downloads里放的源码包3、x11-ssh-askpass-1.2.4.1.tar.gz4、el5/el6/el7对就要编译的系统版本,EL7/SPEC里面包含编译用到的文件5、RPMS里是存储编译好的RPM包5、sshd.pam.el7 就是对应操作系统里的/etc/pam.d里的模板文件原始版本6、openssh.spec。编译好的rpm包放在EL7/RPMS目录下,有能力的小伙伴可以在这里修改相关的参数。7、pullsrc.sh:openssh相关源码文件下载脚本,如果没有网的话,也可以手动下载源码包,不使用这个脚本8、version.env:定义了openssh及openssl源码的版本信息

源码包下载

在解压目录中运行pullsrc.sh脚本文件,这将会下载version.env文件中定义的源码包到downloads目录,一般包括openssl、openssh文件。x11-ssh-askpass-1.2.4.1.tar.gz官方已经很久没有发布新版本了,所以该文件默认已经存放到downloads目录了

 [root@localhost openssh-rpms-main]# ./pullsrc.sh  #上述脚步运行完成后可以发现downloads目录下存在多了openssh跟openssl文件,这就是编译要用到的源码文件 [root@localhost openssh-rpms-main]# ll downloads/ total 17M -rw-r--r-- 1 root root 1.9M Jul 1 15:34 openssh-9.8p1.tar.gz -rw-r--r-- 1 root root 15M Jun 4 23:04 openssl-3.0.14.tar.gz -rw-r--r-- 1 root root 29K Jul 5 17:52 x11-ssh-askpass-1.2.4.1.tar.gz

如果机器出不了外网,把对应的源码包下载下来存到downloads目录也行

构建RPM

源码包下载完成后再解压目录运行compile.sh脚步文件,自动构建openssh RPM

 [root@localhost openssh-rpms-main]# ./compile.sh

安装RPM

通过cd $(./compile.sh RPMDIR)命令转到生成的RPMS目录

 [root@localhost openssh-rpms-main]# cd $(./compile.sh RPMDIR) [root@localhost x86_64]# pwd /opt/openssh-rpms-main/el7/RPMS/x86_64  # 你会在这个目录下找到多个RPM文件,这即是编译成功的openssh相关RPM文件 [root@localhost x86_64]# ls openssh-9.8p1-1.x86_64.rpm openssh-clients-9.8p1-1.x86_64.rpm openssh-debuginfo-9.8p1-1.x86_64.rpm openssh-debugsource-9.8p1-1.x86_64.rpm openssh-server-9.8p1-1.x86_64.rpm  # 备份当前ssh配置文件 [[ -f /etc/ssh/sshd_config ]] && mv /etc/ssh/sshd_config /etc/ssh/sshd_config.$(date +%Y%m%d)  # 安装rpm包。排除所有调试包 find . ! -name '*debug*' -name '*.rpm' | xargs sudo yum --disablerepo=* localinstall -y  # 修改主机秘钥文件权限 chmod -v 600 /etc/ssh/ssh_host_*_key  # For CentOS7+: # in some cases previously installed systemd unit file is left on disk after upgrade. # causes systemd mixing unit files and initscripts units provided by this package. if [[ -d /run/systemd/system && -f /usr/lib/systemd/system/sshd.service ]]; then    mv /usr/lib/systemd/system/sshd.service /usr/lib/systemd/system/sshd.service.$(date +%Y%m%d)    systemctl daemon-reload fi

检查验证

注意一定不要断开当前的 SSH 连接,直接打开一个新的 shell 并登录以验证 sshd 是否正常工作以及版本是否正常

 # 检查安装版本 [root@localhost x86_64]# ssh -V && /usr/sbin/sshd -V OpenSSH_9.8p1, OpenSSL 3.0.14 4 Jun 2024 OpenSSH_9.8p1, OpenSSL 3.0.14 4 Jun 2024  # 重启ssh服务再次验证 [root@localhost x86_64]# systemctl restart sshd [root@localhost x86_64]# ssh -V && /usr/sbin/sshd -V OpenSSH_9.8p1, OpenSSL 3.0.14 4 Jun 2024 OpenSSH_9.8p1, OpenSSL 3.0.14 4 Jun 2024  #同时在验证是否能通过当前主机直接ssh连接其他主机,某些情况下可能因为一些算法的问题导致无法ssh连接其他主机 [root@localhost x86_64]# ssh [username]@[ip]

注意事项

依赖报错

在yum localinstall过程中,可能会收到一些报错。这主要是因为一些子包依赖于主openssh包,仅升级主包将不适合它们的依赖关系。通常,在安装构建的rpm之前需要移除这些包。

 yum erase openssh-askpass openssh-keycat openssh-cavs openssh-askpass openssh-askpass-gnome openssh-debuginfo openssh-help

注意:

具体移除的软件包请根据报错视情况而定,而不是一键移除所有,除非你清楚的知道移除它们有什么影响。

强制安装

不推荐,除非确实解决不了依赖问题

 rpm -ivh --force --nodeps --replacepkgs --replacefiles openssh-*.rpm

安全笔记

以下是升级后常见的一些安全层面的修改,可根据实际情况按需配置

PubkeyAcceptedAlgorithms +ssh-rsa PermitRootLogin yes PasswordAuthentication yes UseDNS no UsePAM yes #如果需要支持旧算法,/etc/ssh/sshd_config中修改,之后重启SSHD KexAlgorithms -diffie-hellman-group1-sha1,diffie-hellman-group1-sha256,diffie-hellman-group14-sha1,diffie-hellman-group14-sha256,diffie-hellman-group15-sha256,diffie-hellman-group15-sha512,diffie-hellman-group16-sha256,diffie-hellman-group16-sha512,diffie-hellman-group17-sha512,diffie-hellman-group18-sha512,diffie-hellman-group-exchange-sha1,diffie-hellman-group-exchange-sha256,diffie-hellman-group-exchange-sha512
「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论