1.問題背景
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.技術知識背景
但是讓人萬萬沒有想到的是,虛擬主機大力發展起來了,這就造成了一個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認證》
3.問題處理
3.1 軟件環境
3.2 軟件安裝
./configure --prefix=/usr/local/apache2 --with-apr=/usr/local/apr --with-apr-util=/usr/local/apr-util/
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
# 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 模塊,要安裝其他模塊也是同樣的流程。
3.3 配置
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 [email protected]
<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
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 [email protected]
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 [email protected]
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的路徑配置一致。<?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>