apache多SSL证书虚拟主机使用mod_jk方式代理tomcat

1.问题背景

   公司旧版的客户端产品之前使用了早期的证书(其签名算法是SHA1),只能与带有 SHA1证书的tomcat服务器通信。
SHA1的证书今年年底都要进行吊销,也就是说年底需要重新签发成sha256证书。

Google关于淘汰SHA1的资料

https://security.googleblog.com/2015/12/an-update-on-sha-1-certificates-in.html

CA/Browser Forum关于通过淘汰SHA1的资料

https://cabforum.org/2014/10/16/ballot-118-sha-1-sunset/

同时,新版客户端产品能够支持sha256证书,也能支持sha1证书。因此,为了兼容性不同版本的客户端产品对证书签名算法的支持,需要在tomcat服务器端配置多SSL证书机制。


2.技术知识背景

“早期的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信息,使得服务器能够切换到正确的域并返回相应的证书。
[warning]要使用SNI,需要客户端和服务器端同时满足条件,幸好对于现代浏览器来说,大部分都支持SSLv3/TLSv1,所以都可以享受SNI带来的便利。”--参考自《 SNI: 实现多域名虚拟主机的SSL/TLS认证
更多的参考资料:

找了很多资料,并没有很好的对tomca的多证书支持的配置资料,而apahce对多证书的支持的资料较多,从后续的维护权衡,采用apahce的代理tomcat方式来配置web服务器的多证书。apache对SNI的支持能够采用mod_ssl和mod_gnutls来支持,mod_gnutls需要安装gnutls模块,安装步骤十分繁琐又容易出错,故不采用(本人安装过,绕了一大圈一大堆的依赖,最后不得不放弃。)。网上拷贝的文章有些是过时的,采用的是gnutls,其实mod_ssl早已支持SNI机制,因为它依赖于openssl,而openssl在 0.9.8f 版就已经支持SNI了,同时注意Apache的版本 2.2.12 and later才能实现SNI。

3.问题处理

3.1  软件环境
apache2.2.31   tomcat-7.0.64   mod_ssl( apache2.2.31编译自带的版本)   mod_jk  linux centos6操作系统
3.2  软件安装
先来安装apache2.2.31
下载Apache安装包apache2.2.31 ,下载地址:http://httpd.apache.org/
编译命令:
./configure --prefix=/usr/local/apache2 --with-apr=/usr/local/apr --with-apr-util=/usr/local/apr-util/ 
(除了指定Apache的安装目录外,还要安装apr、apr-util并指定参数)
make
make install
在编译Apache时分别出现了apr not found、APR-util not found  not found的问题,下面就这些问题解决来实际操作一把。
http://apr.apache.org/download.cgi  下载apr-1.4.5.tar.gz、apr-util-1.3.12.tar.gz
1.解决apr not found问题
  [root@localhost bin]# tar -zxf apr-1.4.5.tar.gz
  [root@localhost apr-1.4.5]# ./configure --prefix=/usr/local/apr
  [root@localhost apr-1.4.5]# make
  [root@localhost apr-1.4.5]# make install
2.解决APR-util not found问题
  [root@localhost bin]# tar -zxf apr-util-1.3.12.tar.gz
  [root@localhost apr-util-1.3.12]# ./configure --prefix=/usr/local/apr-util -with-apr=/usr/local/apr/bin/apr-1-config
  [root@localhost apr-util-1.3.12]# make
  [root@localhost apr-util-1.3.12]# make install

安装好了apache后再来看下在apache上安装mod_ssl模块(可以在安装apahce时就顺带安装mod_ssl,在configure 命令追加 --enable- mods-shared=all --enable-ssl,在此主要说明如何灵活地安装apahce的模块)
1. 首先定位到Apache源码的 proxy目录
# cd /root/Desktop/httpd-2.2.31
# cd modules/proxy/
2. 编译相应模块:
其中 "/usr/local/apache2" 为之前Apache的安装目录
# /usr/local/apache2/bin/apxs -c -i mod_proxy.c proxy_util.c
加载模块:
# /usr/local/apache2/bin/apxs -i -a -n proxy mod_proxy.la
这样,就将proxy安装成功了,你可以到httpd.conf中看到自动添加了如下语句:
LoadModule ssl_module        modules/mod_ssl.so
modules 文件夹中也生成了相应的  mod_ssl.so 模块,要安装其他模块也是同样的流程。
至于mod_jk如何安装和配置知识可参考《 Tomcat系列之Apache使用mod_proxy和mod_jk反向代理Tomcat
3.3  配置
apache httpd.conf文件配置:
ServerRoot "/usr/local/apache2"

LoadModule ssl_module modules/mod_ssl.so

<IfModule !mpm_netware_module>
<IfModule !mpm_winnt_module>
#
# If you wish httpd to run as a different user or group, you must run
# httpd as root initially and it will switch.  
#
# User/Group: The name (or #number) of the user/group to run httpd as.
# It is usually good practice to create a dedicated user and group for
# running httpd, as with most system services.
#
User daemon
Group daemon

</IfModule>
</IfModule>


ServerAdmin huangyx@yealink.com

<Directory />
    Options FollowSymLinks
    AllowOverride None
    Order deny,allow
    Deny from all
</Directory>

<Directory "/usr/local/apache2/htdocs">
    Options Indexes FollowSymLinks
    AllowOverride None
    Order allow,deny
    Allow from all
</Directory>

#
# DirectoryIndex: sets the file that Apache will serve if a directory
# is requested.
#
<IfModule dir_module>
    DirectoryIndex index.html
</IfModule>

#
# The following lines prevent .htaccess and .htpasswd files from being 
# viewed by Web clients. 
#
<FilesMatch "^\.ht">
    Order allow,deny
    Deny from all
    Satisfy All
</FilesMatch>

ErrorLog "logs/error_log"

LogLevel warn

<IfModule log_config_module>
    LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
    LogFormat "%h %l %u %t \"%r\" %>s %b" common

    <IfModule logio_module>
      # You need to enable mod_logio.c to use %I and %O
      LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %I %O" combinedio
    </IfModule>

    CustomLog "logs/access_log" common
</IfModule>

<IfModule alias_module>
    ScriptAlias /cgi-bin/ "/usr/local/apache2/cgi-bin/"
</IfModule>

<IfModule cgid_module>

</IfModule>

<Directory "/usr/local/apache2/cgi-bin">
    AllowOverride None
    Options None
    Order allow,deny
    Allow from all
</Directory>


DefaultType text/plain

<IfModule mime_module>
    #
    # TypesConfig points to the file containing the list of mappings from
    # filename extension to MIME-type.
    #
    TypesConfig conf/mime.types

    #
    # AddType allows you to add to or override the MIME configuration
    # file specified in TypesConfig for specific file types.
    #
    #AddType application/x-gzip .tgz
    #
    # AddEncoding allows you to have certain browsers uncompress
    # information on the fly. Note: Not all browsers support this.
    #
    #AddEncoding x-compress .Z
    #AddEncoding x-gzip .gz .tgz
    #
    # If the AddEncoding directives above are commented-out, then you
    # probably should define those extensions to indicate media types:
    #
    AddType application/x-compress .Z
    AddType application/x-gzip .gz .tgz

    #
    # AddHandler allows you to map certain file extensions to "handlers":
    # actions unrelated to filetype. These can be either built into the server
    # or added with the Action directive (see below)
    #
    # To use CGI scripts outside of ScriptAliased directories:
    # (You will also need to add "ExecCGI" to the "Options" directive.)
    #
    #AddHandler cgi-script .cgi

    # For type maps (negotiated resources):
    #AddHandler type-map var

    #
    # Filters allow you to process content before it is sent to the client.
    #
    # To parse .shtml files for server-side includes (SSI):
    # (You will also need to add "Includes" to the "Options" directive.)
    #
    #AddType text/html .shtml
    #AddOutputFilter INCLUDES .shtml
</IfModule>
# Server-pool management (MPM specific)
#Include conf/extra/httpd-mpm.conf

# Multi-language error messages
#Include conf/extra/httpd-multilang-errordoc.conf

# Fancy directory listings
#Include conf/extra/httpd-autoindex.conf

# Language settings
#Include conf/extra/httpd-languages.conf

# User home directories
#Include conf/extra/httpd-userdir.conf

# Real-time info on requests and configuration
#Include conf/extra/httpd-info.conf

# Virtual hosts
#Include conf/extra/httpd-vhosts.conf

# Local access to the Apache HTTP Server Manual
#Include conf/extra/httpd-manual.conf

# Distributed authoring and versioning (WebDAV)
#Include conf/extra/httpd-dav.conf

# Various default settings
#Include conf/extra/httpd-default.conf

# Secure (SSL/TLS) connections
Include conf/extra/httpd-ssl.conf

<IfModule ssl_module>
SSLRandomSeed startup builtin
SSLRandomSeed connect builtin
</IfModule>

# Load the mod_jk
LoadModule jk_module modules/mod_jk.so
JkWorkersFile /usr/local/apache2/conf/extra/workers.properties
JkLogFile logs/mod_jk.log
JkLogLevel debug


<Directory "/usr/local/apache-tomcat-7.0.64/webapps/rs">  
    Options Indexes FollowSymLinks  
    AllowOverride None  
    Order allow,deny  
    Allow from all  
</Directory> 



mod_jk的workers.properties文件配置:
#让mod_jk模块知道tomcat的位置 
workers.tomcat_home=/usr/local/apache-tomcat-7.0.64

worker.list=TomcatA
worker.TomcatA.port=8009
worker.TomcatA.host=localhost
worker.TomcatA.type=ajp13
worker.TomcatA.lbfactor=1

httpd-ssl.conf文件配置:
NameVirtualHost *:443
Listen 443

AddType application/x-x509-ca-cert .crt
AddType application/x-pkcs7-crl    .crl

SSLCipherSuite HIGH:MEDIUM:!MD5:!RC4
SSLProxyCipherSuite HIGH:MEDIUM:!MD5:!RC4


SSLHonorCipherOrder on 


SSLProtocol all -SSLv2 -SSLv3
SSLProxyProtocol all -SSLv2 -SSLv3


SSLPassPhraseDialog  builtin
SSLSessionCache        "shmcb:/usr/local/apache2/logs/ssl_scache(512000)"
SSLSessionCacheTimeout  300

#   Semaphore:
#   Configure the path to the mutual exclusion semaphore the
#   SSL engine uses internally for inter-process synchronization. 
SSLMutex  "file:/usr/local/apache2/logs/ssl_mutex"

<Directory "/usr/local/apache-tomcat-7.0.64/webapps/ROOT">  
    Options Indexes FollowSymLinks  
    AllowOverride None  
    Order allow,deny  
    Allow from all  
</Directory> 

<VirtualHost _default_:443>
DocumentRoot "/usr/local/apache-tomcat-7.0.64/webapps/rs"
ServerName ******************:443
ServerAdmin huangyx@yealink.com
ErrorLog "/usr/local/apache2/logs/old_error_log"
TransferLog "/usr/local/apache2/logs/old_access_log"

JkMount /* TomcatA

SSLEngine on
SSLCertificateFile "/usr/local/apache-ssl-files/old/rps.crt"
SSLCertificateKeyFile "/usr/local/apache-ssl-files/old/rps.key"
SSLCertificateChainFile "/usr/local/apache-ssl-files/old/rps_ca2.cer"

<FilesMatch "\.(cgi|shtml|phtml|php)$">
    SSLOptions +StdEnvVars
</FilesMatch>
<Directory "/usr/local/apache2/cgi-bin">
    SSLOptions +StdEnvVars
</Directory>


BrowserMatch "MSIE [2-5]" \
         nokeepalive ssl-unclean-shutdown \
         downgrade-1.0 force-response-1.0

CustomLog "/usr/local/apache2/logs/ssl_request_log" \
          "%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \"%r\" %b"
</VirtualHost>


<VirtualHost *:443>
DocumentRoot "/usr/local/apache-tomcat-7.0.64/webapps/rs"
#DocumentRoot "/usr/local/apache2/htdocs"
DirectoryIndex index.html index.jsp
ServerName rps.test.com:443
ServerAdmin huangyx@yealink.com
ErrorLog "/usr/local/apache2/logs/new_error_log"
TransferLog "/usr/local/apache2/logs/new_access_log"

JkMount /* TomcatA

SSLEngine on

SSLCertificateFile "/usr/local/apache-ssl-files/new/rps.cer"
SSLCertificateKeyFile "/usr/local/apache-ssl-files/new/rps.key"
SSLCertificateChainFile "/usr/local/apache-ssl-files/new/root.cer"

<FilesMatch "\.(cgi|shtml|phtml|php)$">
    SSLOptions +StdEnvVars
</FilesMatch>
<Directory "/usr/local/apache2/cgi-bin">
    SSLOptions +StdEnvVars
</Directory>

BrowserMatch "MSIE [2-5]" \
         nokeepalive ssl-unclean-shutdown \
         downgrade-1.0 force-response-1.0

CustomLog "/usr/local/apache2/logs/ssl_request_log" \
          "%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \"%r\" %b"
</VirtualHost> 
注意:默认的虚拟主机的配置  ServerName ******************:443 是采用通配符方式,有请求过来时先去匹配显示指定域名的主机,直到找不到,最后会匹配通配符的主机,apache 通配符的主机会对应tomcat的localhost的主机配置,所以DocumentRoot的路径配置要和tomcat的localhost的路径配置一致。

tomcat的server.xml配置:
<?xml version='1.0' encoding='utf-8'?>


<Server port="8005" shutdown="SHUTDOWN">
  <Listener className="org.apache.catalina.startup.VersionLoggerListener" />
  <!-- Security listener. Documentation at /docs/config/listeners.html
  <Listener className="org.apache.catalina.security.SecurityListener" />
  -->
  <!--APR library loader. Documentation at /docs/apr.html -->
  <Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
  <!--Initialize Jasper prior to webapps are loaded. Documentation at /docs/jasper-howto.html -->
  <Listener className="org.apache.catalina.core.JasperListener" />
  <!-- Prevent memory leaks due to use of particular java/javax APIs-->
  <Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
  <Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
  <Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />

  <!-- Global JNDI resources
       Documentation at /docs/jndi-resources-howto.html
  -->
  <GlobalNamingResources>
    <!-- Editable user database that can also be used by
         UserDatabaseRealm to authenticate users
    -->
    <Resource name="UserDatabase" auth="Container"
              type="org.apache.catalina.UserDatabase"
              description="User database that can be updated and saved"
              factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
              pathname="conf/tomcat-users.xml" />
  </GlobalNamingResources>

  <!-- A "Service" is a collection of one or more "Connectors" that share
       a single "Container" Note:  A "Service" is not itself a "Container",
       so you may not define subcomponents such as "Valves" at this level.
       Documentation at /docs/config/service.html
   -->
  <Service name="Catalina">

    <!--The connectors can use a shared executor, you can define one or more named thread pools-->
    <Connector port="8081" protocol="HTTP/1.1"
                URIEncodeing="UTF-8"
                maxThreads="200"
                minSpareThreads="16"
                maxSpareThreads="50"
                acceptCount="1000"
                maxKeepAliveRequests="100"
                bufferSize="8192"
                connectionTimeout="60000"
                useBodyEncodingForURI="true"
                keepAliveTimeout="10000"
                enableLookups="false"
                compression="on"
                compressionMinSize="2048"
                noCompressionUserAgents="gozilla,traviata"
                compressableMimeType="text/html,text/xml,text/javascript,text/css,text/plain"
               redirectPort="443" />
    <!-- Define an AJP 1.3 Connector on port 8009 -->
    <Connector port="8009" protocol="AJP/1.3" redirectPort="443" />

    <!-- You should set jvmRoute to support load-balancing via AJP ie :
    <Engine name="Catalina" defaultHost="localhost" jvmRoute="jvm1">
    -->
    <Engine name="Catalina" defaultHost="localhost">

      <!--For clustering, please take a look at documentation at:
          /docs/cluster-howto.html  (simple how to)
          /docs/config/cluster.html (reference documentation) -->
      <!--
      <Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"/>
      -->

      <!-- Use the LockOutRealm to prevent attempts to guess user passwords
           via a brute-force attack -->
      <Realm className="org.apache.catalina.realm.LockOutRealm">
        <!-- This Realm uses the UserDatabase configured in the global JNDI
             resources under the key "UserDatabase".  Any edits
             that are performed against this UserDatabase are immediately
             available for use by the Realm.  -->
        <Realm className="org.apache.catalina.realm.UserDatabaseRealm"
               resourceName="UserDatabase"/>
      </Realm>

      <Host name="localhost"  appBase="webapps"
            unpackWARs="true" autoDeploy="true">

        <!-- SingleSignOn valve, share authentication between web applications
             Documentation at: /docs/config/valve.html -->
        <!--
        <Valve className="org.apache.catalina.authenticator.SingleSignOn" />
        -->

        <!-- Access log processes all example.
             Documentation at: /docs/config/valve.html
             Note: The pattern used is equivalent to using pattern="common" -->
        <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
               prefix="localhost_access_log." suffix=".txt"
               pattern="%h %l %u %t "%r" %s %b" />
	<Context path="" docBase="/usr/local/apache-tomcat-7.0.64/webapps/rs"/>
      </Host>


      <Host name="rps.est.com" appBase="webapps"
      unpackWARs="true" autoDeploy="true"
      xmlValidation="false" xmlNamespaceAware="false">
        <Context path="" docBase="/usr/local/apache-tomcat-7.0.64/webapps/rs" 
             reloadable="true" crossContext="true"/>
     </Host>

    </Engine>
  </Service>
</Server>
 
 
apache采用mod_jk代理tomcat的原理配置具体可参考: apache+tomcat+mod_jk整合配置虚拟主机


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值