尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

CentOS7 OpenSSH升级实战:从源码编译到安全加固全指南

CentOS7 OpenSSH升级实战:从源码编译到安全加固全指南 简介面向CentOS 7运维与安全管理人员这份代码包围绕OpenSSH 10.0p2与OpenSSL 3.0.16的升级场景提供了一套完整且可直接参考的实操方案旨在解决系统自带版本过低带来的安全隐患。资源包体仅6KB共3个文件以HTML操作指南为主体并辅以inscode配置与gitignore规则既便于在博客中直观展示关键命令也能顺利纳入版本管理。目前已有115人学习下载内容虽精简却覆盖了升级全链路从无网络或远程环境下的telnet兜底登录到依赖包安装、zlib/OpenSSL/OpenSSH的下载编译与旧版备份再到编译参数配置、动态库链接设置以及升级后sshd服务无法启动的排障思路。借助这份指南读者能够在不中断远程登录的前提下完成系统安全加固减少因依赖缺失或配置不当导致的升级中断也可在升级后快速核对版本、确认服务状态尤其适合需要快速落地OpenSSH补丁、兼顾稳定性与兼容性的中级系统管理员。1. CentOS7升级OpenSSH安全扫描逼出来的必修课绿盟、Nessus这类安全扫描工具一到年底就让整个运维群炸锅CentOS7自带OpenSSH_7.4p1CVE清单翻好几页都翻不完。你打开扫描报告一看高危漏洞集中在SSH加密协议上立刻想在线上做yum update openssh结果发现CentOS7的官方源经过多年封板版本号永远停在7.4p1补丁最多补到本地版本压根儿追不上审计基线。真正能解决问题的是走源码编译把OpenSSH升到8.x甚至9.x。本文把CentOS7升级OpenSSH这条路从头到尾拆开怎么盘家底、怎么装依赖、configure参数怎么给、二进制怎么替换、SELinux和防火墙怎么绕过、回滚怎么做到一键搞定。覆盖对象是生产环境里的运维、实施和负责安全整改的工程师照着步骤做不会把线上的SSH搞残。2. 升级前的家底盘点版本、依赖与备份缺一不可2.1 先看清当前OpenSSH与OpenSSL版本不要上来就下载源码包先确认当前环境里OpenSSH和OpenSSL的版本。CentOS7自带的组合一般是OpenSSH_7.4p1配合OpenSSL 1.0.2k-fips这两个版本之间的绑定关系直接决定了你能不能编译新版OpenSSH。新版OpenSSH从9.6开始把OpenSSL最低版本提到了1.1.1而CentOS7基础源里根本找不到OpenSSL 1.1.1只升SSH不升SSL的路线最多安全地走到8.x系列。先执行下面三条命令把环境信息打出来ssh -V # 例OpenSSH_7.4p1, OpenSSL 1.0.2k-fips 26 Jan 2017 rpm -qa | grep -E ^openssh|^openssl # openssh-7.4p1-22.el7.x86_64 # openssh-server-7.4p1-22.el7.x86_64 # openssh-clients-7.4p1-22.el7.x86_64 # openssl-1.0.2k-26.el7_9.x86_64 sshd -T | grep -E port|protocol|permitrootlogin第一条确认当前SSH组件版本第二条看RPM包里装的到底是哪个版本第三条查看实际生效的配置项。如果sshd -T报错多半是/etc/ssh/sshd_config里有语法兼容性问题先修好再继续。这一步最关键的作用是让你明确你手上这台机器SSH的配置、密钥、启动方式都是旧版本的形态后面所有替换动作都要围绕这个基线展开。2.2 编译依赖清单少一个包都编不过源码编译OpenSSH需要gcc、make、zlib-devel、openssl-devel、pam-devel这些基础包。比较坑的是很多机器为了减小攻击面装了gcc但不装devel头文件导致configure阶段直接报zlib.h not found或者openssl/ssl.h not found。我习惯一次性把这几个包装全避免反复跑configure。同时建议顺手把policycoreutils-python装上后面处理SELinux标签要用semanage。yum install -y gcc make zlib-devel openssl-devel pam-devel policycoreutils-python如果你的机器yum源失效典型现象是yum install卡在Could not retrieve mirrorlist那先换国内yum源再装依赖。CentOS7源失效后直接编辑/etc/yum.repos.d/CentOS-Base.repo把baseurl指向vault.centos.org的归档地址具体操作网上有很多现成配置这里不展开。依赖装完之后用rpm -qa | grep devel确认一下四个关键包都在。记住一个原则头文件缺失的报错九成是devel包没装不要一上来就怀疑源码有问题。2.3 备份配置和密钥这是你的后悔药OpenSSH升级的核心风险不是编译失败而是替换完二进制之后旧配置不兼容、或者host key丢了导致整个SSH进不去。所以动手之前必须做完整备份。这里说的备份不是简单cp一下而是把ssh_config、sshd_config、所有host key、以及当前的sshd和ssh二进制全部留底。# 备份配置文件 cp /etc/ssh/ssh_config /etc/ssh/ssh_config.bak cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak # 备份host key注意保留原有权限所以要加 -a cp -a /etc/ssh/ssh_host_* /etc/ssh/host_key_backup/ # 备份二进制 cp /usr/sbin/sshd /usr/sbin/sshd.old cp /usr/bin/ssh /usr/bin/ssh.old # 记录当前SSH端口和登录方式回滚时需要对照 sshd -T | grep -E ^port|^permitrootlogin|^passwordauthentication二进制备份放到/usr/sbin/sshd.old而不是/tmp是为了避免/tmp被清理。host key备份时用cp -a保留属主和权限因为sshd对host key权限非常敏感属主不对会直接拒绝启动。另外建议把当前/etc/ssh/sshd_config里改动过的行记录到文本里升级后新版sshd对某些旧参数会直接报Bad configuration option到时候你要靠这个记录去恢复原来的行为。2.4 临时开telnet保底通道升级SSH最怕的情况是替换后新sshd起不来、或者SELinux拦截导致端口不通此时SSH已经断了你人在机房外只能干瞪眼。所以生产环境操作前我一般先开telnet作为保底通道。注意这只是临时保底升级完成后必须立刻关闭并卸载。yum install -y telnet-server telnet systemctl enable telnet.socket --now ss -tlnp | grep :23telnet.socket是CentOS7上由systemd管理的socket激活服务systemctl enable --now一条命令就能让它监听23端口。确认23端口在监听之后再继续后面的编译操作。这里提醒一句telnet本身是明文协议万万不可以长期开着防扫描策略、防火墙放行都要掐着时间点来升级一完成马上systemctl disable --now telnet.socket。3. 源码编译升级OpenSSH从configure到make install的完整命令3.1 源码包选择与下载校验OpenSSH官方源码托管在OpenBSD的FTP镜像上生产环境下载源码前一定要先确认版本。如果你不打算连带升级OpenSSL建议选择8.8p1到8.9p1之间的版本这一系列还能配合OpenSSL 1.0.2编译如果坚持要上9.x甚至10.x请先想清楚OpenSSL 1.1.1的替代方案否则configure会直接拒绝执行。cd /usr/local/src wget https://mirrors.tuna.tsinghua.edu.cn/OpenBSD/OpenSSH/portable/openssh-8.9p1.tar.gz wget https://mirrors.tuna.tsinghua.edu.cn/OpenBSD/OpenSSH/portable/openssh-8.9p1.tar.gz.asc下载之后强烈建议校验签名。校验需要先导入OpenSSH官方发布密钥如果懒得折腾GPG至少做一下sha256校验防止下载到被篡改的包。镜像站一般会提供sha256文件。编译前解压tar -xzf openssh-8.9p1.tar.gz cd openssh-8.9p1解压后先看一眼README和ChangeLog确认你选定的版本没有已知的、会影响你现有客户端兼容性的变更。特别是8.8p1起默认禁用了ssh-rsa签名算法如果你的自动化脚本还在用老客户端连这台机器升级完会被拒之门外。3.2 configure参数怎么给prefix、pam、ssl路径都要想明白OpenSSH编译的configure参数直接决定安装后二进制落在哪、读哪份配置文件。我的推荐参数是下面这一组./configure --prefix/usr --sysconfdir/etc/ssh --with-pam --with-md5-passwords--prefix/usr非常关键。CentOS7上sshd二进制本来就在/usr/sbin下配置文件在/etc/ssh下。指定prefix为/usr安装的sshd会覆盖到/usr/sbin/sshd而不是装到/usr/local/sbin/sshd。如果漏了这个参数新sshd装进/usr/local而systemd服务文件指向/usr/sbin/sshd你重启服务发现还是老版本在跑折腾半天找不到原因。--sysconfdir/etc/ssh让新版sshd继续读原来的配置目录不会跑到/usr/local/etc下去找配置。--with-pam启用PAM认证因为CentOS7的密码登录依赖pam_unix模块不加这个参数你升级完可能面临所有密码登录都被拒绝的问题。--with-md5-passwords是兼容旧密码哈希用的如果你的用户还是MD5哈希加上它避免登录失败。OpenSSL路径一般不用显式指定configure会自动找到系统里的openssl头文件只有当你手动装了OpenSSL 1.1.1到非标准路径时才需要加--with-ssl-dir。3.3 编译安装与二进制替换顺序决定成败configure通过后执行编译和安装make -j 4 make install-j 4是并行编译参数4核机器上能省一半时间。编译过程中如果出现error: *** zlib.h not found或openssl/ssl.h not found回头检查2.2步的devel包装没装齐。make install会把sshd、ssh、scp、sftp全部装到/usr/bin和/usr/sbin下。这里有个隐患make install不会覆盖正在运行的sshd二进制文件因为内核还持有旧文件的inode所以安装完必须先重启sshd服务才生效但重启之前要先做一次配置兼容性测试。/usr/sbin/sshd -tsshd -t只做配置解析检查不启动服务。如果输出Bad configuration option: ...说明你的旧sshd_config里有新版不认识的指令。常见的弃用项包括UseDNS、GSSAPIAuthentication有些版本里还能继续用但stricter点的版本会直接拒绝。此时先把有问题的行注释掉再跑sshd -t直到没有输出错误。测试通过后再重启服务systemctl restart sshd systemctl status sshd这时需要立刻新开一个终端窗口验证登录不要关掉当前连接。确认新终端能登进来再考虑关旧窗口。3.4 验证二进制替换是否真的生效make install之后最迷惑人的一个现象是ssh -V显示的还是老版本。原因是CentOS7上的ssh命令可能是从/usr/bin/ssh加载的而你make install把新二进制放到了同一个路径但shell的hash缓存还指向旧的。执行hash -r刷新一下或者直接which ssh看路径。更稳妥的验证方式是看sshd进程的启动路径ps -ef | grep sshd | head -3 # root 1234 1 0 09:00 ? 00:00:00 /usr/sbin/sshd -D如果进程名还是sshd但启动路径没变用ls -l /proc/1234/exe看实际运行的是哪个文件。因为linux下替换运行中的二进制进程会继续跑旧文件只有重启后才会真正加载新文件。所以make install之后必须systemctl restart sshd这一步别省。ssh -V显示OpenSSH_8.9p1就说明编译安装这条路本身没问题了。4. 配置与启动让新版sshd在CentOS7上安稳落地4.1 sshd_config里的三个必调参数新版OpenSSH装好之后不是版本对了就完事sshd_config里几项策略必须一项项过。首先是PermitRootLogin安全扫描通常要求禁止root远程登录默认配置如果是yes要改成no。第二是PasswordAuthentication如果公司安全基线要求密钥登录这里需要设成no但改之前确认所有用户的公钥都进了authorized_keys否则容易全员被锁在门外。第三个是X11Forwarding内网跳板机场景经常需要默认是no按需打开。sed -i s/^#\?PermitRootLogin yes/PermitRootLogin no/ /etc/ssh/sshd_config sed -i s/^#\?PasswordAuthentication yes/PasswordAuthentication no/ /etc/ssh/sshd_config systemctl restart sshd修改完之后务必先开一个新窗口验证密钥登录可用再关闭旧连接。不要在同一条SSH连接里修改配置然后马上断开这是新手最容易翻车的点。如果用的是8.8p1以上的版本还要注意客户端侧是否支持新的ssh-rsa替代算法老客户端用RSA公钥连接新版服务端可能被拒绝这种情况通常要回退到PubkeyAcceptedKeyTypes增加ssh-rsa兼容项。4.2 SELinux对sshd的限制Permission denied的真相CentOS7默认开启SELinux很多人在升级OpenSSH后遇到诡异问题sshd配置没问题、端口没被占用、防火墙放行了但就是连不上journalctl -u sshd里出现Permission denied。这个Permission denied不是密码错误而是SELinux的avc拒绝日志。新编译出来的/usr/sbin/sshd二进制没有正确的SELinux文件类型标签而CentOS7自带的sshd二进制是有sshd_exec_t标签的。ls -lZ /usr/sbin/sshd # 升级前system_u:object_r:sshd_exec_t:s0 # 升级后unconfined_u:object_r:usr_t:s0如果标签不对用restorecon恢复。但restorecon依赖系统里的selinux策略数据库如果策略包没更新可能恢复不了这时可以用chcon手动打标签chcon -t sshd_exec_t /usr/sbin/sshd restorecon -v /etc/ssh/sshd_config打完标签后重启sshd再用ausearch -m avc -ts recent查看有没有新的avc拒绝记录。SELinux这块别靠猜avc日志会把拒绝原因写得清清楚楚。如果升级完遇到SELinux拦截sshd绑定非标准端口比如把Port改成了2222需要:semanage port -a -t ssh_port_t -p tcp 2222semanage命令来自policycoreutils-python这也是我在第2章让你装这个包的原因。不执行这条sshd进程起不来或者起得来但连不上报错信息还特别含糊。4.3 防火墙、systemd服务与开机自启CentOS7里firewalld默认放行ssh服务但如果你改了SSH端口或者升级过程中firewalld规则被重置就会遇到服务正常但外部访问超时的情况。排查顺序是先ss -tlnp | grep ssh确认监听地址再firewall-cmd --list-all看放行列表。firewall-cmd --add-servicessh --permanent firewall-cmd --reload如果你改了端口比如2222则要firewall-cmd --permanent --add-port2222/tcp firewall-cmd --reloadsystemd方面CentOS7的sshd.service文件在/usr/lib/systemd/system/sshd.service它默认ExecStart指向/usr/sbin/sshd。源码安装的sshd路径如果对得上服务文件不用改。但注意如果你configure时用了--prefix/usr/localsshd去了/usr/local/sbinsystemd启动会失败报ExecStart: No such file or directory。处理方式是把sshd.service里的ExecStart改成新路径或者干脆重新configure一次。开机自启用systemctl enable sshd确认一下就行CentOS7默认就是enable的除非你之前手动disable过。5. 升级OpenSSH的避坑指南5个高频翻车点实录5.1 坑configure报cannot find zlib.h或者openssl/ssl.h现象./configure执行到一半直接退出红字提示error: *** zlib.h missing - please install zlib-devel或者cannot find openssl/ssl.h。原因系统里有zlib、openssl运行库但没装对应的-devel包。configure需要的是头文件不是动态库缺头文件必挂。解决装依赖一条命令搞定yum install -y zlib-devel openssl-devel装完继续configure。这里有个容易忽略的点如果你之前手动编译过OpenSSL到/usr/local/ssl系统自带的头文件版本可能和运行库不一致configure可能找到/usr/include/openssl下的老版本导致后续编译报OPENSSL_VERSION_NUMBER不匹配。遇到这种情况先which openssl和openssl version看当前用的是哪套决定是否要加--with-ssl-dir指向新路径。5.2 坑升级完sshd服务起不来报Permission denied现象systemctl restart sshd失败服务状态显示failedjournalctl -u sshd里有fatal: Cannot set number of files: Permission denied或bind: Permission denied on port 22。原因SELinux标签错误。源码编译的二进制被SELinux当作usr_t类型不允许绑定22端口。解决打SELinux标签后重启chcon -t sshd_exec_t /usr/sbin/sshd restorecon -v /etc/ssh/sshd_config systemctl restart sshd如果端口是自定义的还需要semanage加端口规则。这条坑几乎每个人都会踩因为Permission denied的误导性太强容易让人对着sshd_config反复检查而实际问题在文件系统安全上下文上。5.3 坑sshd在跑端口在听但外部连不上现象ps -ef | grep sshd正常ss -tlnp显示22端口监听但本机外ping不通、telnet 22超时或者用跳板机连不上。原因firewalld规则没放行。CentOS7默认放行ssh但升级过程中如果跑过firewall-cmd --reload或者重置过规则ssh服务定义可能丢失。另外如果改了端口firewalld不会自动放行新端口。解决先确认监听地址不是127.0.0.1再看firewalldfirewall-cmd --list-all | grep ssh firewall-cmd --add-servicessh --permanent firewall-cmd --reload如果监听在公网网卡但firewalld放行了还不行检查云安全组规则这些云平台的安全组是独立于系统防火墙的经常有人系统防火墙放行了对安全组忘了加端口白忙半天。5.4 坑升级完没过几天yum update又把openssh覆盖成旧版现象千辛万苦编译安装到8.9p1一周后巡检发现ssh -V又变回7.4p1。原因yum update时CentOS7仓库里的openssh包版本比源码安装的“高”吗不RPM的版本号7.4p1比源码版的8.9p1低按理说不会降级。但如果yum因为其他包依赖解析错误会重装openssh——比如有人手动卸载了openssh再装回来。更常见的情况是编译安装的二进制不在rpm数据库里某次yum install openssh-clients会按依赖把openssh相关rpm全部装一遍直接覆盖/usr/sbin/sshd。解决在/etc/yum.conf里加excludeecho excludeopenssh* /etc/yum.conf加完之后yum update就不会再碰openssh相关包。这个坑很多人不知道因为yum.conf里的exclude平时根本不会动。如果你还想让rpm数据库对这些包有个记录可以做一个自定义的openssh rpm包装那就是另一个课题了。至少先把exclude加上省得刚升完又被打回原形。5.5 坑回滚时sshd.old也起不来了提示libcrypto版本问题现象新版sshd出问题你按备份把/usr/sbin/sshd.old拷回去结果启动直接报/usr/sbin/sshd: /lib64/libcrypto.so.10: version OPENSSL_1.0.2 not found。原因你在第3章升级OpenSSH时如果是连OpenSSL一起升的系统里的libcrypto.so被新版本替换了而旧sshd.old依赖旧版OpenSSL的特定符号动态库版本不匹配起不来。解决回滚时把OpenSSL 1.0.2也找回来。如果用的是系统自带的openssl路径先查ls -l /usr/lib64/libcrypto.so*确认是否被覆盖。最常见的干净做法是用rpm重新安装原版opensslyum install -y openssl-1.0.2k # 版本号按原机实际情况这里要特别提醒不要在生产环境手动去升OpenSSL 1.1.1除非你有明确的业务需求。很多人看新版OpenSSH要求OpenSSL 1.1.1就顺手把系统OpenSSL也编译升级了结果Apache、nginx、curl全部跟着崩。我见过一个案例升级OpenSSL后curl https全挂最后只能重装系统。OpenSSH升级和OpenSSL升级解耦8.9p1配合1.0.2k够用别贪新。6. 验证升级成果与一键回滚把后悔药放到手边升级完成后的验证分三层第一层是版本和算法第二层是功能测试第三层是回滚能力验证。版本层看ssh -V确认是预定的版本。算法层用nmap --script ssh2-enum-algorithms -p 22 ip看服务端支持的密钥交换算法至少能看出是否还在用ssh-rsa这类弱算法。功能测试建议做两件事一是用受控机器密钥登录这台机器确认PubkeyAuthentication正常二是root用户测试登录确认PermitRootLogin策略生效。别忘了一件事telnet保底通道该关了systemctl disable --now telnet.socket yum remove -y telnet-server回滚脚本提前写好放着我一般放/root/rollback_ssh.sh内容就是把备份的二进制和配置原样恢复#!/bin/bash # 回滚OpenSSH升级前提是第2章备份完整 systemctl stop sshd cp /usr/sbin/sshd.old /usr/sbin/sshd cp /usr/bin/ssh.old /usr/bin/ssh cp /etc/ssh/sshd_config.bak /etc/ssh/sshd_config cp -a /etc/ssh/host_key_backup/* /etc/ssh/ restorecon -v /etc/ssh/ /usr/sbin/sshd systemctl start sshd ssh -V这段脚本里restorecon -v是必须的因为备份的host key在拷贝过程中可能被改了安全上下文不恢复标签sshd会拒绝读取。回滚脚本执行完如果ssh -V回到了7.4p1再测一次登录整个回滚就闭环了。我自己的习惯是把备份的二进制、配置、密钥打包成ssh_backup_$(date %Y%m%d).tar.gz存到/root下保持至少一个月确认新版稳定后再删。这套流程走了几十台机器除了第一次踩了SELinux标签坑后面基本没翻过车。如果你要在欧拉或者麒麟这些同样源于RHEL 7的发行版上操作步骤完全可以复用区别只在yum源地址和selinux策略包的名字上。希望帮到你。本文还有配套的精品资源点击获取
返回列表