发布于 

手动降级openssl:解决-Rails-部署的问题

简介

1、为什么要降 openssl 版本?

我的工程比较老,使用的还是 rails 3.2ruby 1.8(自己源码编译的),生产环境的应用服务器是 passenger。在安装 passenger时发生了错误(passenger-install-nginx-module 的安装方式):提示需要 ruby 支持 openssl

1
2
3
4
5
6
ossl_pkey_ec.c:815: error: ‘EC_GROUP_new_curve_GF2m’ undeclared (first use in this function)
ossl_pkey_ec.c:815: error: (Each undeclared identifier is reported only once
ossl_pkey_ec.c:815: error: for each function it appears in.)
make[1]: *** [ossl_pkey_ec.o] Error 1
make[1]: Leaving directory `/home/vagrant/ruby-1.8.7-p357/ext/openssl'
make: *** [all] Error 1

后面我查询了下面两篇文章,折腾了很久未能解决问题,最后无奈降级系统自带的 openssl 版本。

当前云服务器的系统是 centOS 6.10,默认安装了 openssl 1.0.x 版本,我需要在 ruby-1.8 环境下使用 openssl 0.9.8 系列版本。

2、我还尝试编译 ruby 源码中自带的 openssl

1
2
cd ruby-1.8.7/ext/openssl
ruby extconf.rb

报错:

=== OpenSSL for Ruby configurator ===
=== Checking for system dependent stuff… ===
checking for t_open() in -lnsl… no
checking for socket() in -lsocket… no
checking for assert.h… yes
=== Checking for required stuff… ===
checking for openssl/ssl.h… no
=== Checking for required stuff failed. ===
Makefile wasn’t created. Fix the errors above.

系统自带的 openssl 版本(OpenSSL 1.0.1e-fips 11 Feb 2013)和 ruby 版本去编译 openssl 扩展库不兼容,无法通过编译。

可以通过下面命令查看 openssl 版本:

1
openssl version

下面我们正式进入战斗。

安装低版本 openssl

1、下载 openssl-0.9.8

1
2
3
4
cd /usr/local
wget https://www.openssl.org/source/openssl-0.9.8e.tar.gz --no-check-certificate
tar -zxvf openssl-0.9.8e.tar.gz
cd openssl-0.9.8e

2、编译

1
2
3
./config --prefix=/usr/local/ssl -fPIC no-asm
make
make install

正常情况下,我们配置一下默认安装路径即可,但是这里我们加了两个参数 -fPICno-asm

  • no-asm 是为了解决类似 “md5-x86_64.s:41: Error: 0xd76aa478 out range of signed 32bit displacement” 的报错。

  • -fPIC 是为了解决类似 “/usr/local/ssl/lib/libssl.a: error adding symbols: Bad value” 的报错。

如果你使用 ./config --prefix=/usr/local/ssl 能够编译、安装正常就不需要加这两个参数。如果报错了,请先执行 make clean 操作。

1
2
3
4
5
我们都知道在生成一个动态库时需要指定 -fPIC,这是创建动态库所要求的,共享库被加载是在内存中的位置是不固定的,是一个相对的位置。
那么在生成静态库时通常不指定 -fPIC, 可是在64bit编译使用静态库就会提示需要 -fPIC 重新编译该库。
由于 openssl 编译静态库时,没有使用 -fPIC 选项,使得编译出来的静态库没有重定位能力。
这样在 64bit 机器上编译出来的静态库如果不指定-fPIC选项几乎全部不能使用。
因此需要重新加上 -fPIC 从新编译 openssl。

编译如果报找不到库的错误,请安装 libssl

1
yum install libssl-dev

3、备份之前 OpenSSL 版本的文件,以方便恢复

1
2
mv -f /usr/bin/openssl /usr/bin/openssl.old
mv -f /usr/include/openssl /usr/include/openssl.old

4、增加软链,指向新版本的 OpenSSL 路径

1
2
ln -s /usr/local/ssl/bin/openssl /usr/bin/openssl
ln -s /usr/local/ssl/include/openssl /usr/include/openssl

5、写入 ld 配置文件ld.so.conf

1
echo "/usr/local/ssl/lib">>/etc/ld.so.conf

可以看下 vim /etc/ld.so.conf 文件内容。

6、添加 so 库的路径,添加完成之后,运行ldconfig,将新增的 so 文件缓存到/etc/ld.so.cache中。

1
ldconfig -v

最后,确认版本是否正确。

1
openssl version -a

OpenSSL 0.9.8e 23 Feb 2007
built on: Thu Jan 5 11:13:28 CST 2023
platform: linux-x86_64

检查一下,ruby 是否带 openssl 模块:

1
ruby -ropenssl -e 'puts OpenSSL::OPENSSL_VERSION'

理论上还不行,别着急,接下来我们重新编译 ruby。

编译 ruby+openssl

编译 ruby + openssl 模块:

1
2
3
4
5
6
7
8
9
10
cd /usr/local/ruby-1.8.7
# 我之前编译过
make clean

# --prefix 指定ruby安装目录
# --with-openssl-dir 指定openssl目录(刚安装的 openssl)
./configure --enable-pthread --prefix=/usr/local --with-openssl-dir=/usr/local/ssl

make
make install

(可选操作)如果还是编译报错,可以尝试用下面这种方式进行修复:

1
2
3
4
# ruby 源码自带了 openssl 库,当然还有其他扩展库如 zlib
cd /usr/local/ruby-1.8.7/ext/openssl
ruby extconf.rb
make && make install

编译完成之后,也是修复成功了。如果这一步你还是无法通过编译,先放弃这个操作,直接看下面的内容去检测一下。

检测一下编译后的 ruby 是否带 openssl 模块,使用如下命令。

1
2
3
4
5
6
# 检查 openssl zlib
ruby -ropenssl -rzlib -e "puts :success"

# 用下面的也可以
ruby -ropenssl -e "puts :success"
ruby -ropenssl -e 'puts OpenSSL::OPENSSL_VERSION'

在控制台会输出对应的信息就代表成功了。如果没有成功会报类似如下的错误:

ruby: no such file to load – openssl (LoadError)

上面能够成功,我也觉得很神奇,不管怎么样我遇到的问题算是解决了。后来我在 官网 doc 上面找到了一些解释。

module OpenSSL

OpenSSL (指的是 ruby 自带的 openssl) provides SSL, TLS and general purpose cryptography. It wraps the OpenSSL (指的是系统的 openssl 库) library.

Install

OpenSSL comes bundled with the Standard Library of Ruby.

This means the OpenSSL extension is compiled with Ruby and packaged on build. During compile time, Ruby will need to link against the OpenSSL library on your system. However, you cannot use openssl provided by Apple to build standard library openssl.

If you use OSX, you should install another openssl and run “./configure –with-openssl-dir=/path/to/another-openssl“. For Homebrew user, run brew install openssl and then “./configure –with-openssl-dir=brew –prefix openssl.

最后,自己重新编译 passenger,工程可以正常运行了。


~~

当你遇到问题的时候,不要慌张,试着让自己放下问题出去走一走,回过头再来看或许问题就引刃而解了。


本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。

veryitman