在里提到在生产环境下应该使用SSL来创建JMX连接,本文就来讲一下具体怎么做。
前导知识
先了解一下Java客户端程序在创建SSL连接的一些相关的事情:
- Java client程序在做SSL连接的时候,会拉取server的证书,利用truststore去验证这个证书,如果不存在 or 证书过期 or 不是由可信CA签发,就意味着服务端不被信任,就不能连接。
- 如果在程序启动时没有特别指定使用哪个truststore(通过System Property
javax.net.ssl.trustStore
指定),那么就会使用$JAVA_HOME/jre/lib/security/cacerts
。如果指定了,就会使用指定的truststore + cacerts来验证。 - cacerts存放了JDK信任的CA证书(含有public key),它里面预先已经存放了已知的权威CA证书。你可以通过
keytool -list -keystore $JAVA_HOME/jre/lib/security/cacerts
看到(让你输密码的时候直接回车就行了)
以上过程被称为server authentication,也就是说client验证server是否可信,server authentication是最常见的,https就是这种模式。
不过在用SSL连接JMX的时候,还要做client authentication,即server验证client是否可信。原理和上面提到的一样,只不过变成server用自己的truststore里验证client的证书是否可信。
第一步:制作keystore和truststore
上面提到的证书主要保存了一个public key,SSL是一个非对称加密协议,因此还有一个对应的private key,在java里private key和private key存放在keystore里。
下面我们来制作visualvm(client)和java app(server)的keystore和truststore。
先讲大致流程,然后再给出命令:
- 生成visualvm的keystore,导出cert,把cert导入到java-app的truststore里
- 生成java-app的keystore,导出cert,把cert导入到visualvm的truststore里
具体命令:
-
生成visualvm的keystore
keytool -genkeypair \ -alias visualvm \ -keyalg RSA \ -validity 365 \ -storetype pkcs12 \ -keystore visualvm.keystore \ -storepass
\ -keypass <同visualvm keystore的密码> \ -dname "CN= <姓名> , OU= <组织下属单位> , O= <组织名称> , L= <城市> , S= <省份> , C= <国家2字母> " 国家2字母> 省份> 城市> 组织名称> 组织下属单位> 姓名> 同visualvm> -
导出visualvm的cert
keytool -exportcert \ -alias visualvm \ -storetype pkcs12 \ -keystore visualvm.keystore \ -file visualvm.cer \ -storepass
-
把visualvm的cert导入到java-app的truststore里,实际上就是生成了一个truststore
keytool -importcert \ -alias visualvm \ -file visualvm.cer \ -keystore java-app.truststore \ -storepass
\ -noprompt -
生成java-app的keystore
keytool -genkeypair \ -alias java-app \ -keyalg RSA \ -validity 365 \ -storetype pkcs12 \ -keystore java-app.keystore \ -storepass
\ -keypass <同java-app keystore的密码> \ -dname "CN= <姓名> , OU= <组织下属单位> , O= <组织名称> , L= <城市> , S= <省份> , C= <国家2字母> " 国家2字母> 省份> 城市> 组织名称> 组织下属单位> 姓名> 同java-app> -
导出java-app的cert
keytool -exportcert \ -alias java-app \ -storetype pkcs12 \ -keystore java-app.keystore \ -file java-app.cer \ -storepass
-
把java-app的cert导入到visualvm的truststore里
keytool -importcert -alias java-app \ -file java-app.cer \ -keystore visualvm.truststore \ -storepass
\ -noprompt
所以最终得到的文件是这么几个:
- visualvm.keystore,包含visualvm的public key和private key
- visualvm.truststore,包含java-app cert
- java-app.keystore,包含java-app的public key和private key
- java-app.truststore,包含visualvm cert
第二步:启动Tomcat
我们还是用Tomcat做实验,给CATALINA_OPTS
添加几个参数像下面这样,因为参数比较多,所以我们在$TOMCAT/bin
下添加一个setenv.sh
的文件(记得加上可执行权限):
CATALINA_OPTS="-Dcom.sun.management.jmxremote"CATALINA_OPTS="$CATALINA_OPTS -Dcom.sun.management.jmxremote.port=1100"CATALINA_OPTS="$CATALINA_OPTS -Dcom.sun.management.jmxremote.rmi.port=1100"CATALINA_OPTS="$CATALINA_OPTS -Djava.rmi.server.hostname="CATALINA_OPTS="$CATALINA_OPTS -Dcom.sun.management.jmxremote.authenticate=false"# 以下和启用SSL有关CATALINA_OPTS="$CATALINA_OPTS -Dcom.sun.management.jmxremote.ssl=true"CATALINA_OPTS="$CATALINA_OPTS -Dcom.sun.management.jmxremote.registry.ssl=true"CATALINA_OPTS="$CATALINA_OPTS -Dcom.sun.management.jmxremote.ssl.need.client.auth=true"CATALINA_OPTS="$CATALINA_OPTS -Djavax.net.ssl.keyStore= "CATALINA_OPTS="$CATALINA_OPTS -Djavax.net.ssl.keyStorePassword= "CATALINA_OPTS="$CATALINA_OPTS -Djavax.net.ssl.trustStore= "CATALINA_OPTS="$CATALINA_OPTS -Djavax.net.ssl.trustStorePassword= "
然后$TOMCAT/bin/startup.sh
第三步:启动visualvm
jvisualvm -J-Djavax.net.ssl.keyStore=\ -J-Djavax.net.ssl.keyStorePassword= \ -J-Djavax.net.ssl.trustStore= \ -J-Djavax.net.ssl.trustStorePassword=
你可以不加参数启动jvisualvm,看看下一步创建JMX连接是否成功,如果配置正确应该是不会成功的。
第四步:创建JMX连接
加了上述参数启动jvisualvm后,和里提到的步骤一样创建JMX连接,只不过在创建JMX连接的时候不要勾选【不要求SSL连接】(不过经实测,勾不勾选都能连接成功的)。
参考资料
- ,这个表格列出了一些SSL相关的System Properties
- ,这是Java对于SSL支持的最全的参考文档
我的博客即将同步至腾讯云+社区,邀请大家一同入驻: