简体   繁体   English

如何在自定义JMX客户端中忽略SSL证书

[英]How to ignore SSL certificate in custom JMX client

I want to write a custom JMX client. 我想编写一个自定义的JMX客户端。 The client connects to a server I trust. 客户端连接到我信任的服务器。 I definitely don't want to import the key using the keytool. 我绝对不想使用keytool导入密钥。 It fails when getting the connection with a SsLHandshakeException . 使用SsLHandshakeException获得连接时失败。

String username = "admin";
String password = "admin";
String[] credentials = new String[] { username, password };
Map<String, Object> env = new HashMap<>();
env.put(JMXConnector.CREDENTIALS, credentials);
// Only required for SSL Connections
env.put("com.sun.jndi.rmi.factory.socket", new SslRMIClientSocketFactory());
// MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://trustedhost:10010/jmxrmi");
JMXConnector jmxc = JMXConnectorFactory.connect(url, env);

The Exception I get: 我得到的异常:

Exception in thread "main" java.io.IOException: Failed to retrieve RMIServer stub: javax.naming.CommunicationException [Root exception is java.rmi.ConnectIOException: error during JRMP connection establishment; nested exception is: 
    javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake]
    at javax.management.remote.rmi.RMIConnector.connect(RMIConnector.java:369)
    at javax.management.remote.JMXConnectorFactory.connect(JMXConnectorFactory.java:270)
    at my.monitor.TestMbean.main(TestMbean.java:32)
Caused by: javax.naming.CommunicationException [Root exception is java.rmi.ConnectIOException: error during JRMP connection establishment; nested exception is: 
    javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake]
    at com.sun.jndi.rmi.registry.RegistryContext.lookup(RegistryContext.java:122)
    at com.sun.jndi.toolkit.url.GenericURLContext.lookup(GenericURLContext.java:205)
    at javax.naming.InitialContext.lookup(InitialContext.java:417)
    at javax.management.remote.rmi.RMIConnector.findRMIServerJNDI(RMIConnector.java:1957)
    at javax.management.remote.rmi.RMIConnector.findRMIServer(RMIConnector.java:1924)
    at javax.management.remote.rmi.RMIConnector.connect(RMIConnector.java:287)
    ... 2 more
Caused by: java.rmi.ConnectIOException: error during JRMP connection establishment; nested exception is: 
    javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake
    at sun.rmi.transport.tcp.TCPChannel.createConnection(TCPChannel.java:304)
    at sun.rmi.transport.tcp.TCPChannel.newConnection(TCPChannel.java:202)
    at sun.rmi.server.UnicastRef.newCall(UnicastRef.java:342)
    at sun.rmi.registry.RegistryImpl_Stub.lookup(Unknown Source)
    at com.sun.jndi.rmi.registry.RegistryContext.lookup(RegistryContext.java:118)
    ... 7 more
Caused by: javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake
    at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:980)
    at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1363)
    at sun.security.ssl.SSLSocketImpl.writeRecord(SSLSocketImpl.java:735)
    at sun.security.ssl.AppOutputStream.write(AppOutputStream.java:123)
    at java.io.BufferedOutputStream.flushBuffer(BufferedOutputStream.java:82)
    at java.io.BufferedOutputStream.flush(BufferedOutputStream.java:140)
    at java.io.DataOutputStream.flush(DataOutputStream.java:123)
    at sun.rmi.transport.tcp.TCPChannel.createConnection(TCPChannel.java:229)
    ... 11 more
Caused by: java.io.EOFException: SSL peer shut down incorrectly
    at sun.security.ssl.InputRecord.read(InputRecord.java:505)
    at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:961)
    ... 18 more

I don't know a way to circumvent the SSL security which Java requires but I think you should reconsider your stance on "I definitely don't want to import the key using the keytool." 我不知道有什么方法可以规避Java所需的SSL安全性,但我认为您应该重新考虑“我绝对不想使用keytool导入密钥”的立场。 The question isn't whether you trust the server. 问题不在于您是否信任服务器。 The important questions are: 重要的问题是:

  1. You want plain text communication with the server. 您希望与服务器进行纯文本通信。 How many people will be able to listen on this? 有多少人可以听呢? If your client runs inside the local network, then only everyone in the same company will be able to spy on you. 如果您的客户端在局域网内运行,则只有同一公司的每个人都可以监视您。 If you leave the protected network, an unknown number of people can suddenly watch what you're doing. 如果您离开受保护的网络,则未知人数的人会突然看着您在做什么。
  2. If you disable SSL in the client, how should the server make sure that commands are coming from you? 如果在客户端中禁用SSL,服务器应如何确保命令来自您? Without SSL, someone could hijack your communication and take control of the server. 没有SSL,某人可能会劫持您的通信并控制服务器。
  3. Without SSL, the password will be transmitted as plain text. 没有SSL,密码将以纯文本格式传输。 A TV station recently found that having post it notes with passwords on the wall while giving interviews is not a smart move in 2015. 一个电视台最近发现 ,在接受采访时在墙上贴上带有密码的便条在2015年并不是明智之举。

So the correct question should be: How can I set up SSL correctly to secure JMX? 因此,正确的问题应该是:如何正确设置SSL以保护JMX? See http://docs.oracle.com/javase/8/docs/technotes/guides/management/agent.html search "Using SSL" 请参见http://docs.oracle.com/javase/8/docs/technotes/guides/management/agent.html搜索“使用SSL”

The client connects to a server I trust. 客户端连接到我信任的服务器。

How do you know? 你怎么知道的? The whole purpose of certificate validation is to make sure that you actually connect to the server you want to and not to some man-in-the-middle. 证书验证的整个目的是确保您确实连接到想要的服务器,而不是中间人。

Try putting this before your code 尝试将其放在代码之前

TrustManager[] trustAllCerts = new TrustManager[]{new X509TrustManager() {
    public java.security.cert.X509Certificate[] getAcceptedIssuers() {
        return null;
    }

    public void checkClientTrusted(X509Certificate[] certs, String authType) {
    }

    public void checkServerTrusted(X509Certificate[] certs, String authType) {
    }
}
};

try {
    logger.info("Hacking SSL Validation");
    SSLContext sc = SSLContext.getInstance("SSL");
    sc.init(null, trustAllCerts, new java.security.SecureRandom());
    SSLContext.setDefault(sc);
    logger.info("SSL Validation hacked");
} catch (Exception e) {
    throw new RuntimeException(e);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM