news 2026/10/13 5:42:01

OpenSSL 1.1.1 离线安装包制作与内网部署实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
OpenSSL 1.1.1 离线安装包制作与内网部署实战

简介:本资源为 openssl 1.1.1 离线安装包,面向需要在无外网或受限网络环境中部署 OpenSSL 的运维、后端开发及安全测试人员,解决源码编译安装时依赖下载困难、版本不匹配等问题。压缩包共约 2000 个文件,整体 11.37MB,以 C 源码(944 个)与头文件(269 个)为核心,辅以大量 POD 文档、Perl 脚本、配置模板及少量 PEM 证书样例、汇编与测试用例,覆盖库实现、文档说明与构建脚本等模块。解压后进入目录,执行 ./config --prefix=/usr/local/openssl1.1 --openssldir=/usr/local/openssl1.1/ssl,再 make -j$(nproc) 与 sudo make install 即可完成编译安装。目前已有 957 人学习下载,适合希望掌握源码编译流程、自定义安装路径并排查依赖问题的读者参考,目录结构完整,便于按模块查阅与二次构建。

1. openssl 1.1.1 离线安装包:内网机器上那套绕不开的编译活

机房里有台 CentOS 7 的构建机,网卡是通的但只放行了内网 yum 源,yum install openssl-devel拉下来的还是 1.0.2k。业务侧编译某个中间件时直接报undefined reference to 'OPENSSL_init_ssl',因为代码里用了 1.1.1 才引入的初始化接口。这时候你手里能用的只有一台能上网的笔记本和一个 U 盘,剩下的活就是自己攒一个 openssl 1.1.1 离线安装包,拷进去编译、安装、让动态库被正确找到。这篇笔记讲的就是这条链路:源码包怎么选、依赖怎么备齐、configure 参数怎么定、装完为什么openssl version还是老版本、以及升级后哪些东西会连带翻车。适合经常在内网、隔离网、信创环境里做基础库替换的运维和构建工程师,也适合第一次被libssl.so.1.1: cannot open shared object file卡住的开发。

2. 离线包到底装什么:源码、依赖和目录规划

2.1 为什么是源码编译而不是找现成 rpm

很多人第一反应是去搜「openssl 1.1.1 rpm 离线包」,找到一堆第三方打包的.rpm,拷进去rpm -ivh一装,看着挺省事。但这条路在真实环境里翻车概率很高。第一,第三方 rpm 的编译参数你不可控,--prefix可能是/usr/local,也可能是/opt,装完openssl version指向哪里全看打包者心情。第二,rpm 的依赖链是写死的,目标机器缺libcom_err或者 glibc 版本对不上,rpm -ivh直接甩一堆Failed dependencies,你还得再去找依赖的离线包,越滚越大。第三,也是最要命的,很多业务是静态链接或者指定路径链接 openssl 的,rpm 装到系统默认路径反而和业务预期冲突。

源码编译的好处是路径、参数、编译选项全部自己说了算,产出的东西是一个自包含的目录,拷到哪台机器都能用,不污染系统包管理。代价是要在目标机器上装编译工具链,或者在一台同架构的机器上编好再拷二进制过去。我一般选后者:找一台和目标机 glibc 版本一致的编译机,编完打包整个--prefix目录,目标机只需要解压和配环境变量,连 gcc 都不用装。

这里有个前提要确认清楚:目标机的 CPU 架构和 glibc 版本。uname -m看架构,ldd --version看 glibc。openssl 1.1.1 对 glibc 的要求不高,2.17 以上基本都能跑,CentOS 7 自带 2.17,没问题。但如果编译机是 glibc 2.28 编出来的,拷到 2.17 的机器上大概率报GLIBC_2.28 not found,这就是血泪经验——编译机和目标机的 glibc 版本必须对齐,宁可找台老机器编。

2.2 离线包该包含哪些文件

一个能自洽的 openssl 1.1.1 离线安装包,我一般按这个清单准备:

文件/目录作用是否必需
openssl-1.1.1w.tar.gz源码包必需
perlconfigure 脚本依赖 perl目标机无 perl 时必需
make / gcc编译工具链目标机编译时必需
zlib-devel启用 zlib 压缩支持可选,但建议带
编译产物目录已编译好的 prefix 目录免编译方案必需
install.sh安装脚本建议

源码包版本我一般锁 1.1.1w,这是 1.1.1 系列的最后一个版本,安全补丁最全。不要去下 1.1.1a 这种早期版本,CVE 一堆。下载渠道就是 openssl 官网的 source 页面,或者用wget直接拉https://www.openssl.org/source/openssl-1.1.1w.tar.gz。注意官网现在主推 3.x,1.1.1 系列已经进入维护末期,但很多老业务还锁在 1.1.1 的 ABI 上,不能随便升 3.x,因为 3.x 的 API 有破坏性变更。

提示:1.1.1 系列官方支持已经结束,新项目建议直接上 3.x。但如果你的业务依赖 1.1.1 的 ABI,升级前务必确认所有动态链接的库都兼容。

2.3 目录规划:prefix 选哪里

--prefix的选择直接决定了后面环境变量怎么配、动态库怎么找。三种常见方案:

一是装到/usr/local/openssl-1.1.1,独立目录,不碰系统自带的/usr/bin/openssl。好处是干净,坏处是业务编译时要显式指定-I和-L,动态库运行时还要配LD_LIBRARY_PATH或者写进/etc/ld.so.conf.d/。

二是直接覆盖/usr,--prefix=/usr,装完系统openssl命令就变成 1.1.1 了。看着省事,但风险极大——系统里其他依赖 1.0.2 的程序可能直接崩,尤其是 ssh、curl 这些基础组件。除非你非常清楚系统里所有 openssl 的消费者,否则别这么干。

三是装到/opt/openssl,然后通过 alternatives 或者软链接切换。这是比较折中的做法,但 alternatives 管理的是命令,动态库的查找还是得靠 ldconfig。

我一般选第一种,prefix 用/usr/local/openssl-1.1.1,然后单独写一个openssl.sh环境脚本,需要用的业务source一下就行,互不干扰。

3. 从源码到可用:编译参数与打包步骤

3.1 编译机上的完整操作流程

假设编译机是 CentOS 7,已经装了 gcc、make、perl。先把源码包传上去,解压、配置、编译、安装,一条龙:

# 解压源码 tar -zxvf openssl-1.1.1w.tar.gz cd openssl-1.1.1w # 配置:指定 prefix,启用共享库,启用 zlib ./config \ --prefix=/usr/local/openssl-1.1.1 \ --openssldir=/usr/local/openssl-1.1.1/ssl \ shared \ zlib \ -fPIC # 编译,-j 后面跟 CPU 核数,加快速度 make -j$(nproc) # 安装到 prefix 目录 make install # 验证编译产物 /usr/local/openssl-1.1.1/bin/openssl version

--prefix指定安装根目录,--openssldir指定配置文件目录,这两个最好分开写清楚,不然后面找openssl.cnf会找半天。shared是关键,不加这个只生成静态库libssl.a和libcrypto.a,业务如果动态链接就找不到.so。zlib启用压缩支持,TLS 层的数据压缩会用到,虽然现在压缩在 TLS 里不推荐开(有 CRIME 攻击),但库层面支持着没坏处。-fPIC是位置无关代码,生成共享库必须加,不加在某些平台上链接会报错。

make -j$(nproc)里的$(nproc)是当前 CPU 核数,编译 openssl 大概需要几分钟,核多的机器能快不少。make install会把bin、lib、include、ssl几个目录铺到 prefix 下。

编译完先别急着打包,验证一下产物:

# 看动态库是否生成 ls -l /usr/local/openssl-1.1.1/lib/ # 应该能看到 libssl.so.1.1 和 libcrypto.so.1.1 # 看版本 /usr/local/openssl-1.1.1/bin/openssl version -a # 输出里 OpenSSL 1.1.1w 和 built on 时间要对

如果lib目录下只有.a没有.so,说明shared没生效,回去检查 config 那步是不是漏了。如果openssl version报error while loading shared libraries,说明编译机自己都没找到库,用ldd看一下依赖路径。

3.2 打包成离线安装包

编译验证通过后,把整个 prefix 目录打包,再附上安装脚本:

# 打包 prefix 目录 cd /usr/local tar -czvf openssl-1.1.1-offline.tar.gz openssl-1.1.1/ # 查看包大小,一般在 10MB 以内 ls -lh openssl-1.1.1-offline.tar.gz

安装脚本install.sh负责在目标机上解压、配环境、刷新动态库缓存:

#!/bin/bash set -e PREFIX=/usr/local/openssl-1.1.1 PKG=openssl-1.1.1-offline.tar.gz # 解压到 /usr/local tar -xzvf $PKG -C /usr/local/ # 写 ld.so.conf,让系统能找到动态库 echo "$PREFIX/lib" > /etc/ld.so.conf.d/openssl-1.1.1.conf ldconfig # 配环境变量,追加到 /etc/profile.d/ cat > /etc/profile.d/openssl-1.1.1.sh <<EOF export PATH=$PREFIX/bin:\$PATH export LD_LIBRARY_PATH=$PREFIX/lib:\$LD_LIBRARY_PATH EOF chmod +x /etc/profile.d/openssl-1.1.1.sh echo "install done, run: source /etc/profile.d/openssl-1.1.1.sh"

set -e让脚本遇到错误立即退出,避免半装状态。ld.so.conf.d那个文件是给系统动态链接器看的,ldconfig刷新缓存后,所有程序运行时都能找到libssl.so.1.1。/etc/profile.d/下的脚本会在登录时自动 source,PATH和LD_LIBRARY_PATH都配好。注意LD_LIBRARY_PATH是双刃剑,全局设置可能影响其他程序,如果只想给特定业务用,就别写进 profile.d,让业务自己 source。

注意:ldconfig之后如果系统里原本有 1.0.2 的库,两个版本的libssl.so会共存,但 soname 不同(libssl.so.10vslibssl.so.1.1),不会直接冲突。真正冲突的是头文件和命令,所以 PATH 的顺序很重要。

3.3 目标机上的安装与验证

把openssl-1.1.1-offline.tar.gz和install.sh拷到目标机,执行:

chmod +x install.sh ./install.sh source /etc/profile.d/openssl-1.1.1.sh # 验证 which openssl # 应该输出 /usr/local/openssl-1.1.1/bin/openssl openssl version # 应该输出 OpenSSL 1.1.1w # 验证动态库能被找到 ldd $(which openssl) | grep ssl # 应该指向 /usr/local/openssl-1.1.1/lib/libssl.so.1.1

which openssl确认 PATH 生效,openssl version确认版本对,ldd确认动态库路径对。这三步都过了,基础安装就算成了。如果which还是/usr/bin/openssl,说明 PATH 没生效,检查 profile.d 脚本有没有执行权限,或者当前 shell 是不是没重新登录。

4. 装完为什么还是老版本:路径、缓存与链接的排查

4.1 openssl version 显示旧版本的四种原因

这是最高频的翻车现场:明明装完了,openssl version还是 1.0.2k。按概率排,原因有四种。

第一种,PATH 顺序问题。系统/usr/bin在 PATH 里排在/usr/local/openssl-1.1.1/bin前面,shell 先找到旧的。echo $PATH看一眼顺序,把新路径往前挪,或者直接用绝对路径/usr/local/openssl-1.1.1/bin/openssl version验证。

第二种,hash 缓存。bash 会缓存命令路径,hash -r清一下再试。这个坑很隐蔽,尤其是你在同一个 shell 里先跑过旧命令再改 PATH,bash 记着旧路径不放。

第三种,profile.d 脚本没被执行。/etc/profile.d/只在登录 shell 里 source,如果你是用su切用户或者非交互式 ssh 执行命令,可能不加载。手动source /etc/profile.d/openssl-1.1.1.sh一下。

第四种,装是装了但装错了地方。--prefix写错,或者make install时权限不够装到了别处。find / -name "openssl" -type f 2>/dev/null全局搜一下,看新版本到底在哪。

4.2 动态库找不到的排查链路

业务启动时报error while loading shared libraries: libssl.so.1.1: cannot open shared object file,说明运行时链接器找不到库。排查顺序:

先ldd /path/to/your/binary | grep ssl,看它期望的库路径是什么。如果显示not found,说明链接器搜索路径里没有。链接器的搜索路径由/etc/ld.so.conf及其include的conf.d目录决定,加上LD_LIBRARY_PATH环境变量。ldconfig -p | grep libssl看当前缓存里注册了哪些版本的 libssl。

如果ldconfig -p里没有 1.1,说明/etc/ld.so.conf.d/openssl-1.1.1.conf没写或者没跑ldconfig。补上再跑一次。如果ldconfig -p里有但业务还是找不到,检查业务的启动脚本是不是清空了LD_LIBRARY_PATH,或者用了setuid导致环境变量被忽略。

还有一种情况是业务编译时链接的是静态库,但运行时又去找动态库,这种混合链接的坑最难查。readelf -d /path/to/binary | grep NEEDED看它到底依赖哪些 so,比ldd更准。

4.3 升级后 ssh、curl 挂了的应急处理

如果你手贱把 openssl 装到了/usr覆盖了系统库,重启后 ssh 连不上、curl 报错,别慌。系统里通常还留着旧版本的库文件,只是软链接被改了。ls -l /usr/lib64/libssl.so*看软链接指向,把指向 1.1 的链接改回 1.0.2 的实体文件。如果实体文件也被覆盖了,那就得从同版本系统的另一台机器拷libssl.so.10和libcrypto.so.10回来,或者进 rescue 模式用安装盘恢复。

预防这个问题的办法很简单:永远不要--prefix=/usr,永远装独立目录。系统自带的 openssl 就让它待着,业务要用新版本就显式指定路径。这是最省心的策略,没有之一。

5. 避坑清单:五个真实踩过的坑

坑一:编译机 glibc 版本高于目标机,拷过去报GLIBC_2.28 not found。现象是二进制直接起不来,ldd报版本不匹配。原因是 openssl 编译时链接了编译机的 glibc 符号。解决办法是编译机和目标机 glibc 版本对齐,或者用 Docker 起一个和目标机同版本的基础镜像来编译。我一般用centos:7镜像编译,产出的二进制在 CentOS 7 上跑没问题。

坑二:make install后openssl version正常,但业务编译时#include <openssl/ssl.h>找不到头文件。现象是 gcc 报openssl/ssl.h: No such file or directory。原因是头文件装在 prefix 的include下,但 gcc 默认不搜这个路径。解决办法是编译业务时加-I/usr/local/openssl-1.1.1/include,链接时加-L/usr/local/openssl-1.1.1/lib -lssl -lcrypto。如果业务用 pkg-config,把 prefix 下的lib/pkgconfig加进PKG_CONFIG_PATH。

坑三:ldconfig跑了但ldconfig -p里看不到新库。现象是配置文件写了,命令也跑了,就是没注册。原因是/etc/ld.so.conf.d/下的文件名必须以.conf结尾,写成openssl-1.1.1不带后缀会被忽略。另外文件内容必须是目录路径,不能写具体的.so文件路径。改成echo "/usr/local/openssl-1.1.1/lib" > /etc/ld.so.conf.d/openssl-1.1.1.conf再ldconfig。

坑四:业务用 Python 的ssl模块,升级后import ssl报错。现象是 Python 启动就崩,报ImportError: libssl.so.1.1: cannot open shared object file。原因是 Python 的_ssl扩展模块编译时链接了特定版本的 openssl,升级后 soname 对不上。解决办法是重新编译 Python,或者用LD_LIBRARY_PATH指向新库。但更稳妥的做法是别动系统 Python 依赖的 openssl,给业务单独配虚拟环境。

坑五:离线包拷到目标机解压后权限全丢,脚本执行报Permission denied。现象是install.sh跑不了,或者解压出来的bin/openssl没有执行权限。原因是 tar 打包时没保留权限,或者 U 盘文件系统(FAT32)不支持 Unix 权限位。解决办法是打包时用tar -czpvf,p保留权限;拷贝时用scp或者打包成tar再传,别直接拖 U 盘。如果已经丢了权限,chmod +x补一下。

6. 让离线包更省心:版本锁定与自动化校验

装完能跑只是及格线,真正省心的是让这套离线包可复现、可校验、可回滚。我现在的习惯是在打包阶段就把版本信息和校验和固化下来,目标机安装前先验一遍,避免拷错包或者包损坏。

具体做法是在 prefix 目录下放一个BUILD_INFO文件,记录编译时间、编译机、glibc 版本、configure 参数:

cat > /usr/local/openssl-1.1.1/BUILD_INFO <<EOF version=1.1.1w build_time=$(date -u +%Y-%m-%dT%H:%M:%SZ) build_host=$(hostname) glibc=$(ldd --version | head -1 | awk '{print $NF}') configure=--prefix=/usr/local/openssl-1.1.1 --openssldir=/usr/local/openssl-1.1.1/ssl shared zlib -fPIC EOF

然后打包时生成 SHA256 校验和,安装脚本里先校验再解压:

# 打包时生成校验和 sha256sum openssl-1.1.1-offline.tar.gz > openssl-1.1.1-offline.tar.gz.sha256 # 安装脚本里校验 sha256sum -c openssl-1.1.1-offline.tar.gz.sha256 || { echo "checksum mismatch, abort" exit 1 }

sha256sum -c会读校验和文件并比对,不匹配就退出。这一步能挡住传输损坏和拷错版本的问题,尤其是 U 盘拷贝场景,文件损坏概率不低。

回滚方案也要提前想好。因为我们是独立 prefix 安装,回滚其实就是把/etc/ld.so.conf.d/openssl-1.1.1.conf删掉、ldconfig刷新、把 profile.d 脚本移走,业务就回到系统自带的 openssl 了。prefix 目录留着不删,下次要用再配回来。这种非侵入式安装的最大好处就是回滚成本极低,不用重装系统。

最后一个技巧是关于多版本共存的。如果一台机器上既要跑依赖 1.1.1 的新业务,又要跑依赖 1.0.2 的老业务,别去折腾全局 PATH,让每个业务在自己的启动脚本里显式指定:

# 新业务启动脚本 export LD_LIBRARY_PATH=/usr/local/openssl-1.1.1/lib:$LD_LIBRARY_PATH export PATH=/usr/local/openssl-1.1.1/bin:$PATH exec /path/to/new-service # 老业务启动脚本保持原样,不 source 任何 openssl 环境 exec /path/to/old-service

这样两个业务各用各的库,互不干扰。全局环境保持系统默认,谁也别动。这套做法我在好几个隔离网环境里用了几年,没再出过因为 openssl 版本导致的连环故障。编译参数和目录规划一次做对,后面就是复制粘贴的活。希望帮到你。

本文还有配套的精品资源,点击获取

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/13 5:41:03

从模糊代号到最小闭环:我用四层问题拆解一个叫“rea”的项目

有人丢给你一个项目&#xff0c;名字只有三个字母&#xff1a;“rea”。没有文档&#xff0c;没有需求清单&#xff0c;没有背景介绍&#xff0c;就一个词。你会怎么办&#xff1f;直接开干&#xff1f;那你大概率会踩进深坑。我这些年看到太多从“看不懂的代号”到“重写系统”…

作者头像 李华
网站建设 2026/10/13 5:40:35

大模型Agent技能库工程实战:从Prompt硬扛到可复用执行层

如果最近你也在折腾大模型应用&#xff0c;多半和我一样绕不开“agent-skills”这个词。我最早看到“agent-skills”时还以为是某个炫酷的模型能力包&#xff0c;后来动手做了一整套基于技能库&#xff08;skills&#xff09;的AI助手才发现&#xff0c;它真正解决的是大模型“…

作者头像 李华
网站建设 2026/10/13 5:39:38

Oracle 11g 64位下 exp.exe 与 imp.exe 实战:老DBA的导出导入避坑指南

简介&#xff1a;这份资源是Oracle 11g 64位版本的bin目录完整打包&#xff0c;面向需要做数据库导入导出、备份迁移的DBA与开发人员&#xff0c;尤其适合习惯在PL/SQL Developer中通过图形界面调用命令行工具的用户。包内共691个文件&#xff0c;以372个dll动态库、118个exe可…

作者头像 李华
网站建设 2026/10/13 5:39:22

从零手写Cortex-M抢占式调度器:任务切换与实现详解

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/13 5:38:33

CS2启动器Overflow闪退根源与显存调度修复指南

1. 问题本质&#xff1a;这不是“闪退”&#xff0c;而是内存管理机制被触发的保护性中断 “CS2更新后Valve界面闪退、Overflow溢出错误”——这个标题里藏着一个被广泛误读的关键点。很多用户一看到“闪退”就下意识归因于显卡驱动或系统兼容性&#xff0c;甚至反复重装客户端…

作者头像 李华
网站建设 2026/10/13 5:38:30

Spring Boot集成AI对话接口:从零搭建HR政策问答机器人

1. 项目定位&#xff1a;为什么是 Spring Boot AI 对话接口1.1 HR 政策问答机器人的核心需求拆解这个项目叫“AI全栈12-02”&#xff0c;名字里已经透露出完整的信息&#xff1a;它属于一条 AI 全栈学习路线的中期实践&#xff0c;前一步多半是把模型 API 跑通&#xff0c;从这…

作者头像 李华