使用SSL和自签名证书使JMX在Tomcat 7下运行

时间:2013-09-26 16:13:19

标签: java tomcat ssl jmx

我正在尝试使用SSL在Tomcat 7.0.23下运行JMX。服务器位于AWS中,这意味着所有主机都是NAT,我需要使用JmxRemoteLifecycleListener来显式设置JMX使用的两个端口。我一直在做很多关于这个主题的阅读,但我不能让所有的部分正确地协同工作。

没有SSL,我可以让JMX正常工作。我为我的Tomcat版本下载了catalina-jmx-remote.jar的版本,并将其安装在我的tomcat / lib目录中。我的server.xml包含:

  <Listener className="org.apache.catalina.mbeans.JmxRemoteLifecycleListener" 
        rmiRegistryPortPlatform="1099" rmiServerPortPlatform="1098" />

当我使用以下设置启动Tomcat时,我可以使用不安全的会话进行连接:

-Dcom.sun.management.jmxremote 
-Dcom.sun.management.jmxremote.password.file=/path/to/jmxremote.password 
-Dcom.sun.management.jmxremote.access.file=/path/to/jmxremote.access 
-Djava.rmi.server.hostname=<public IP of server> 
-Dcom.sun.management.jmxremote.ssl=false

但是,如果我将这些更改为以下内容,则无法建立SSL连接:

-Dcom.sun.management.jmxremote 
-Dcom.sun.management.jmxremote.password.file=/path/to/jmxremote.password 
-Dcom.sun.management.jmxremote.access.file=/path/to/jmxremote.access 
-Djava.rmi.server.hostname=<public IP of server> 
-Dcom.sun.management.jmxremote.ssl=true
-Dcom.sun.management.jmxremote.ssl.need.client.auth=false 
-Dcom.sun.management.jmxremote.authenticate=true
-Djavax.net.ssl.keyStore=/path/to/keystore.dat 
-Djavax.net.ssl.keyStorePassword=<password>
-Djavax.net.ssl.trustStore=/path/to/truststore.dat 
-Djavax.net.ssl.trustStorePassword=<password>

keystore.dat只包含通过以下方式创建的单个证书:

openssl x509 -outform der -in cert.pem -out cert.der
keytool -import -alias tomcat -keystore keystore.dat -file cert.der -storepass <password>

truststore.dat包含java cacerts的完整副本以及我自签名证书的CA证书:

cp $JAVA_HOME/jre/lib/security/cacerts truststore.dat
keytool -storepasswd -storepass changeit -new <password> -keystore truststore.dat
keytool -import -trustcacerts -file mycacert.pem -alias myalias -keystore truststore.dat -storepass <password>

启动Tomcat后我尝试通过jconsole连接,但无法建立连接。我尝试使用openssl验证SSL,但看起来Tomcat没有使用证书:

$ openssl s_client -connect <host>:1099
CONNECTED(00000003)
140735160957372:error:140790E5:SSL routines:SSL23_WRITE:ssl handshake failure:s23_lib.c:177:
---
no peer certificate available
---
No client certificate CA names sent
---
SSL handshake has read 0 bytes and written 322 bytes
---
New, (NONE), Cipher is (NONE)
Secure Renegotiation IS NOT supported
Compression: NONE
Expansion: NONE
---

我已经通过导出密钥并验证证书链来验证我的本地密钥库和信任库是否已正确设置(combined.pem是来自truststore.dat的所有CA证书,cert.pem是来自keystore.dat的证书) ):

$ openssl verify -verbose -purpose sslserver -CAfile combined.pem cert.pem
cert.pem: OK

所以现在我完全失去了。证书和CA证书看起来正确。未加密的JMX连接有效。但我似乎无法获得使用SSL的连接。我在这里错过了什么?

我不知道这只是一个红鲱鱼,但我没有看到任何方法来指定JMX使用keyStore中的证书。我读到的一些内容暗示它只使用带有别名“tomcat”的证书。这是对的吗?

2 个答案:

答案 0 :(得分:1)

您正在端口 1099 上启动 RMI注册表。要使 RMI注册表使用 SSL ,您需要传递额外的-Dcom.sun.management.jmxremote.registry.ssl=true参数。

修改 您是否使用jconsole -J-Djavax.net.ssl.trustStore=truststore -J-Djavax.net.ssl.trustStorePassword=trustword -Djavax.net.ssl.keyStore=keystore -Djavax.net.ssl.keyStorePassword=password启动JConsole?它需要知道商店的位置和相应的密码。

对于VisualVM,您可以安装 VisualVM-Security 插件,该插件将在“选项”对话框中添加新选项卡,允许您在UI中自定义SSL相关选项。

答案 1 :(得分:1)

我希望tomcat能够使用jmx和ssl并跟随Bruce设置。万一有人遇到同样的问题:使用openssl和keytool命令形成Bruce我遇到客户端ssl错误:

javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure

不知道为什么,但一方面的指纹在开始时长了5个字符。

我使用以下方法重新创建了密钥库:

keytool -genkeypair -alias tomcat -keyalg RSA -keystore keystore.jks -dname cn=test,ou=test,dc=example,dc=com

在tomcat sever.xml中,我按照Bruce的建议添加了监听器。

因为客户端身份验证设置为false,所以我不在tomcat jmx配置中添加truststore。相反,我添加了registry.ssl:

[...]
-Djavax.net.ssl.keyStorePassword=your_keystore_pass
-Dcom.sun.management.jmxremote.registry.ssl=true

然后在客户端,因为J.B.建议我为visualvm下载ssl插件并纵横交错密钥库,导致:

visualvm -J-Djavax.net.ssl.trustStore=keystore.jks -J-Djavax.net.ssl.trustStorePassword=your_keystore_pass

添加身份验证时,请确保您的jmx访问文件如下所示:

<user_name>    readwrite

,您的密码文件如下:

<user_name>    <your_password>

这解决了我使用visualm vm进行测试的ssl jmx设置。

修改

通过SSL设置注册表也存在一些问题,请按以下方式设置:

-Dcom.sun.management.jmxremote.registry.ssl=true

引导客户抛出:

Root exception is java.rmi.ConnectIOException: non-JRMP server at remote endpoint

添加客户端身份验证:

-Dcom.sun.management.jmxremote.ssl.need.client.auth=true
-Djavax.net.ssl.trustStore=truststore.jks
-Djavax.net.ssl.trustStorePassword=your_trust_store_pass

解决了jmx及其注册表以使用ssl。