几周前遇到的一个问题,需要在Ubuntu VPS上编译安装Apache httpd,并满足如下要求:
- 覆盖由包管理器(Debian apt)安装的版本
- 使用非操作系统提供的OpenSSL
- 使用最新版本的nghttp2*1
- 可执行文件名称与Debian apt安装的一致,为apache2(默认编译后为httpd,与CentOS的一致)
有这样的需求是因为这台VPS上的一个VirtualHost需要支持RC4及3DES等过时的加密套件,而最新的OpenSSL 1.0.2k需要在编译时添加参数enable-weak-ssl-ciphers才能启用.在尝试多种方式均未果后*2,编译安装并覆盖原版Apache httpd.
安装APR
cd ~
#下载APR并校验MD5
wget http://apache.osuosl.org//apr/apr-1.5.2.tar.gz
md5sum apr-1.5.2.tar.gz
tar -xvf apr-1.5.2.tar.gz
cd apr-1.5.2/
#设置安装目录
./configure --prefix-/opt/apr
#编译安装,-jN为编译的线程数,可根据CPU线程数调整
make -j2
make install
安装APR-util
cd ~
#下载APR-util并校验MD5
wget http://apache.osuosl.org//apr/apr-util-1.5.4.tar.gz
md5sum apr-util-1.5.4.tar.gz
tar -xvf apr-util-1.5.4.tar.gz
cd apr-util-1.5.4/
#设置安装目录,并指定APR所在目录
./configure --prefix=/opt/apr-util --with-apr=/opt/apr
#编译安装
make -j2
make install
安装PCRE
wget https://ftp.pcre.org/pub/pcre/pcre-8.40.tar.gz
wget https://ftp.pcre.org/pub/pcre/pcre-8.40.zip.sig
#下载并导入发布者公钥以验证签名
wget https://ftp.pcre.org/pub/pcre/Public-Key
gpg --import ./Public-Key
gpg --verify ./pcre-8.40.zip.sig
tar -xvf ./pcre-8.40.zip
cd pcre-8.40/
./configure --prefix=/opt/pcre
make -j2
make install
安装OpenSSL
cd ~
#下载OpenSSL 1.0.2k并校验SHA256
wget https://www.openssl.org/source/openssl-1.0.2k.tar.gz
sha256sum openssl-1.0.2k.tar.gz
tar -xvf openssl-1.0.2k.tar.gz
cd openssl-1.0.2k/
#设置安装目录并启用过时的SSL加密套件
./configure --prefix=/opt/openssl --openssldir=/opt/openssl/conf enable-weak-ssl-ciphers no-zlib
#编译安装
make -j2
make install
安装nghttp2
wget https://github.com/nghttp2/nghttp2/releases/download/v1.22.0/nghttp2-1.22.0.tar.gz
tar -xvf nghttp2-1.22.0.tar.gz
cd nghttp2-1.22.0/
./configure --prefix=/opt/nghttp2
make -j2
make install
安装httpd
cd ~
#下载httpd 2.4.25并校验SHA1
wget http://mirrors.ocf.berkeley.edu/apache//httpd/httpd-2.4.25.tar.gz
sha1sum httpd-2.4.25.tar.gz
tar -xvf httpd-2.4.25.tar.gz
cd httpd-2.4.25/
起初我将所有模块(Modules)以动态(shared)形式编译:
./configure --with-apr=/opt/apr \
--with-apr-util=/opt/apr-util \
--with-pcre=/opt/pcre \
--with-ssl=/opt/openssl \
--with-nghttp2=/opt/nghttp2 \
--prefix= \
--enable-so \
--enable-ssl \
--enable-http2 \
#按照Debian(Ubuntu)的目录格式安装
--enable-layout=Debian \
#可执行文件名称为apache2,而非httpd
--with-program-name=apache2 \
--enable-mods-shared=all \
--enable-mpms-shared=all \
make -j2
make install
如此安装后,试图启动apache2时却报了错,检索错误信息发现是没有加载mod_unixd
导致的.用LoadModule
命令将其加载后还是报错,这回变成配置文件中定义日志格式的LogFormat
语句不能识别。
于是重新安装了包管理器提供的apache2,并对比/usr/lib/apache2/modules目录,发现自己安装的版本多出了5个文件:mod_log_config
、mod_logio
、mod_unixd
、mod_version
、mod_watchdog
,这5个模块本应被静态(static)编译,并不需要用LoadModule
来加载。这解释了启动时报错的原因。
于是重新编译,将这5个模块静态编译
#清除之前编译好的Binary
make clean
#重新配置
./configure --with-apr=/opt/apr \
--with-apr-util=/opt/apr-util \
--with-pcre=/opt/pcre \
--with-ssl=/opt/openssl \
--with-nghttp2=/opt/nghttp2 \
--prefix= \
--enable-so \
--enable-ssl \
--enable-http2 \
--enable-layout=Debian \
--with-program-name=apache2 \
--enable-mods-shared=most \
#对以上5个模块静态编译
--enable-mods-static='log_config logio unixd version watchdog' \
--enable-mpms-shared=all
make -j2
make install
这次启动apache2时不再报错,但是用nmap扫描加密套件,发现仍无法启用3DES.似乎所指定的OpenSSL目录并没被使用.后来发现ivan ristic*3.的一篇博客文章[1]提到了--enable-ssl-staticlib-deps
这个编译参数,且在其文章中,mod_ssl
也被静态编译.于是又进行了新的尝试
make clean
./configure --with-apr=/opt/apr \
--with-apr-util=/opt/apr-util \
--with-pcre=/opt/pcre \
--with-ssl=/opt/openssl \
--with-nghttp2=/opt/nghttp2 \
--prefix= \
--enable-so \
--enable-ssl \
--enable-http2 \
--enable-layout=Debian \
--with-program-name=apache2 \
--enable-mods-shared=most \
#将mod_ssl也静态编译
--enable-mods-static='log_config logio unixd version watchdog ssl' \
--enable-mpms-shared=all \
--enable-ssl-staticlib-deps
make -j2
make install
由于mod_ssl
被静态编译,不再需要用LoadModule
加载,因此还要加这个语句注释掉
vim /etc/apache2/mods-available/ssl.load
#LoadModule ssl_module /usr/lib/apache2/modules/mod_ssl.so
再启动apache2,没有报错,3DES的加密套件也可用.
*1.一个以C语言编写的http/2库,Apache httpd的mod_http2
依赖于它.<br >
*2.包括重新编译OpenSSL及在此前提下用apxs重新安装mod_ssl等.<br >
*3.SSL配置教学书籍《Bulletproof SSL》的作者.<br >
[1].https://blog.ivanristic.com/2013/08/compiling-apache-with-static-openssl.html