我正在尝试在两个tomcat服务器之间使用https。不幸的是,自签名证书导致了这个错误:
Caused by: javax.net.ssl.SSLHandshakeException:
sun.security.validator.ValidatorException: PKIX path building failed:
sun.security.provider.certpath.SunCertPathBuilderException:
unable to find valid certification path to requested target
具体来说,我有一个主tomcat和一些从属tomcat服务器。主服务器使用简单的HttpURLConnection从servlet进行通信。
使用我自己生成的证书颁发机构创建自签名证书的最简单方法是什么,这样每次添加新服务器时,我都不需要更改主tomcat服务器。
我可以访问openssl和java 7 keytool
参考我以前的配置:
server.xml连接器:
<Connector port="443" maxHttpHeaderSize="8192" maxThreads="150"
minSpareThreads="25" maxSpareThreads="75" enableLookups="false"
disableUploadTimeout="true" acceptCount="100" debug="0" scheme="https"
secure="true" clientAuth="false" sslProtocol="TLS" keystoreType="PKCS12"
keystoreFile="/usr/java/apache-tomee-plus/conf/keystore.ks"
keystorePass="XXX_SSL" truststoreType="JKS"
truststoreFile="/usr/java/apache-tomee-plus/conf/truststore.ks"
SSLEnabled="true" maxPostSize="0"/>
启动脚本/etc/init.d/tomee
$DAEMON_HOME/jsvc \
-user $TOMCAT_USER \
-home $JAVA_HOME \
-pidfile $JSVC_PID_FILE \
-Dcatalina.home=$CATALINA_HOME \
-Djava.security.auth.login.config=$CATALINA_HOME/conf/jaas.conf \
-Djavax.net.ssl.keystore=$CATALINA_HOME/conf/keystore.ks \
-Djavax.net.ssl.keyStorePassword=XXX_SSL \
-Djavax.net.ssl.trustStore=$CATALINA_HOME/conf/truststore.ks \
-Djavax.net.ssl.trustStorePassword=changeit \
-Djava.awt.headless=true \
-Djava.io.tmpdir=$TMP_DIR \
-Dopenam.agents.bootstrap.dir=/home/tomcat/tomcat_v6_agent/Agent_001/config \
-Djava.net.preferIPv4Stack=true -Djava.net.preferIPv4Addresses \
-outfile $CATALINA_HOME/logs/catalina.out \
-errfile $CATALINA_HOME/logs/catalina.err \
$CATALINA_OPTS \
-cp $CLASSPATH \
org.apache.catalina.startup.Bootstrap
CONF /的Jaas.conf
josso {
org.josso.tc55.agent.jaas.SSOGatewayLoginModule required debug=true;
};
仅适用于传统支持,将逐步淘汰。我不确定它是否加载,因为它是为tomcat 5.5 ...
构建的在代码中,我通过使用以下HostnameVerifier()来避免在CN =中使用IP地址的问题。
HostnameVerifier hv = new HostnameVerifier()
{
public boolean verify(String urlHostName, SSLSession session)
{
return true;
}
};
HttpsURLConnection.setDefaultHostnameVerifier(hv);
connection = (HttpURLConnection) servlet.openConnection();
------------更新---------------
通过与@Bruno的长时间讨论解决了这个问题,请使用他原来的帖子以及我们的长聊聊天。
最后,我使用了工具Keytool Explorer和XCA,让我更容易学习和执行。
答案 0 :(得分:2)
首先,您实际上并未实现服务器到服务器的连接:这些仍然是客户端到服务器的连接。只是您的客户端是在servlet容器中运行的webapp。
这很重要,因为它是用于建立连接的客户端信任设置。这些与Tomcat连接器上的信任设置不同。
您的客户端网络应用程序如何使用其信任设置取决于它的实现方式以及它使用的库。似乎可以说大多数客户端都会使用默认的JRE设置,除非有特定的代码要做。如果没有任何设置,通常会使用JRE的cacerts
文件(请参阅JSSE Reference guide, customisation section中的详细信息)。您还可以指定常用的javax.net.ssl.*
属性(使用-Djavax.net.ssl....=....
);这需要在.bat
中的catalina启动脚本文件(.sh
或JAVA_OPTS
,具体取决于平台)中完成。这将影响在此JRE实例中运行的默认值,因此它可能不是您的首选(您可能需要更具体的内容,仅影响给定的Web应用程序,但您需要知道该Web应用程序的实现方式或它可以使用的可能选项)。尽管<Connector .../>
中的设置会覆盖此设置(并且信任库设置不重要,除非您也想使用客户端证书身份验证)。
如果您有许多系统,则可能不值得使用自签名证书:每个客户端都需要将所有这些自签名证书导入其信任存储区。相反,您可以创建自己的CA并仅导入该CA证书。 (在本地部署中,单个顶级/根CA应该足够,而不需要中间CA.)OpenSSL CA.pl
是构建小型CA的好脚本,但您可能会发现其他工具如XCA或TinyCA更方便。 (请注意,您通常可以使用.p12
密钥库类型直接在Java中使用PKCS12
文件,而不是默认的JKS。对于PKCS#12存储,密钥库密码和密钥/密钥管理器密码是相同。)
由于您使用的是IP地址而不是名称,因此您还应该注意Java follows RFC 2818 on IP address quite stricly(与许多浏览器不同)。特别是,主题DN的CN中的IP地址将不起作用:它必须是主题备用名称扩展名(IPAddress类型,而不是DNSname)。
修改强>
首先,摆脱该主机名验证程序:它为将使用该默认验证程序的所有HttpsURLConnection
引入了MITM攻击的漏洞,包括可能与外部服务器的连接。您可以使用SAN的IP地址来解决此问题。
以下是您需要遵循的步骤:
创建您的CA(例如使用XCA)。将其证书(不是其私钥)导出到mycacert.pem
。
如果您的应用程序可能与其他服务建立HTTPS连接,请将默认的cacerts
文件复制到新文件mytruststore.jks
中(如果您的应用程序未进行任何其他连接) ,不要复制文件,keytool
会创建文件。
将mycacert.pem
导入mytruststore.jks
keytool
:
keytool -import -keystore mytruststore.jks -alias my_alias_name -cert mycacert.pem
您现在拥有一个信任库,您可以在需要与这些服务器通信的所有客户端中安装该信任库。 (如果使用JRE更新cacerts
文件,则可能需要再次执行这些步骤。)
JAVA_OPTS
:-Djavax.net.ssl.trustStore=...
(和密码)完成的。除了这些JVM选项在Catalina发布严格的情况下,它们与其他类型的客户端相同。-Djavax.net.ssl.keyStore=...
,这只会用于客户端证书身份验证,并且让webapps使用他们所在的服务器证书并不总是一个好主意# 39;重新运行以进行客户端身份验证。为要使用的每个服务器为该CA创建证书。如果要使用IP地址,请确保使用IP地址SAN。 (由于您可以控制所有内容,XCA应该允许您一步生成私钥和证书,这里不需要CSR,但如果您愿意,也可以。您还可以为Web服务器扩展准备配置文件,以及添加IP地址或其他类型的主题备用名称的选项。)
将证书和私钥的组合导出到每个服务器的PKCS#12(例如server1.p12
)。每个服务器都应该有自己的,不要共享它们。您可以在每个服务器配置中将其用作"keystore keystore"。
keystoreType="PKCS12",
和keyPass
和keystorePass
在使用PKCS#12存储时应该相同。)(使用客户端证书身份验证可能值得确保与服务器的连接至少仅来自同一CA的另一个实体,没有更精确的内容,但您在连接器上配置的信任库会需要只包含您的CA证书,而不是其他证书,因此请为此创建一个全新的信任库。)
答案 1 :(得分:0)
要回答您的问题,我认为您不需要证书链。我已经将tomcat与自签名服务器证书一起使用,并使用另一个自签名客户端证书连接到它。我不知道tomEE,但我想它会是一样的。
为了帮助您弄清楚发生了什么,我想到了这些可能的调试操作:
在进入自动化之前,尝试在没有脚本的情况下使工作正常。生成正确的配置会更容易。
确保脚本正常运行:检查商店的内容是否符合预期,并确保server.xml文件指向正确的。
如果可以,请尝试使用浏览器客户端身份验证单独测试服务器。
最重要的是,确保您的服务器之间确实需要https。如果您处于受保护的领域,那么您可能过度使用安全性并且只是放慢了应用程序的速度。
答案 2 :(得分:0)
如何在tomcats之间使用https时创建两个tomcats会满意的自签名证书?
Tomcat必须允许您执行以下两项操作之一。首先是运行私有PKI,或者第二个是使用pinset。
首先更容易回答:pinset是一组用于标识主机或主机集的可信证书或公钥。它是带有乘数的证书或公钥。在这种情况下,您需要获取3或4个证书并将其应用于每个服务器。然后,当对等方进行通信时,它们将隐含地信任对等方的证书。
Tomcat(或IIS或Apache)不允许您指定pinset。也就是说,您无法指定要信任的自签名证书集合。所以你必须使用私人PKI。
更难的答案是运行私人PKI。运行私有PKI没什么困难的。困难在于实施它,因为它有很多。没有灵丹妙药可以使它工作,因为你需要私有PKI,你需要配置服务器才能使用它。
对于问题“如何使用我自己的CA签署每个证书”,例如,请参阅How To Setup a CA甚至Signing a certificate with my CA和Create my CA how to make a trusted self certified...。
我无法帮助您配置Tomcat。但是,如果您正在构建客户端和服务器,则以下是在OpenSSL中以编程方式执行此操作的步骤。这里,“客户端”和“服务器”表示Tomcat服务器正在扮演的角色(每个角色都扮演两个角色):
客户端
SSL_CTX_load_verify_locations
SSL_CTX_set_default_verify_paths
SSL_CTX_set_verify
SSL_VERIFY_PEER
服务器
SSL_CTX_use_certificate_chain_file
SSL_CTX_use_PrivateKey_file
SSL_CTX_set_verify
SSL_VERIFY_PEER|VERIFY_FAIL_IF_NO_PEER_CERT
当充当客户端时,Tomcat服务器需要知道组织的受信任根。这就是SSL_CTX_load_verify_locations
和SSL_CTX_set_default_verify_paths
完成的事情。
当充当客户端时,SSL_CTX_set_verify
确保Tomcat服务器验证对等方的标识(以OpenSSL中缺少主机名检查为模)。
当充当服务器时,Tomcat服务器需要知道要发送的证书和要签名的私钥。这就是SSL_CTX_use_certificate_chain_file
和SSL_CTX_use_PrivateKey_file
所做的事情。
当充当服务器时,Tomcat服务器需要相互身份验证。这就是SSL_CTX_set_verify
与SSL_VERIFY_PEER|VERIFY_FAIL_IF_NO_PEER_CERT
的关系。
我不知道如何将这些内容写入Tomcat配置中。