ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

CentOS 7.6源码编译升级OpenSSL 1.1.1m全指南

2026/9/1 2:57:31 拓冰建站 浏览量
CentOS 7.6源码编译升级OpenSSL 1.1.1m全指南 简介OpenSSL是互联网安全通信的基础密码库内置RSA、DSA、ECC等主流加密算法并实现SSL/TLS协议、密钥与证书封装管理等功能。该压缩包提供截至2021年12月27日的最新稳定版1.1.1m源码面向Linux系统管理员、运维工程师和安全开发人员可用于搭建、加固或定制加密通信环境。压缩包为tar.gz格式约9.39MB包含完整源码树、构建配置脚本以及命令行工具实现可自行编译以调整安装路径和启用特性。已有532人学习下载。获取后可掌握从源码部署OpenSSL的完整流程借助其证书管理、密钥生成、哈希与消息认证码计算等能力为Web、邮件等网络服务提供可靠的TLS支持还可利用内置测试程序验证算法实现或通过openssl命令完成连接测试、证书签发等日常运维。该版本同步修复了已知安全漏洞并优化性能是维护数据传输机密性与完整性的重要基础组件。 把openssl-1.1.1m.tar.gz这个包从官网拖下来在 CentOS 7.6 上编译安装我前后踩了四五个坑才把整个环境理顺。这篇博文就把这次升级的完整过程写出来重点说清楚为什么用老版本、编译时那些参数怎么选、装完后又有一堆服务报错该怎么收尾。适合正在给 CentOS 7 系机器升级 OpenSSL、又不想被 1.1.1m 的源码包折腾到怀疑人生的人参考。先说结论OpenSSL 1.1.1m 属于 1.1.1 系列里比较后期的稳定版CentOS 7.6 自带的 OpenSSL 1.0.2k 在很多新软件面前已经不够用了。从源码编译安装这件事本身不难难的是编译参数、动态库路径、以及升级后对系统里其他依赖旧版本组件的连锁反应。下面按我实际操作时的顺序展开。1. 项目背景为什么还要装 1.1.1m 而不是直接上 3.x1.1 从版本线看 1.1.1m 的定位很多人第一次看到openssl-1.1.1m.tar.gz会觉得奇怪OpenSSL 3.x 都出了这么久了为什么还有人抱着 1.1.1m 不放我当时选择它的原因很简单它是 1.1.1 系列里的一个维护版本1.1.1 系列是 LTS 版本线生命周期很长很多企业内部系统、PHP 扩展、老版本 Nginx 模块在 1.1.1 上验证充分直接跳到 3.x 可能遇到 API 不兼容问题。1.1.1m 这个版本发布于 2021 年底修复了一批安全问题。对于生产环境来说比最新版本更重要的是“已经被大量验证过”这正是 CentOS 7.6 这类老系统上最看重的。如果你手头有 PHP 需要升级到支持 OpenSSL 1.1.1那么 1.1.1m 是性价比很高的选择。从功能上看1.1.1m 完整支持 TLS 1.3支持X25519、ChaCha20-Poly1305这些现代加密套件性能也比 1.0.2 时代好了不少。对于大多数业务场景它不会成为短板。1.2 升级 OpenSSL 前先想清楚替换系统库还是独立安装这是我在这次升级里最重要的一条经验不要直接去替换/usr/bin/openssl。CentOS 7.6 上 yum、curl、sshd 等大量系统组件都是链着系统自带 OpenSSL 1.0.2k 编译出来的你贸然把/usr/bin/openssl换成 1.1.1m最直接的后果是 yum 直接报错甚至 sshd 都可能起不来。所以我的方案是独立安装到/usr/local/openssl-1.1.1m然后通过 PATH 和动态库搜索路径让新版本“优先”被使用而不是彻底替换系统的旧版本。这样系统底层组件继续用它们依赖的 1.0.2k新编译的软件可以用 1.1.1m两边互不干扰。如果你需要的是整个系统彻底迁移那就得另外评估所有依赖方的兼容性属于大工程本文不展开。2. 编译前的依赖与准备2.1 “perl is needed by openssl”到底卡在哪如果你在 CentOS 7.6 上直接跑 OpenSSL 的 configure也就是./config很可能看到类似perl is needed by openssl的提示。这不是说系统里没有 perl而是缺少 Perl 的模块或者编译相关组件。OpenSSL 1.1.1m 的构建脚本依赖 Perl 来生成部分头文件和汇编代码具体来说需要Test::More模块。CentOS 7.6 最小化安装时通常没有这个模块即使有 perl 主程序模块不齐全也会报错。我当时的处理方式是用 yum 补装yum install -y perl perl-core perl-Test-Simple perl-IPC-Cmd这里有个小坑perl-Core和perl-IPC-Cmd有时候在默认软件源里名字不太一样如果提示找不到包先执行yum list perl-* | grep IPC看看实际包名。这一步做好了后面 configure 才能顺利跑完。2.2 工具链与构建环境核对除了 Perl编译 OpenSSL 还需要 gcc、make、以及 zlib 开发头文件。很多人忽略 zlib 依赖导致编译出来的 OpenSSL 不支持压缩运行时倒是没大问题但某些依赖压缩特性的功能会异常。我列的完整准备命令如下yum install -y gcc gcc-c make zlib-devel安装完可以快速检查一下gcc --version perl -v | head -2 ls /usr/include/zlib.h确认这三个都正常后再继续执行 configure。这一步别嫌啰嗦前期环境有问题后面编译报错会非常难排查。实测下来在 CentOS 7.6 上编译 OpenSSL 1.1.1m 并不需要额外安装太多东西上面这些就已经够了。3. 源码编译与安装实操3.1 configure 参数取舍解压源码包tar -xzf openssl-1.1.1m.tar.gz cd openssl-1.1.1m接下来是重头戏configure 参数。直接./config能编译成功但那只是“能跑”的版本不是“好用”的版本。我使用的参数是./config --prefix/usr/local/openssl-1.1.1m \ --openssldir/usr/local/openssl-1.1.1m/ssl \ shared zlib \ -Wl,-rpath,/usr/local/openssl-1.1.1m/lib各项参数的含义--prefix指定安装目录这个目录决定了make install后所有文件放哪里。--openssldirOpenSSL 运行时配置文件和证书目录的地址默认是prefix/ssl我显式写出来是为了后面找openssl.cnf不用猜。shared生成动态链接库.so这是必选项。如果不加最后只有静态库.aPHP、Nginx 这类软件根本没法正常加载。zlib启用压缩支持。-Wl,-rpath给编译出的可执行文件写入动态库搜索路径避免运行时找不到.so。这一步很关键很多人在编译安装后执行openssl version失败就是因为动态库路径不对。这里也说明一下CentOS 7.6 下有时候还需要加no-weak-ssl-ciphers这类安全选项但考虑到兼容性我这次没有启用避免某些老客户端握手失败。如果你的环境对安全性要求高可以自行评估。3.2 make 与 make install 及动态库链接configure 通过后开始编译make -j$(nproc)-j$(nproc)是并行编译CentOS 7.6 上如果是 4 核机器编译速度会快很多。整个编译过程大概几分钟到十几分钟不等取决于机器配置。看到以下提示说明编译完成OpenSSL 1.1.1m ready然后安装make install安装完成后目录结构如下/usr/local/openssl-1.1.1m/ ├── bin/openssl ├── include/openssl/*.h └── lib/ ├── libcrypto.so ├── libssl.so └── pkgconfig/下一步很关键把动态库路径加入系统加载器配置。编辑/etc/ld.so.conf.d/openssl-1.1.1m.confecho /usr/local/openssl-1.1.1m/lib /etc/ld.so.conf.d/openssl-1.1.1m.conf ldconfig再调整 PATH 环境变量让新版本的openssl命令优先被找到。我习惯写到/etc/profile.d/openssl.shexport PATH/usr/local/openssl-1.1.1m/bin:$PATH这样所有新登录的 shell 都会自动使用新版本。3.3 验证升级结果重启一个终端执行openssl version正常情况下会输出OpenSSL 1.1.1m 14 Dec 2021如果想确认编译时用的配置是否生效执行openssl version -a重点看下面几行OPENSSLDIR: /usr/local/openssl-1.1.1m/ssl enginesdir: /usr/local/openssl-1.1.1m/lib/engines-1.1如果OPENSSLDIR指向的还是系统默认路径说明 configure 参数没生效需要回炉重来。这个验证步骤不要省我见过很多人装完以后openssl version显示新版本但程序运行时调用的还是旧库就是因为 OPENSSLDIR 不对。4. 升级后最常见的连锁问题4.1 git/curl 拉取失败报 “unexpected eof while reading”升级到 1.1.1m 之后最常被问到的问题之一就是 git 在拉取远程仓库时出现error: rpc failed; curl 56 OpenSSL SSL_read: error:0A000126:SSL routines::unexpected eof while reading我第一次看到这个错误时第一反应是 OpenSSL 编译坏了。排查后确认不是编译问题而是新版本 OpenSSL 在对端 TLS 协议协商时更严格对端服务器或者中间代理返回了一个异常的 EOF。解决办法有几个方向如果是 git 访问 GitHub 这类站点先检查 git 版本老版本 git 的 http 实现与 OpenSSL 1.1.1 配合不佳建议升级 git。检查对端服务是否只支持 TLS 1.0/1.1OpenSSL 1.1.1 默认策略下对这些老协议比较敏感必要时临时用openssl s_client -tls1验证。如果是内网代理抓包看是不是代理主动断连。实际最有效的方法是用GIT_TRACE_CURL1打开 curl 日志定位是哪一层断的。这个报错在我处理过的案子里80% 都不是 OpenSSL 本身的问题而是对端协议或者代理策略。4.2 Nginx/PHP 等服务如何让新版本生效很多人的需求是“PHP 升级 OpenSSL 至 1.1.1”但忘了关键一步PHP 扩展里如果开启了 openssl它在编译时会链接 openssl 头文件和动态库而 PHP 是通过某种方式编译的比如./configure --with-openssl。如果之前编译 PHP 时链接的是系统的 1.0.2k那么即使我们现在把/usr/local/openssl-1.1.1m/lib加入了 ldconfigPHP 也不会自动切换因为它编译进.so的动态库路径已经是旧的了。正确的做法是重编 PHP或者重编对应的 openssl 扩展cd /path/to/php-7.x/ext/openssl phpize ./configure --with-openssl/usr/local/openssl-1.1.1m make make install这里有一个实操心得--with-openssl的路径最好写到prefix那层不要只写到include。因为 configure 脚本会根据这个路径去找include/openssl/ssl.h和lib/libssl.so。只填/usr/local/openssl-1.1.1m就行会自动拼接。验证是否生效可以写一段 PHP 脚本执行?php echo OPENSSL_VERSION_TEXT, \n;输出OpenSSL 1.1.1m就说明 PHP 侧已经切换成功。Nginx 在编译 http_ssl_module 时同理需要指定--with-openssl/usr/local/openssl-1.1.1m。4.3 应用编译时 “checking openssl header version” 对不上很多第三方软件在编译时会有一步检查日志类似checking openssl header version... 100020bf (OpenSSL 1.0.2k 26 Jan 2017)这是典型的“头文件目录指向旧版本”的问题。原因是 configure 脚本默认找/usr/include/openssl/opensslv.h这个文件还是老的。解决办法是在编译前导出环境变量export CPPFLAGS-I/usr/local/openssl-1.1.1m/include export LDFLAGS-L/usr/local/openssl-1.1.1m/lib -Wl,-rpath,/usr/local/openssl-1.1.1m/lib export PKG_CONFIG_PATH/usr/local/openssl-1.1.1m/lib/pkgconfig再重新运行 configure。这里要注意的是顺序export 必须在 configure 之前完成否则 configure 检测到的头文件路径还是旧的。这个坑我在编译一个内部工具时踩了好几次后来习惯把这三个变量固定写到项目环境的env.sh里每次编译前先 source。4.4 系统安装包时提示依赖 openssl 某版本如果你在 CentOS 7.6 上用rpm -ivh安装某些 rpm 包可能会看到error: Failed dependencies: openssl 1.1.1 is needed by xxx这是因为 rpm 在检查依赖时默认登记的是/usr/bin/openssl这个二进制对应的版本。我们用源码方式安装 OpenSSL 之后rpm 数据库并没有感知到新版本。解决思路有两个使用--nodeps强制安装但我强烈不建议在生产环境这么干依赖链条断掉后面会很麻烦。更稳妥的方式是找到对应的新版 rpm 包来装或者通过 yum 源升级系统自带的 openssl 版本。CentOS 7 官方源到 EOL 前也没有把 openssl 升到 1.1.1所以很多时候确实只能另想办法。我实际用的折中方案是新程序独立编译到/usr/local下业务侧的依赖全部指向新版本系统层面的 rpm 包不强行升级。这样依赖检查的问题基本不碰也不会破坏系统组件。5. 从 1.1.1m 走向 3.x迁移要点5.1 3.x 带来了什么变化如果将来你决定从 1.1.1m 升级到 OpenSSL 3.x需要注意几个方面。3.x 采用了新的 Provider 架构传统算法被拆分到 legacy provider 里默认仅加载 default provider这导致 MD4、MDC2、Blowfish、CAST5、DES部分模式等算法在默认配置下直接不可用。如果你在 3.x 上跑老项目最常见的一个报错是error:0308010C:digital envelope routines::unsupported这就是老程序用了默认 provider 不支持的算法。解决方法是代码里显式加载 legacy provider或者用配置文件openssl_conf openssl_init [openssl_init] providers provider_sect [provider_sect] default default_sect legacy legacy_sect [default_sect] activate 1 [legacy_sect] activate 1其次OpenSSL 3.x 的很多函数标记为 deprecated虽然仍然编译通过但编译日志里会有一堆 deprecation 警告。如果项目里的代码是 1.0.2 时代写的直接升 3.x 会相当痛苦。这也是我这次仍然选择 1.1.1m 的另一个重要原因。5.2 迁移时的几个雷区DH参数长度3.x 默认要求 DH 参数至少 2048 位老程序里写死的 1024 位 DH 参数直接握手失败。证书签名算法3.x 默认安全级别提高使用 SHA1 签名的证书在不少场景下会被拒绝。兼容宏以前很多程序靠OPENSSL_VERSION_NUMBER 0x10100000L判断版本分支在 3.x 下这套逻辑很可能失效需要检查代码里所有版本判断点。如果你还在用 conda 管理 Python 环境系统升级 3.x 后还可能出现 conda 环境里的libssl.so与系统新库冲突的问题。常见的表现是import ssl报 symbol 找不到。这是因为 conda 环境打包或迁移到新机器时固化的libcrypto.so路径和系统版不一致。用conda create --clone创建独立环境时最好重新安装 openssl 相关依赖不要直接沿用旧环境的 tar.gz 包。6. 收尾根据经验给几点建议源码安装 OpenSSL 这件事最难的地方从来不是敲命令而是升级后对周边生态的影响。我在生产环境上维护了多个独立的 OpenSSL 安装目录每个目录对应不同的业务线版本需求。这样做的好处是互不干扰坏处是磁盘占用和运维复杂度会上升但对稳定性的收益很大。最后分享一个小细节每次编译前我都习惯用make clean清掉上一次的编译产物。别小看这一步如果 configure 参数改了而没 clean可能会有残留对象文件导致链接阶段出现极其诡异的报错。另外给服务器做快照再升级永远是值得推荐的习惯。本文还有配套的精品资源点击获取