怎样让Apache实现一个独立IP安装多个SSL证书

2014年10月14日 由 Amon

【备注】

1. 目前本文仅停留在探索阶段,本人没能实现目标,仅有参考价值。在探索过程证明了网上现有的使用老版本软件不能实现目标,使用新版本解决了一系列依赖包的问题后,在对mod_gnutls-0.7进行make时不能通过。

2. 除了本方案试图解决一个独立IP安装多个SSL证书,替代方案是购买一个支持多域名( Multi-Domain)的SSL证书,或者购买一个支持单域名泛解析(Wildcard)的SSL证书,。

多域名( Multi-Domain)SSL证书推荐:

COMODO PositiveSSL Multi-Domain

网址:https://www.namecheap.com/security/ssl-certificates/comodo/positivessl-multi-domain.aspx

价格:$29.88/年,或者三年折扣价 $26.88/年

单域名泛解析(Wildcard)SSL证书推荐:

COMODO EssentialSSL Wildcard

网址:https://www.namecheap.com/security/ssl-certificates/comodo/essentialssl-wildcard.aspx

价格:$99.90/年,或者三年折扣价 $95.00/年

Apache多HTTPS虚拟主机的配置,利用的原理的是SNI。基于域名的虚拟主机,即共享同一个IP地址和端口的HTTPS虚拟主机。

SNI(Server Name Indication)服务器名称指示,是一个TLS的扩展,它使得启用SSL的基于域名的虚拟主机的配置成为可能。打破了每个HTTPS的虚拟主机需要一个IP地址的要求。因此,成本大大降低,因为所有的HTTPS虚拟主机可以共享相同的IP地址和端口,使HTTPS Web服务的更简单。

早期的SSLv2根据经典的公钥基础设施PKI(Public Key Infrastructure)设计,它默认认为:一台服务器(或者说一个IP)只会提供一个服务,所以在SSL握手时,服务器端可以确信客户端申请的是哪张证书。但是让人万万没有想到的是,虚拟主机大力发展起来了,这就造成了一个IP会对应多个域名的情况。解决办法有一些,例如申请泛域名证书,对所有*.yourdomain.com的域名都可以认证,但如果你还有一个yourdomain.net的域名,那就不行了。

在HTTP协议中,请求的域名作为主机头(Host)放在HTTP Header中,所以服务器端知道应该把请求引向哪个域名,但是早期的SSL做不到这一点,因为在SSL握手的过程中,根本不会有Host的信息,所以服务器端通常返回的是配置中的第一个可用证书。因而一些较老的环境,可能会产生多域名分别配好了证书,但返回的始终是同一个。既然问题的原因是在SSL握手时缺少主机头信息,那么补上就是了。

SNI(Server Name Indication)定义在RFC 4366,是一项用于改善SSL/TLS的技术,在SSLv3/TLSv1中被启用。它允许客户端在发起SSL握手请求时(具体说来,是客户端发出SSL
请求中的ClientHello阶段),就提交请求的Host信息,使得服务器能够切换到正确的域并返回相应的证书。

要使用SNI,需要客户端和服务器端同时满足条件,幸好对于现代浏览器来说,大部分都支持SSLv3/TLSv1,所以都可以享受SNI带来的便利。

支持SNI的浏览器、服务器、库

  • Internet Explorer 7 or later, on Windows Vista or higher. Does not work on Windows XP, even Internet Explorer 8.
  • Mozilla Firefox 2.0 or later
  • Opera 8.0 or later (the TLS 1.1 protocol must be enabled)
  • Opera Mobile at least version 10.1 beta on Android[citation needed]
  • Google Chrome (Vista or higher. XP on Chrome 6 or newer. OS X 10.5.7 or higher on Chrome 5.0.342.1 or newer)
  • Safari 2.1 or later (Mac OS X 10.5.6 or higher and Windows Vista or higher)
  • Konqueror/KDE 4.7 or later
  • MobileSafari in Apple iOS 4.0 or later
  • Android default browser on Honeycomb or newer
  • Windows Phone 7[citation needed]
  • MicroB on Maemo

支持SNI的服务器

  • Apache 2.2.12 or later using mod_ssl(or alternatively with experimental mod_gnutls)
  • Cherokee if compiled with TLS support
  • Versions of lighttpd 1.4.x and 1.5.x with patch, or 1.4.24+ without patch
  • Nginx with an accompanying OpenSSL built with SNI support
  • LiteSpeed 4.1 or later
  • Pound 2.6 or later
  • Apache Tomcat on Java 7 or later
  • Microsoft Internet Information Server IIS 8

支持SNI的库

  • Mozilla NSS 3.11.1 client-side only
  • OpenSSL 0.9.8f (released 11 Oct 2007) – not compiled in by default, can be compiled in with config option ‘–enable-tlsext’
  • OpenSSL 0.9.8j (released 07 Jan 2009) through 1.0.0 (released 29 March 2010) – compiled in by default
  • GNU TLS
  • libcurl / cURL since 7.18.1 (released 30 Mar 2008) when compiled against
    an SSL/TLS toolkit with SNI support
  • Python 3.2 (ssl, urllib and httplib modules)
  • Qt 4.8
  • Oracle Java 7 JSSE

参考资料:

在Apache环境下,需要使用 mod_gnutls (https://mod.gnutls.org)来实现同一个IP上配置多个HTTPS主机。

mod_gnutls is an extension for ​Apache’s httpd uses the ​GnuTLS library to provide HTTPS.
It is similar to ​mod_ssl in purpose, but it supports some features and protocols that mod_ssl does not, and it does not use ​OpenSSL.

GnuTLS(GNU Transport Layer Security Library)是用于实现TLS加密协议的函数库。是TLS 标准的开源实现。是GNU的SSL实现,或者按GNU的意思是SSL的升级换代。它和 OpenSSL 是最值得关注的 TLS 开源库。

GnuTLS 是一个安全通讯库,实现了 SSL、TLS 和 DTLS 协议和相关技术。提供了简单的 C 语言编程接口用来访问这些安全通讯协议,提供解析和读写 X.509、PKCS #12、OpenPGP 和其他相关结构。特点是可移植性和高效。

第一步. 安装mod_gnutls

1. 安装各种依赖包

安装httpd-devel、libffi-devel、libtasn1-devel、guile-devel【验证成功】

yum install httpd-devel libffi-devel libtasn1-devel guile-devel

成功安装:

httpd-devel-2.2.15-39.el6.centos.x86_64
libffi-devel-3.0.5-3.2.el6.x86_64
libtasn1-devel-2.3-6.el6_5.x86_64
guile-devel-1.8.7-5.el6.x86_64 

安装libnettle【验证成功】

参考:http://www.tuicool.com/articles/3qeuQbB
手册:http://www.linuxfromscratch.org/blfs/view/svn/postlfs/nettle.html
下载:http://ftp.gnu.org/gnu/nettle/

安装最新版nettle-3.1:

wget http://ftp.gnu.org/gnu/nettle/nettle-3.1.tar.gz
tar -xzvf nettle-3.1.tar.gz
cd nettle-3.1
./configure
make && make install

安装后的路径是:

/usr/local/include/nettle

软连接(必须):

ln -s /usr/local/include/nettle /usr/include/nettle

安装gmplib【验证成功】

下载:https://gmplib.org/download/gmp/

安装最新版gmp-6.0.0:

wget https://gmplib.org/download/gmp/gmp-6.0.0a.tar.xz
xz -d gmp-6.0.0a.tar.xz
tar -xvf gmp-6.0.0a.tar
cd gmp-6.0.0
./configure
make && make install

安装后的路径是:

/usr/local/include/gmp.h

安装p11-kit【验证待定】

手册:ttp://p11-glue.freedesktop.org/p11-kit.html
参考:http://www.cnblogs.com/xiaouisme/archive/2012/05/23/2515151.html
下载:http://p11-glue.freedesktop.org/releases/

安装最新版p11-kit-0.23.1:

wget http://p11-glue.freedesktop.org/releases/p11-kit-0.23.1.tar.gz
tar -xzvf p11-kit-0.23.1.tar.gz
cd p11-kit-0.23.1
./configure
make && make install

安装后的路径是:

/usr/lib64/pkcs11

软连接(?):

ln -s /usr/lib64/pkcs11 /usr/include/p11-kit

安装autogen【验证成功】

官网:http://sourceforge.net/projects/autogen/
下载:http://sourceforge.net/projects/autogen/files/
文档:http://ftp.gnu.org/old-gnu/Manuals/autogen-5.5.4/html_chapter/autogen_6.html

安装最新版AutoGen-5.16.2:

wget http://sourceforge.net/projects/autogen/files/AutoGen/AutoGen-5.16.2/autogen-5.16.2.tar.xz
xz -d autogen-5.16.2.tar.xz
tar -xvf autogen-5.16.2.tar
cd autogen-5.16.2
./configure
make && make install

安装后的路径是:

/usr/local/share/autogen

安装libtasn1【验证成功】

下载:http://ftp.gnu.org/gnu/libtasn1/

安装最新版libtasn1-4.5:

wget http://ftp.gnu.org/gnu/libtasn1/libtasn1-4.5.tar.gz
tar -xzvf libtasn1-4.5.tar.gz
cd libtasn1-4.5
./configure
make && make install

安装后的路径是:

/usr/local/share/info/libtasn1.info

安装libidn【验证待定】

下载:http://ftp.gnu.org/gnu/libidn/

安装最新版libidn-1.31:

wget http://ftp.gnu.org/gnu/libidn/libidn-1.31.tar.gz
tar -xzvf libidn-1.31.tar.gz
cd libidn-1.31
./configure
make && make install

安装后的路径是:

安装libunbound【验证成功】

下载:http://unbound.net/download.html

安装最新版unbound-1.5.4:

wget http://unbound.net/downloads/unbound-1.5.4.tar.gz
tar -xzvf unbound-1.5.4.tar.gz
cd unbound-1.5.4
./configure
make && make install

安装后的路径是:

/usr/local/sbin/unbound

安装gnutls【验证成功】

YUM方式可以安装gnutls 2.8.5,但是mod_gnutls最新版本要求至少gnutls 3.1.4。所以必须源码编译方式安装。

手册:http://www.gnutls.org/
手册:http://docs.huihoo.com/gnutls/3.4.3/
参考:http://wiki.mikejung.biz/Gcc_CentOS
参考:http://buildd.debian-ports.org/status/fetch.php?pkg=gnutls28&arch=sh4&ver=3.3.15-7&stamp=1434506763
下载:ftp://ftp.gnutls.org/gcrypt/gnutls

安装最新版gnutls-3.4.3:

wget ftp://ftp.gnutls.org/gcrypt/gnutls/v3.4/gnutls-3.4.3.tar.xz
xz -d gnutls-3.4.3.tar.xz
tar -xvf gnutls-3.4.3.tar
cd gnutls-3.4.3
./configure --with-included-libtasn1 --without-p11-kit
make && make install

./configure 时输出:

configure: summary of build options:

  version:              3.4.3 shared 32:0:2
  Host/Target system:   x86_64-unknown-linux-gnu
  Build system:         x86_64-unknown-linux-gnu
  Install prefix:       /usr/local
  Compiler:             gcc
  CFlags:               -g -O2
  Library types:        Shared=yes, Static=no
  Local libopts:        no
  Local libtasn1:       yes
  Use nettle-mini:      no

configure: External hardware support:

  /dev/crypto:          no
  Hardware accel:       x86-64
  Padlock accel:        yes
  getrandom variant:    no
  PKCS#11 support:      no
  TPM support:          no

configure: Optional features:
(note that included applications might not compile properly
if features are disabled)

  DTLS-SRTP support:    yes
  ALPN support:         yes
  OCSP support:         yes
  Ses. ticket support:  yes
  OpenPGP support:      yes
  SRP support:          yes
  PSK support:          yes
  DHE support:          yes
  ECDHE support:        yes
  Anon auth support:    yes
  Heartbeat support:    yes
  IDNA support:         no
  Unicode support:      yes
  Self checks:          no
  Non-SuiteB curves:    yes
  FIPS140 mode:         no

configure: Optional applications:

  crywrap app:          no

configure: Optional libraries:

  Guile wrappers:       yes
  C++ library:          yes
  DANE library:         yes
  OpenSSL compat:       no

configure: System files:

  Trust store pkcs11:
  Trust store dir:
  Trust store file:     /etc/pki/tls/cert.pem
  Blacklist file:
  CRL file:
  Priority file:        /etc/gnutls/default-priorities
  DNSSEC root key file: /etc/unbound/root.key

configure: WARNING:
***
*** The DNSSEC root key file in /etc/unbound/root.key was not found.
*** This file is needed for the verification of DNSSEC responses.
*** Use the command: unbound-anchor -a "/etc/unbound/root.key"
*** to generate or update it.
***

安装后的路径是:

/usr/include/gnutls

查看安装好的gnutls版本:

ls -lah /usr/local/bin/

输出:

total 3.7M
drwxr-xr-x.  2 root root 4.0K Jul 22 15:14 .
drwxr-xr-x. 12 root root 4.0K Dec 26  2013 ..
-rwxr-xr-x   1 root root  52K Jul 22 12:21 asn1Coding
-rwxr-xr-x   1 root root  63K Jul 22 12:21 asn1Decoding
-rwxr-xr-x   1 root root  46K Jul 22 12:21 asn1Parser
-rwxr-xr-x   1 root root 518K Jul 22 11:47 autogen
-rwxr-xr-x   1 root root 3.3K Jul 22 11:47 autoopts-config
-rwxr-xr-x   1 root root 379K Jul 22 15:14 certtool
-rwxr-xr-x   1 root root  48K Jul 22 11:47 columns
-rwxr-xr-x   1 root root 297K Jul 22 15:14 danetool
-rwxr-xr-x   1 root root  87K Jul 22 11:47 getdefs
-rwxr-xr-x   1 root root 230K Jul 22 15:14 gnutls-cli
-rwxr-xr-x   1 root root 178K Jul 22 15:14 gnutls-cli-debug
-rwxr-xr-x   1 root root 168K Jul 22 15:14 gnutls-serv
-rwxr-xr-x   1 root root  88K Jul 22 13:06 idn
-rwxr-xr-x   1 root root 121K Jul 22 11:06 nettle-hash
-rwxr-xr-x   1 root root  46K Jul 22 11:06 nettle-lfib-stream
-rwxr-xr-x   1 root root 119K Jul 22 11:06 nettle-pbkdf2
-rwxr-xr-x   1 root root  91K Jul 22 15:14 ocsptool
-rwxr-xr-x   1 root root  93K Jul 22 10:51 p11-kit
-rwxr-xr-x   1 root root 157K Jul 22 11:06 pkcs1-conv
-rwxr-xr-x   1 root root  36K Jul 22 15:14 psktool
-rwxr-xr-x   1 root root 286K Jul 22 11:06 sexp-conv
-rwxr-xr-x   1 root root  54K Jul 22 15:14 srptool
-rwxr-xr-x   1 root root 527K Jul 22 10:51 trust

输入:

gnutls-cli -v

输出:

gnutls-cli 3.4.3
Copyright (C) 2000-2015 Free Software Foundation, and others, all rights reserved.
This is free software. It is licensed for use, modification and
redistribution under the terms of the
GNU General Public License, version 3 or later
    <http://gnu.org/licenses/gpl.html>

please send bug reports to:  bugs@gnutls.org

成功安装gnutls-3.4.3!

2. 安装mod_gnutls

手册:https://mod.gnutls.org/wiki/develop
参考:http://lists.infradead.org/pipermail/openconnect-devel/2013-November/001307.html
参考:http://lists.infradead.org/pipermail/openconnect-devel/2013-November/001309.html
下载:https://mod.gnutls.org/downloads/

安装最新版mod_gnutls-0.7:

注意,根据网上的文章《apache mod_gnutls实现一个独立IP安装多个SSL证书》:这里只需要make,不需要make install。

wget https://mod.gnutls.org/downloads/mod_gnutls-0.7.tar.bz2
tar -xjvf mod_gnutls-0.7.tar.bz2
cd mod_gnutls-0.7
./configure PKG_CONFIG_PATH=/usr/local/lib/pkgconfig/:/usr/local/lib64/pkgconfig/
make

./configure 时输出:

Configuration summary for mod_gnutls:

   * mod_gnutls version:        0.7
   * Apache Modules directory:  /usr/lib64/httpd/modules
   * GnuTLS Library version:    3.4.3
   * SRP Authentication:        no
   * MSVA Client Verification:  no
   * Build documentation:       no

make报错【尚未解决】:

mod_gnutls.c:260: error: missing initializer
mod_gnutls.c:260: error: (near initialization for 'mgs_config_cmds[27].func')
make[1]: *** [libmod_gnutls_la-mod_gnutls.lo] Error 1
make[1]: Leaving directory `/root/mod_gnutls-0.7/src'
make: *** [all-recursive] Error 1

安装后的路径是:

?

2. Apache加载mod_gnutls模块

cp mod_gnutls-0.7/src/.libs/libmod_gnutls.so /usr/lib/httpd/modules/mod_gnutls.so
cp mod_gnutls-0.7/data/{dh,rsa}file /etc/httpd/conf/

mod_gnutls模块依赖dhfile和rsafile文件。

3. 配置httpd.conf

Listen 10.10.10.10:443
LoadModule gnutls_module modules/mod_gnutls.so
AddType application/x-x509-ca-cert .crt
AddType application/x-pkcs7-crl    .crl
GnuTLSCache dbm "/var/cache/mod_gnutls_cache"
GnuTLSCacheTimeout 300
NameVirtualHost 10.10.10.10:443

创建会话缓存目录:

mkdir -m 0700 /var/cache/mod_gnutls_cache
chown nobody.nobody /var/cache/mod_gnutls_cache

4. 配置虚拟主机

<virtualhost 10.10.10.10:443="">
    ServerName www.domain1.name:443
    GnuTLSEnable on
    GnuTLSCertificateFile ./ssl/www.domain1.name.public.cer
    GnuTLSKeyFile ./ssl/www.domain1.name.private.key
    DocumentRoot "/var/www/www.domain1.name"
</virtualhost>
<virtualhost 10.10.10.10:443="">
    ServerName www.domain2.name:443
    GnuTLSEnable on
    GnuTLSCertificateFile ./ssl/www.domain2.name.public.cer
    GnuTLSKeyFile ./ssl/www.domain2.name.private.key
    DocumentRoot "/var/www/www.domain2.name"
</virtualhost>

这样访问每个虚拟主机都正常。

广告位
美团云