VisualVM 之 SSL+JMX

在前面两篇文章中分别介绍了了如何使用jstatd和JMX来配置VisualVM做一个监控。但生产环境中,往往是需要经过合法性的校验才允许创建链接的,之前的方式适合测试环境操作。在生成环境中,强烈建议使用SSL认证。SSL需要提供证书才能访问,安全性较高。

 

第一步:制作keystore 和truststore

由于SSL是一个非对称加密协议,因此会有public key 和 private key,而public key、private key是保存在keystore里面的。

下面主要讲下client 和 server 的keystore 、truststore制作流程。主要步骤是

1、生成client keystore ,从client keystore导出cer, 将 cer 导入到server truststore(生成server truststore)

2、生成server keystore ,从server keystore导出cer, 将 cer 导入到client truststore(生成client truststore)

 

具体流程

1、client keystore

 

格式:

keytool -genkeypair \
-alias <client名称> \
-keyalg RSA \
-validity 365 \
-storetype pkcs12 \
-keystore <client名称>.keystore \
-storepass <client keystore password> \
-keypass <同 client keystore password> \
-dname "CN=<姓名> OU=<组织下属单位> O=<组织> L=<城市> S=<省> C=<国家>"

 

示例:

keytool -genkeypair \
-alias visualvm \
-keyalg RSA \
-validity 365 \
-storetype pkcs12 \
-keystore visualvm.keystore \
-storepass 123456 \
-keypass 123456 \
-dname "CN=chihay OU=Alphalion O=dev L=GZ S=GD C=CN"

 

2、client cer

格式:

keytool -exportcert \
-alias <client name> \
-storetype pkcs12 \
-keystore <client name>.keystore \
-file <client name>.cer \
-storepass <client keystore password>

示例:

keytool -exportcert \
-alias visualvm \
-storetype pkcs12 \
-keystore visualvm.keystore \
-file visualvm.cer \
-storepass 123456

 

3、生成server truststore

 

格式:

keytool -importcert \
-alias <client name> \
-file <client name(上一步生成的文件名)>.cer \
-keystore <servier name>.truststore \
-storepass <servier truststore password> \
-noprompt

 

示例:

keytool -importcert \
-alias visualvm \
-file visualvm.cer \
-keystore visualvm-test-app.truststore \
-storepass 789012 \
-noprompt

 

4、server keystore(跟第一步格式是一样的)

格式:

keytool -genkeypair \
-alias <server名称> \
-keyalg RSA \
-validity 365 \
-storetype pkcs12 \
-keystore <server名称>.keystore \
-storepass <server keystore password> \
-keypass <同 server keystore password> \
-dname "CN=<姓名> OU=<组织下属单位> O=<组织> L=<城市> S=<省> C=<国家>"

示例:

 keytool -genkeypair \
-alias visualvm-test-app \
-keyalg RSA \
-validity 365 \
-storetype pkcs12 \
-keystore visualvm-test-app.keystore \
-storepass 012345 \
-keypass 012345 \
-dname "CN=chihay OU=Alphalion O=dev L=GZ S=GD C=CN"

 

5、server cer (跟第二步格式一样)

格式:

keytool -exportcert \
-alias <server name> \
-storetype pkcs12 \
-keystore <server name>.keystore \
-file <server name>.cer \
-storepass <server keystore password>

示例:

keytool -exportcert \
-alias visualvm-test-app \
-storetype pkcs12 \
-keystore visualvm-test-app.keystore \
-file visualvm-test-app.cer \
-storepass 012345

 

6、client truststore(跟第三步格式一样)

格式:

keytool -importcert \
-alias <server name> \
-file <server name(上一步生成的server文件名)>.cer \
-keystore <client name>.truststore \
-storepass <client truststore password> \
-noprompt

示例:

keytool -importcert \
-alias visualvm-test-app \
-file visualvm-test-app.cer \
-keystore visualvm.truststore \
-storepass 678901 \
-noprompt

 

 

最终生成六个文件

 

第二步:启动server服务

启动命令(注意参数名称和内容不要写错,否则client会报JMX链接不上):

java -jar -Dcom.sun.management.jmxremote \
-Dcom.sun.management.jmxremote.port=<port>  \
-Dcom.sun.management.jmxremote.rmi.port=<同样port>  \
-Djava.rmi.server.hostname=<ip> \
-Dcom.sun.management.jmxremote.authenticate=false \
-Dcom.sun.management.jmxremote.ssl=true \
-Dcom.sun.management.jmxremote.registry.ssl=true \
-Dcom.sun.management.jmxremote.ssl.need.client.auth=true \
-Djavax.net.ssl.keyStore=<path server keyStore> \
-Djavax.net.ssl.keyStorePassword=<server keyStorePassword> \
-Djavax.net.ssl.trustStore=<path server trustStore> \
-Djavax.net.ssl.trustStorePassword=<server trustStorePassword>  \
visualvmtest-0.0.1-SNAPSHOT.jar

示例:

java -jar -Dcom.sun.management.jmxremote \
-Dcom.sun.management.jmxremote.port=2223  \
-Dcom.sun.management.jmxremote.rmi.port=2223  \
-Djava.rmi.server.hostname=192.168.124.18 \
-Dcom.sun.management.jmxremote.authenticate=false \
-Dcom.sun.management.jmxremote.ssl=true \
-Dcom.sun.management.jmxremote.registry.ssl=true \
-Dcom.sun.management.jmxremote.ssl.need.client.auth=true \
-Djavax.net.ssl.keyStore=/opt/visualvm-test/keystore/visualvm-test-app.keystore \
-Djavax.net.ssl.keyStorePassword=012345 \
-Djavax.net.ssl.trustStore=/opt/visualvm-test/keystore/visualvm-test-app.truststore \
-Djavax.net.ssl.trustStorePassword=789012  \
visualvmtest-0.0.1-SNAPSHOT.jar

第三步:启动client

如果这个时候直接打开VisualVM app,是链接不上server的。server会报错:

2020-09-07 09:40:01.332  WARN 3092 --- [MI TCP Accept-0] sun.rmi.transport.tcp                    : RMI TCP Accept-0: accept loop for ServerSocket[addr=0.0.0.0/0.0.0.0,localport=44883] throws

java.net.SocketException: java.security.NoSuchAlgorithmException: Error constructing implementation (algorithm: Default, provider: SunJSSE, class: sun.security.ssl.SSLContextImpl$DefaultSSLContext)
        at javax.net.ssl.DefaultSSLSocketFactory.throwException(SSLSocketFactory.java:248) ~[na:1.8.0_171]
        at javax.net.ssl.DefaultSSLSocketFactory.createSocket(SSLSocketFactory.java:270) ~[na:1.8.0_171]
        at sun.management.jmxremote.ConnectorBootstrap$SslServerSocket.accept(ConnectorBootstrap.java:992) ~[na:1.8.0_171]
        at sun.rmi.transport.tcp.TCPTransport$AcceptLoop.executeAcceptLoop(TCPTransport.java:405) [na:1.8.0_171]
        at sun.rmi.transport.tcp.TCPTransport$AcceptLoop.run(TCPTransport.java:377) [na:1.8.0_171]
        at java.lang.Thread.run(Thread.java:748) [na:1.8.0_171]
Caused by: java.security.NoSuchAlgorithmException: Error constructing implementation (algorithm: Default, provider: SunJSSE, class: sun.security.ssl.SSLContextImpl$DefaultSSLContext)
        at java.security.Provider$Service.newInstance(Provider.java:1617) ~[na:1.8.0_171]
        at sun.security.jca.GetInstance.getInstance(GetInstance.java:236) ~[na:1.8.0_171]
        at sun.security.jca.GetInstance.getInstance(GetInstance.java:164) ~[na:1.8.0_171]
        at javax.net.ssl.SSLContext.getInstance(SSLContext.java:156) ~[na:1.8.0_171]
        at javax.net.ssl.SSLContext.getDefault(SSLContext.java:96) ~[na:1.8.0_171]
        at javax.net.ssl.SSLSocketFactory.getDefault(SSLSocketFactory.java:122) ~[na:1.8.0_171]
        at sun.management.jmxremote.ConnectorBootstrap$SslServerSocket.getDefaultSSLSocketFactory(ConnectorBootstrap.java:1008) ~[na:1.8.0_171]
        at sun.management.jmxremote.ConnectorBootstrap$SslServerSocket.accept(ConnectorBootstrap.java:990) ~[na:1.8.0_171]
        ... 3 common frames omitted
Caused by: java.security.PrivilegedActionException: null
        at java.security.AccessController.doPrivileged(Native Method) ~[na:1.8.0_171]
        at sun.security.ssl.SSLContextImpl$DefaultManagersHolder.getKeyManagers(SSLContextImpl.java:822) ~[na:1.8.0_171]
        at sun.security.ssl.SSLContextImpl$DefaultManagersHolder.<clinit>(SSLContextImpl.java:758) ~[na:1.8.0_171]
        at sun.security.ssl.SSLContextImpl$DefaultSSLContext.<init>(SSLContextImpl.java:913) ~[na:1.8.0_171]
        at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) ~[na:1.8.0_171]
        at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) ~[na:1.8.0_171]
        at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) ~[na:1.8.0_171]
        at java.lang.reflect.Constructor.newInstance(Constructor.java:423) ~[na:1.8.0_171]
        at java.security.Provider$Service.newInstance(Provider.java:1595) ~[na:1.8.0_171]
        at sun.security.jca.GetInstance.getInstance(GetInstance.java:236) ~[na:1.8.0_171]
        at sun.security.jca.GetInstance.getInstance(GetInstance.java:164) ~[na:1.8.0_171]
        at javax.net.ssl.SSLContext.getInstance(SSLContext.java:156) ~[na:1.8.0_171]
        at javax.net.ssl.SSLContext.getDefault(SSLContext.java:96) ~[na:1.8.0_171]
        at javax.net.ssl.SSLSocketFactory.getDefault(SSLSocketFactory.java:122) ~[na:1.8.0_171]
        at javax.rmi.ssl.SslRMIServerSocketFactory.getDefaultSSLSocketFactory(SslRMIServerSocketFactory.java:368) ~[na:1.8.0_171]
        at javax.rmi.ssl.SslRMIServerSocketFactory.<init>(SslRMIServerSocketFactory.java:180) ~[na:1.8.0_171]
        at javax.rmi.ssl.SslRMIServerSocketFactory.<init>(SslRMIServerSocketFactory.java:118) ~[na:1.8.0_171]
        at javax.rmi.ssl.SslRMIServerSocketFactory.<init>(SslRMIServerSocketFactory.java:80) ~[na:1.8.0_171]
        at sun.management.jmxremote.ConnectorBootstrap$HostAwareSslSocketFactory.<init>(ConnectorBootstrap.java:891) ~[na:1.8.0_171]
        at sun.management.jmxremote.ConnectorBootstrap$HostAwareSslSocketFactory.<init>(ConnectorBootstrap.java:884) ~[na:1.8.0_171]
        at sun.management.jmxremote.ConnectorBootstrap$HostAwareSslSocketFactory.<init>(ConnectorBootstrap.java:872) ~[na:1.8.0_171]
        at sun.management.jmxremote.ConnectorBootstrap.createSslRMIServerSocketFactory(ConnectorBootstrap.java:649) ~[na:1.8.0_171]
        at sun.management.jmxremote.ConnectorBootstrap.exportMBeanServer(ConnectorBootstrap.java:774) ~[na:1.8.0_171]
        at sun.management.jmxremote.ConnectorBootstrap.startRemoteConnectorServer(ConnectorBootstrap.java:468) ~[na:1.8.0_171]
        at sun.management.Agent.startAgent(Agent.java:262) ~[na:1.8.0_171]
        at sun.management.Agent.startAgent(Agent.java:452) ~[na:1.8.0_171]
Caused by: java.io.FileNotFoundException: 012345 (没有那个文件或目录)
        at java.io.FileInputStream.open0(Native Method) ~[na:1.8.0_171]
        at java.io.FileInputStream.open(FileInputStream.java:195) ~[na:1.8.0_171]
        at java.io.FileInputStream.<init>(FileInputStream.java:138) ~[na:1.8.0_171]
        at java.io.FileInputStream.<init>(FileInputStream.java:93) ~[na:1.8.0_171]
        at sun.security.ssl.SSLContextImpl$DefaultManagersHolder$2.run(SSLContextImpl.java:826) ~[na:1.8.0_171]
        at sun.security.ssl.SSLContextImpl$DefaultManagersHolder$2.run(SSLContextImpl.java:823) ~[na:1.8.0_171]
        ... 26 common frames omitted

 

正确方式应该是在$JAVA_HOME/bin目录下,使用jvisualvm 并带上keyPassword 和truststorePassword启动 client。这时会直接打开一个客户端。这是一个使用证书创建的链接。在创建的时候选不选SSL都可以的。

jvisualvm -J-Djavax.net.ssl.keyStore=/Users/yang/Documents/file/keystore/visualvm.keystore \
-J-Djavax.net.ssl.keyStorePassword=123456 \
-J-Djavax.net.ssl.trustStore=/Users/yang/Documents/file/keystore/visualvm.truststore \
-J-Djavax.net.ssl.trustStorePassword=678901

 

总结:

1、生成keyStore 和 trustStore 参数要写对,password要对应的上

2、启动的时候,参数值要写对,这点比较坑,写错了参数是会报链接不上。所以出现链接不上的时候要先确认参数对了,再去看是不是防火墙端口这些问题导致的。比如正确的密码是678901,但是写错成6789012的话就不行了。还有路径也会导致这些问题。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值