若要进行生产环境的操作,请务必看完整篇文档
实验环境:Centos7.6 离线系统
目前已经成功完成了openssh 9.1p1的编译

1、准备openssh源码包

在home目录开始,设置工作目录

cd ~

从openssh.com下载openssh源码包

下面链接可先尝试自己的浏览器能否点击进去,防止服务器获取不到相应的地址

# 下载需要的安装包
wget https://cdn.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-9.0p1.tar.gz

#下载x11-ssh-askpass x11 口令对话框插件源码包,可选,如无需x11-ssh-askpass可通过修改spec文件跳过该源码包

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

验证文件签名,可选

# 从openbsd下载签名公钥
wget https://ftp.openbsd.org/pub/OpenBSD/OpenSSH/RELEASE_KEY.asc
# 导入公钥
gpg --import RELEASE_KEY.asc
# 下载源码包签名
wget https://cdn.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-9.0p1.tar.gz.asc
# 检验签名
gpg --verify openssh-9.0p1.tar.gz.asc openssh-9.0p1.tar.gz

2、安装rpm-build及编译环境

安装rpm-build包及其他编译需要的包

yum -y install rpm-build zlib-devel openssl-devel gcc perl-devel pam-devel unzip

添加askpass支持需要增加安装依赖包libxXt-devel imake gtk2-devel

yum -y install libXt-devel imake gtk2-devel

创建rpm-build工作目录,SOURCES放置源码包,SPECS放置配置文件

mkdir -p ~/rpmbuild/{BUILD,RPMS,SOURCES,SPECS,SRPMS}

补充说明,rpmbuild下目录

  • BUILD 编译rpm包的临时目录
  • BUILDROOT 编译后生成的软件临时安装目录
  • RPMS 最终生成的可安装rpm包的所在目录
  • SOURCES 所有源代码和补丁文件的存放目录
  • SPECS 存放SPEC文件的目录(重要)
  • SRPMS 软件最终的rpm源码格式存放路径
    将源码包拷贝至rpmbuild工作目录
cp ~/openssh-9.0p1.tar.gz ~/rpmbuild/SOURCES

如需要添加askpass支持

cp ~/x11-ssh-askpass-1.2.4.1.tar.gz ~/rpmbuild/SOURCES

3、提取spec文件

从源码包提取spec文件[所需的spec文件是从tar包中提取的]

tar -zxvf openssh-9.0p1.tar.gz openssh-9.0p1/contrib/redhat/openssh.spec
cp ~/openssh-9.0p1/contrib/redhat/openssh.spec ~/rpmbuild/SPECS

4、修改spec文件

无需askpass可通过修改spec文件参数跳过x11-ssh-askpass源码包,需要注释的地方有3个

# Do we want to disable building of x11-askpass? (1=yes 0=no)
%global no_x11_askpass 1

# Do we want to disable building of gnome-askpass? (1=yes 0=no)
%global no_gnome_askpass 1

#注释掉Source1 x11-ssh-askpass包引用
Source1: http://www.jmknoble.net/software/x11-ssh-askpass/x11-ssh-askpass-%{aversion}.tar.gz

已知需要解决spec文件引起的报错:

  1. 解决openssl-devel<1.1 报错
    需要手动注释掉以下配置项
    #BuildRequires: openssl-devel < 1.1

openssh 9.4

openssh 9.4p1版本依赖openssl 1.1.v的环境

若编译无法通过,出现以下提示
错误:发现已安装(但未打包的)文件:
/usr/libexec/openssh/ssh-sk-helper
/usr/share/man/man8/ssh-sk-helper.8.gz

RPM 构建错误:
发现已安装(但未打包的)文件:
/usr/libexec/openssh/ssh-sk-helper
/usr/share/man/man8/ssh-sk-helper.8.gz

验证发现自带spec文件为2018年最后更新,ssh-sk-helper为2019年12月新增,spec文件未%file中未包含该文件
修改spec文件

在%attr(0644,root,root) %{_mandir}/man8/ssh-pkcs11-helper.8*后追加
%attr(0755,root,root) %{_libexecdir}/openssh/ssh-sk-helper
%attr(0644,root,root) %{_mandir}/man8/ssh-sk-helper.8*

5、编译并生成rpm

cd ~/rpmbuild/SPECS
rpmbuild -ba openssh.spec

超多输出,只要最后是“+ exit 0”就是成功生成
生成后的文件存放在~/rpmbuild/RPMS
因为是在x86_64做的编译所以在~/rpmbuild/RPMS/x86_64目录中

/home/<user_name>/rpmbuild/RPMS/x86_64
# 如果没有编译askpass的话,不会生成 askpass包,所以实际生成的rpm包数量为4个或者6个(带askpass)
[user1@localhost x86_64]$ ll
总用量 4536
-rw-rw-r--. 1 user1 user1 602772 6月 25 15:10 openssh-9.0p1-1.el7.centos.x86_64.rpm
-rw-rw-r--. 1 user1 user1 44312 6月 25 15:10 openssh-askpass-9.0p1-1.el7.centos.x86_64.rpm
-rw-rw-r--. 1 user1 user1 24696 6月 25 15:10 openssh-askpass-gnome-9.0p1-1.el7.centos.x86_64.rpm
-rw-rw-r--. 1 user1 user1 580532 6月 25 15:10 openssh-clients-9.0p1-1.el7.centos.x86_64.rpm
-rw-rw-r--. 1 user1 user1 2958016 6月 25 15:10 openssh-debuginfo-9.0p1-1.el7.centos.x86_64.rpm
-rw-rw-r--. 1 user1 user1 419928 6月 25 15:10 openssh-server-9.0p1-1.el7.centos.x86_64.rpm
[user1@localhost x86_64]$

6、安装

安装之前请尽量开始telnet服务
还有,备份配置,一定要做!

mkdir ~/ssh_bak
mkdir ~/ssh_bak/service
# 备份PAM配置
cp /etc/pam.d/sshd ~/ssh_bak/
# 备份sshd_config
cp /etc/ssh/sshd_config ~/ssh_bak/
# 备份sshd的启动服务
cp /usr/lib/systemd/system/sshd* ~/ssh_bak/service/

升级方式安装

现在不推荐使用卸载安装的方式,因为这种方式会产生一些问题,导致sshd服务不能够自动启动。

1、解压安装包,进入存放rpm的目录
2、执行yum安装命令:

yum -y localinstall openssh*.rpm --disablerepo=* --nogpgcheck

3、恢复PAM设置

cp -f ~/ssh_bak/sshd /etc/pam.d/

自打包未包含systemd管理服务的service文件,需要自行添加,因centos自带rpm包中包含原始包中不存在的sshd-keygen可能会出现未找到文件错误,需谨慎执行,如不使用service文件管理使用chkconfig管理sshd的开机启动。

4、修改key文件访问权限

#修改/etc/ssh/ssh_host_* 权限
chmod 400 /etc/ssh/ssh_host_*

5、恢复配置文件(可选)

注意,该步骤为可选步骤,仅在服务启动失败时供排查报错或者恢复配置使用!

cp -f ~/ssh_bak/sshd /etc/sysconfig/sshd
cp -f ~/ssh_bak/pam.d/sshd /etc/pam.d/sshd
cp -f ~/ssh_bak/service/* /usr/lib/systemd/system/sshd*

6、修改sshd_config

安装时会创建新版配置文件sshd_config.rpmnew,如果原有的配置无法生效可以参考新的配置

vim /etc/ssh/sshd_config
## 务必保证以下几项设置都正确!否则会进不了服务器!
# 允许root登录
PermitRootLogin yes
# 允许密码登录
PasswordAuthentication yes

7、尝试重启sshd进程

systemctl restart sshd
# 如果是通过sshd.socket服务启动可以执行以下命令
systemctl restart sshd.socket

8、尝试建立新的ssh连接

ssh -v localhost

注意查看输出的远端版本信息,如果此时连接不上,需要立即排查以上设置是否正确。

...
debug1: Local version string SSH-2.0-OpenSSH_9.0
debug1: Remote protocol version 2.0, remote software version OpenSSH_9.1
debug1: compat_banner: match: OpenSSH_9.0 pat OpenSSH* compat 0x04000000
...

SecureCRT7.1密钥交换算法不在OpenSSH8.3默认列表中,XShell6无此问题
需要在配置文件中增加SecureCRT7.1支持的算法。

sshd -T | grep kexalgorithms>> /etc/ssh/sshd_config
vi /etc/ssh/sshd_config
#或者手动在KexAlgorithms添加 diffie-hellman-group14-sha1

后续补充内容

20210426 补充
在一次升级过程中,发现升级后使用sshd -V命令查看sshd版本,结果返回的还是之前的版本(Centos7.8 openssh 7.9p1 升级到 openssh 8.6p1),经过研究发现,sshd命令被映射到两个文件,一个是/usr/sbin/sshd,这个是默认的启动文件,查看版本,是8.6p1,另一个在不同的目录中,在bash中调用sshd会使用另外一个老版本的sshd,所以不能通过sshd -V验证当前已经使用的sshd版本,最好是 ssh -v root@ip 命令来验证。另外,最好在PATH中删除老版本的sshd路径和ssh路径,以免产生其他不必要的错误操作。
20210730 补充
之前在升级Openssh时由于没有恢复/etc/sysconfig/sshd文件导致其自动启动会失败,在机器重启后sshd服务启动不了,进不了机器。

附件一:降级

yum -y downgrade openssh-server-7.4p1-21.el7 openssh-clients-7.4p1-21.el7 openssh-7.4p1-21.el7
/bin/cp -f ~/ssh_bak/sshd /etc/pam.d/
/bin/cp -f ~/ssh_bak/ssh_config /etc/ssh/
/bin/cp -f ~/ssh_bak/sshd_config /etc/ssh/

附件二:使用Telnet登录并进行安装

以root登录ssh
安装telnet服务

systemctl stop firewalld
systemctl disable firewalld
yum install telnet-server
yum install xinetd
# 若不能在线安装,需要下载rpm包,不会太多,一共两三个
systemctl start telnet.socket
systemctl start xinetd
systemctl enable telnet.socket
systemctl enable xinetrd

安装完成验证ssh登录成功,并在服务器重启后仍能使用ssh登录,则:

#启动firewalld,
systemctl start firewalld
systemctl enable firewalld
#关闭telnet服务,
systemctl stop telnet.socket
systemctl stop xinetd
systemctl disable telnet.socket
systemctl disable xinetd
#卸载telnet-server,
yum erase telnet-server

若要修改 telnet的端口号,其配置文件在:/usr/lib/systemd/system/telnet.socket

附件三:其他参考

/etc/pam.d/sshd

[root@localhost ~]# cat /etc/pam.d/sshd
#%PAM-1.0
auth required pam_sepermit.so
auth substack password-auth
auth include postlogin
# Used with polkit to reauthorize users in remote sessions
-auth optional pam_reauthorize.so prepare
account required pam_nologin.so
account include password-auth
password include password-auth
# pam_selinux.so close should be the first session rule
session required pam_selinux.so close
session required pam_loginuid.so
# pam_selinux.so open should only be followed by sessions to be executed in the user context
session required pam_selinux.so open env_params
session required pam_namespace.so
session optional pam_keyinit.so force revoke
session include password-auth
session include postlogin
# Used with polkit to reauthorize users in remote sessions
-session optional pam_reauthorize.so prepare

/usr/lib/systemd/system/sshd-keygen.service

[Unit]
Description=OpenSSH Server Key Generation
ConditionFileNotEmpty=|!/etc/ssh/ssh_host_rsa_key
ConditionFileNotEmpty=|!/etc/ssh/ssh_host_ecdsa_key
ConditionFileNotEmpty=|!/etc/ssh/ssh_host_ed25519_key
PartOf=sshd.service sshd.socket

[Service]
ExecStart=/usr/sbin/sshd-keygen
Type=oneshot
RemainAfterExit=yes

/usr/lib/systemd/system/sshd.service

[Unit]
Description=OpenSSH server daemon
Documentation=man:sshd(8) man:sshd_config(5)
After=network.target sshd-keygen.service
Wants=sshd-keygen.service

[Service]
Type=notify
EnvironmentFile=/etc/sysconfig/sshd
ExecStart=/usr/sbin/sshd -D $OPTIONS
ExecReload=/bin/kill -HUP $MAINPID
KillMode=process
Restart=on-failure
RestartSec=42s

[Install]
WantedBy=multi-user.target

/usr/lib/systemd/system/sshd@.service

[Unit]
Description=OpenSSH per-connection server daemon
Documentation=man:sshd(8) man:sshd_config(5)
Wants=sshd-keygen.service
After=sshd-keygen.service

[Service]
EnvironmentFile=-/etc/sysconfig/sshd
ExecStart=-/usr/sbin/sshd -i $OPTIONS
StandardInput=socket

/usr/lib/systemd/system/sshd.socket

[Unit]
Description=OpenSSH Server Socket
Documentation=man:sshd(8) man:sshd_config(5)
Conflicts=sshd.service

[Socket]
ListenStream=22
Accept=yes

[Install]
WantedBy=sockets.target

lib/systemd/system/sshd.service

[Unit]
Description=OpenSSH server daemon
Documentation=man:sshd(8) man:sshd_config(5)
After=network.target sshd-keygen.service
Wants=sshd-keygen.service

[Service]
Type=notify
EnvironmentFile=/etc/sysconfig/sshd
ExecStart=/usr/sbin/sshd -D $OPTIONS
ExecReload=/bin/kill -HUP $MAINPID
KillMode=process
Restart=on-failure
RestartSec=42s

[Install]
WantedBy=multi-user.target

/lib/systemd/system/sshd.socket

[Unit]
Description=OpenSSH Server Socket
Documentation=man:sshd(8) man:sshd_config(5)
Conflicts=sshd.service

[Socket]
ListenStream=22
Accept=yes

[Install]
WantedBy=sockets.target