看到这个标题的你一定很疑惑,俺也很疑惑,但是它确确实实就是发生了。

今天上班处理了2(+1)个故障工单,都是服务器ssh连接不上,共涉及一台物理服务器,三台虚拟服务器,都是同样的问题——为了编译Nginx,先编译了某个版本的openssl,替换了系统的openssl,导致NetworkManager服务出问题,进而导致ssh服务出问题,所以无法远程连接。

幸好我们部门还有物理的方式访问服务器,排查问题。通过history看了下先前操作,这几台机子的操作如出一辙,都是将自己编译的libssl库放在/usr/lib64/openssl下,然后通过链接的方式,将编译出来的openssl相关库和可执行文件替换了系统原本的库和引用。

好家伙,怪不得江湖上看一眼对方出招就知道对方是哪个门派的,我看一眼也知道了操作这几台服务器的人应该是看的同一篇文档。

其具体的影响链条是,NetworkManager服务使用到了libcurl,而libcurl又用到了libssl,但新编译的libssl里面的某东西版本不符合libcurl的需求,导致NetworkManager起不来。NetworkManager起不来,网络就不通,看到的所有网口状态都是down,sshd一是没有网口来监听,二是依赖的(自己编译的openssl里的)libcrypto没有被正确地链接(或者版本不满足),导致sshd也起不来。

跟外包的师傅沟通了下,得知他们那边的要求是,要用1.1.1w版本的openssl,编译Nginx。

我寻思1.1.1w版本的openssl只是用来编译一个Nginx的话,非得扬了系统的openssl嘛。好在我虽然是运维,但也是开发出身,也略知一二。

编译Nginx

当下载了nginx的源代码,并解压后,执行一下configure,检查一下编译环境

1初配置.webp

需要先明确一下,nginx的三个重要依赖库分别是pcre, openssl和zlib

如果最后出现了这个,则是说明缺pcre

2缺pcre.webp

当然,可以通过在configure时加上参数--with-pcre,引用pcre源代码的目录来解决,或者通过系统的包管理器来安装pcre的开发套件。

apt list | grep pcre

3包管理里面的pcre库.webp

指定一个安装目录(--prefix),我把它安装到根目录。此外还指定了pcre的路径

4指定安装路径和pcre路径.webp

检查完毕后,大抵会看到openssl其实并没有使用到。只有当编译参数里面用到了--with-http_ssl_module时,才会使用openssl

5没使用openssl.webp

首先把指定版本的openssl源代码解压出来

6解压openssl源码.webp

配置编译环境时,加上--with-openssl参数,引用openssl源码的路径。然后,对我自己的机子而言,配置nginx编译环境的指令就是

./configure --prefix=/nginx --with-pcre=/home/leaf/Downloads/nginx/pcre2-10.44 --with-http_ssl_module --with-openssl=/home/leaf/Downloads/nginx/openssl-1.1.1w

在输出就能看到引用的openssl库源码路径

7编译选项里面openssl源码路径.webp

最后即编译,安装

make
make install

然后就能在--prefix参数指定的目录下面见到nginx了,我这里设置的路径是根目录下/nginx

完成后,去看一下nginx的版本,其基于的openssl版本便已经是1.1.1w了。

8查看nginx的openssl版本.webp

如果自行编译的openssl只是为了编译某个应用程序,而不是提供给整个系统全局使用的话,完全没有必要也不应该去更改甚至替换系统里的openssl库。