rabbitmq SSL安全问题,套接字异常:管道中断(写入失败)

xghobddn  于 2022-11-08  发布在  RabbitMQ
关注(0)|答案(1)|浏览(235)
package com.rm.rabbitmq.tls;

import java.io.*;
import java.security.*;
import javax.net.ssl.*;

import com.rabbitmq.client.*;

public class Example2 {

    public static void main(String[] args) throws Exception {
        char[] keyPassphrase = "".toCharArray();
        KeyStore ks = KeyStore.getInstance("PKCS12");
        ks.load(new FileInputStream("/Users/global/Documents/tls-gen/basic/result/client_key.p12"), keyPassphrase);

        KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
        kmf.init(ks, keyPassphrase);

        char[] trustPassphrase = "welcome".toCharArray();
        KeyStore tks = KeyStore.getInstance("JKS");
        tks.load(new FileInputStream("/Users/global/Documents/tls-gen/basic/result/truststore"), trustPassphrase);

        TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
        tmf.init(tks);

        SSLContext c = SSLContext.getInstance("TLSv1.3");
        c.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);

        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("localhost");
        factory.setPort(5671);
        factory.useSslProtocol(c);
        factory.useSslProtocol("TLSv1.2");
        //factory.enableHostnameVerification();

        Connection conn = factory.newConnection();
        Channel channel = conn.createChannel();

        channel.queueDeclare("rabbitmq-java-test", false, true, true, null);
        channel.basicPublish("", "rabbitmq-java-test", null, "Hello, World".getBytes());

        GetResponse chResponse = channel.basicGet("rabbitmq-java-test", false);
        if (chResponse == null) {
            System.out.println("No message retrieved");
        } else {
            byte[] body = chResponse.getBody();
            System.out.println("Received: " + new String(body));
        }

        channel.close();
        conn.close();
    }
}

RabbitMq配置文件高级配置文件

[
  {ssl, [{versions, ['tlsv1.3', 'tlsv1.2','tlsv1.1']}]},
  {rabbit, [
     {ssl_listeners, [5671]},
     {ssl_options, [{cacertfile, "/Users/global/Documents/tls-gen/basic/result/ca_certificate.pem"},
                    {certfile,   "/Users/global/Documents/tls-gen/basic/result/server_certificate.pem"},
                    {keyfile,    "/Users/global/Documents/tls-gen/basic/result/server_key.pem"},
                    {verify,     verify_peer},
                    {fail_if_no_peer_cert, true}]}
   ]}
].

让我们验证一下rabbitMq是否开始支持TLS连接?

2022-06-02 21:20:29.062237+05:30 [info] <0.658.0> started TCP listener on 127.0.0.1:5672
2022-06-02 21:20:29.063290+05:30 [info] <0.678.0> started TLS (SSL) listener on [::]:5671

现在是时候检查使用java客户端连接到rabbitmq时的详细错误了。

javax.net.ssl|FINE|01|main|2022-06-02 22:08:46.906 IST|SunX509KeyManagerImpl.java:164|found key for : 1 (
  "certificate" : {
    "version"            : "v3",
    "serial number"      : "02",
    "signature algorithm": "SHA256withRSA",
    "issuer"             : "L=$$$$, CN=TLSGenSelfSignedtRootCA 2022-06-01T22:41:29.160912",
    "not before"         : "2022-06-01 22:41:33.000 IST",
    "not  after"         : "2032-05-29 22:41:33.000 IST",
    "subject"            : "O=client, CN=del1-lmc-n72765.local",
    "subject public key" : "RSA",
    "extensions"         : [
      {
        ObjectId: 2.5.29.19 Criticality=false
        BasicConstraints:[
          CA:false
          PathLen: undefined
        ]
      },
      {
        ObjectId: 2.5.29.31 Criticality=false
        CRLDistributionPoints [
          [DistributionPoint:
             [URIName: http://localhost:8000/basic.crl]
        ]]
      },
      {
        ObjectId: 2.5.29.37 Criticality=false
        ExtendedKeyUsages [
          clientAuth
        ]
      },
      {
        ObjectId: 2.5.29.15 Criticality=false
        KeyUsage [
          DigitalSignature
          Key_Encipherment
        ]
      },
      {
        ObjectId: 2.5.29.17 Criticality=false
        SubjectAlternativeName [
          DNSName: del1-lmc-n72765.local
          DNSName: del1-lmc-n72765.local
          DNSName: localhost
        ]
      }
    ]}
)
javax.net.ssl|FINE|01|main|2022-06-02 22:08:46.916 IST|X509TrustManagerImpl.java:78|adding as trusted certificates (
  "certificate" : {
    "version"            : "v3",
    "serial number"      : "01",
    "signature algorithm": "SHA256withRSA",
    "issuer"             : "L=$$$$, CN=TLSGenSelfSignedtRootCA 2022-06-01T22:41:29.160912",
    "not before"         : "2022-06-01 22:41:32.000 IST",
    "not  after"         : "2032-05-29 22:41:32.000 IST",
    "subject"            : "O=server, CN=del1-lmc-n72765.local",
    "subject public key" : "RSA",
    "extensions"         : [
      {
        ObjectId: 2.5.29.35 Criticality=false
        AuthorityKeyIdentifier [
        KeyIdentifier [
        0000: 80 1C 48 61 BB 42 15 D6   0C 1C 2A D8 37 B6 13 94  ..Ha.B....*.7...
        0010: 9A 91 65 3F                                        ..e?
        ]
        ]
      },
      {
        ObjectId: 2.5.29.19 Criticality=false
        BasicConstraints:[
          CA:false
          PathLen: undefined
        ]
      },
      {
        ObjectId: 2.5.29.31 Criticality=false
        CRLDistributionPoints [
          [DistributionPoint:
             [URIName: http://localhost:8000/basic.crl]
        ]]
      },
      {
        ObjectId: 2.5.29.37 Criticality=false
        ExtendedKeyUsages [
          serverAuth
        ]
      },
      {
        ObjectId: 2.5.29.15 Criticality=false
        KeyUsage [
          DigitalSignature
          Key_Encipherment
        ]
      },
      {
        ObjectId: 2.5.29.17 Criticality=false
        SubjectAlternativeName [
          DNSName: del1-lmc-n72765.local
          DNSName: del1-lmc-n72765.local
          DNSName: localhost
        ]
      },
      {
        ObjectId: 2.5.29.14 Criticality=false
        SubjectKeyIdentifier [
        KeyIdentifier [
        0000: CF 1A 03 E3 8D EB F5 53   5E E2 3C 49 AF C9 15 2B  .......S^.<I...+
        0010: 20 89 DF 65                                         ..e
        ]
        ]
      }
    ]}
)

    javax.net.ssl|FINE|01|main|2022-06-02 22:08:47.170 IST|SSLSocketOutputRecord.java:258|WRITE: TLS12 handshake, length = 258
    javax.net.ssl|SEVERE|01|main|2022-06-02 22:08:47.174 IST|TransportContext.java:362|Fatal (HANDSHAKE_FAILURE): Couldn't kickstart handshaking (
    "throwable" : {
      java.net.SocketException: Broken pipe (Write failed)
        at java.net.SocketOutputStream.socketWrite0(Native Method)
        at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:111)
        at java.net.SocketOutputStream.write(SocketOutputStream.java:155)
        at sun.security.ssl.SSLSocketOutputRecord.flush(SSLSocketOutputRecord.java:268)
        at sun.security.ssl.HandshakeOutStream.flush(HandshakeOutStream.java:89)
        at sun.security.ssl.ClientHello$ClientHelloKickstartProducer.produce(ClientHello.java:572)
        at sun.security.ssl.SSLHandshake.kickstart(SSLHandshake.java:509)
        at sun.security.ssl.ClientHandshakeContext.kickstart(ClientHandshakeContext.java:115)
        at sun.security.ssl.TransportContext.kickstart(TransportContext.java:250)
        at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:394)
        at sun.security.ssl.SSLSocketImpl.ensureNegotiated(SSLSocketImpl.java:819)
        at sun.security.ssl.SSLSocketImpl.access$200(SSLSocketImpl.java:75)
        at sun.security.ssl.SSLSocketImpl$AppOutputStream.write(SSLSocketImpl.java:1104)
        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 com.rabbitmq.client.impl.SocketFrameHandler.sendHeader(SocketFrameHandler.java:129)
        at com.rabbitmq.client.impl.SocketFrameHandler.sendHeader(SocketFrameHandler.java:134)
        at com.rabbitmq.client.impl.AMQConnection.start(AMQConnection.java:276)
        at com.rabbitmq.client.ConnectionFactory.newConnection(ConnectionFactory.java:590)
        at com.rabbitmq.client.ConnectionFactory.newConnection(ConnectionFactory.java:612)
        at com.rm.rabbitmq.tls.Example2.main(Example2.java:40)}

    )
    javax.net.ssl|ALL|01|main|2022-06-02 22:08:47.174 IST|SSLSessionImpl.java:839|Invalidated session:  Session(1654187927078|SSL_NULL_WITH_NULL_NULL)
    javax.net.ssl|FINE|01|main|2022-06-02 22:08:47.175 IST|SSLSocketOutputRecord.java:73|WRITE: TLS12 alert(handshake_failure), length = 2
    javax.net.ssl|WARNING|01|main|2022-06-02 22:08:47.176 IST|TransportContext.java:404|Fatal: failed to send fatal alert HANDSHAKE_FAILURE (
    "throwable" : {
      java.net.SocketException: Broken pipe (Write failed)
        at java.net.SocketOutputStream.socketWrite0(Native Method)
        at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:111)
        at java.net.SocketOutputStream.write(SocketOutputStream.java:155)
        at sun.security.ssl.SSLSocketOutputRecord.encodeAlert(SSLSocketOutputRecord.java:83)
        at sun.security.ssl.TransportContext.fatal(TransportContext.java:401)
        at sun.security.ssl.TransportContext.fatal(TransportContext.java:313)
        at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:411)
        at sun.security.ssl.SSLSocketImpl.ensureNegotiated(SSLSocketImpl.java:819)
        at sun.security.ssl.SSLSocketImpl.access$200(SSLSocketImpl.java:75)
        at sun.security.ssl.SSLSocketImpl$AppOutputStream.write(SSLSocketImpl.java:1104)
        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 com.rabbitmq.client.impl.SocketFrameHandler.sendHeader(SocketFrameHandler.java:129)
        at com.rabbitmq.client.impl.SocketFrameHandler.sendHeader(SocketFrameHandler.java:134)
        at com.rabbitmq.client.impl.AMQConnection.start(AMQConnection.java:276)
        at com.rabbitmq.client.ConnectionFactory.newConnection(ConnectionFactory.java:590)
        at com.rabbitmq.client.ConnectionFactory.newConnection(ConnectionFactory.java:612)
        at com.rm.rabbitmq.tls.Example2.main(Example2.java:40)}

    )
    javax.net.ssl|FINE|01|main|2022-06-02 22:08:47.176 IST|SSLSocketImpl.java:1510|close the underlying socket
    javax.net.ssl|FINE|01|main|2022-06-02 22:08:47.176 IST|SSLSocketImpl.java:1529|close the SSL connection (initiative)
    Exception in thread "main" javax.net.ssl.SSLException: Couldn't kickstart handshaking
        at sun.security.ssl.Alert.createSSLException(Alert.java:127)
        at sun.security.ssl.TransportContext.fatal(TransportContext.java:370)
        at sun.security.ssl.TransportContext.fatal(TransportContext.java:313)
        at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:411)
        at sun.security.ssl.SSLSocketImpl.ensureNegotiated(SSLSocketImpl.java:819)
        at sun.security.ssl.SSLSocketImpl.access$200(SSLSocketImpl.java:75)
        at sun.security.ssl.SSLSocketImpl$AppOutputStream.write(SSLSocketImpl.java:1104)
        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 com.rabbitmq.client.impl.SocketFrameHandler.sendHeader(SocketFrameHandler.java:129)
        at com.rabbitmq.client.impl.SocketFrameHandler.sendHeader(SocketFrameHandler.java:134)
        at com.rabbitmq.client.impl.AMQConnection.start(AMQConnection.java:276)
        at com.rabbitmq.client.ConnectionFactory.newConnection(ConnectionFactory.java:590)
        at com.rabbitmq.client.ConnectionFactory.newConnection(ConnectionFactory.java:612)
        at com.rm.rabbitmq.tls.Example2.main(Example2.java:40)
        Suppressed: java.net.SocketException: Broken pipe (Write failed)
            at java.net.SocketOutputStream.socketWrite0(Native Method)
            at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:111)
            at java.net.SocketOutputStream.write(SocketOutputStream.java:155)
            at sun.security.ssl.SSLSocketOutputRecord.encodeAlert(SSLSocketOutputRecord.java:83)
            at sun.security.ssl.TransportContext.fatal(TransportContext.java:401)
            ... 14 more
    Caused by: java.net.SocketException: Broken pipe (Write failed)
        at java.net.SocketOutputStream.socketWrite0(Native Method)
        at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:111)
        at java.net.SocketOutputStream.write(SocketOutputStream.java:155)
        at sun.security.ssl.SSLSocketOutputRecord.flush(SSLSocketOutputRecord.java:268)
        at sun.security.ssl.HandshakeOutStream.flush(HandshakeOutStream.java:89)
        at sun.security.ssl.ClientHello$ClientHelloKickstartProducer.produce(ClientHello.java:572)
        at sun.security.ssl.SSLHandshake.kickstart(SSLHandshake.java:509)
        at sun.security.ssl.ClientHandshakeContext.kickstart(ClientHandshakeContext.java:115)
        at sun.security.ssl.TransportContext.kickstart(TransportContext.java:250)
        at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:394)
        ... 12 more

openssl s_client -connect localhost:5672

CONNECTED(00000005)
    4305976812:error:1400410B:SSL routines:CONNECT_CR_SRVR_HELLO:wrong version number:/System/Volumes/Data/SWE/macOS/BuildRoots/9dc5c14c79/Library/Caches/com.apple.xbs/Sources/libressl/libressl-56.60.3/libressl-2.8/ssl/ssl_pkt.c:386:
    ---
    no peer certificate available
    ---
    No client certificate CA names sent
    ---
    SSL handshake has read 5 bytes and written 0 bytes
    ---
    New, (NONE), Cipher is (NONE)
    Secure Renegotiation IS NOT supported
    Compression: NONE
    Expansion: NONE
    No ALPN negotiated
    SSL-Session:
        Protocol  : TLSv1.2
        Cipher    : 0000
        Session-ID: 
        Session-ID-ctx: 
        Master-Key: 
        Start Time: 1654306955
        Timeout   : 7200 (sec)
        Verify return code: 0 (ok)
    ---

openssl s_client -connect localhost:5671

CONNECTED(00000005)
write:errno=54
---
no peer certificate available
---
No client certificate CA names sent
---
SSL handshake has read 0 bytes and written 0 bytes
---
New, (NONE), Cipher is (NONE)
Secure Renegotiation IS NOT supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
SSL-Session:
    Protocol  : TLSv1.2
    Cipher    : 0000
    Session-ID: 
    Session-ID-ctx: 
    Master-Key: 
    Start Time: 1654307520
    Timeout   : 7200 (sec)
    Verify return code: 0 (ok)
---

我已经花了一天的时间试图解决这个问题,但我仍然很容易受到如何解决这个问题。我已经访问了100个线程来解决这个问题,但没有线索。
非常感谢您的关注和参与。

rn0zuynd

rn0zuynd1#

3天/夜后,我修复了这个问题。
步骤:1我错误地调用了factory.useSslProtocol(“TLSv1.2”);它已经被称为factory.useSslProtocol(c);

ConnectionFactory factory = new ConnectionFactory();
            factory.setHost("localhost");
            factory.setPort(5671);
            factory.useSslProtocol(c);

第2步:我还没有完成这一步。将证书导入JDK cacert存储

keytool -import  -trustcacerts -alias Server_cert1 -file /opt/homebrew/etc/rabbitmq/testca/cacert.cer -keystore /Library/Java/JavaVirtualMachines/jdk1.8.0_311.jdk/Contents/Home/jre/lib/security/cacerts

请注意代码:SSLContext.getInstance("TLSv1.3")这段代码提取添加到JDK cacert存储中的证书,因此请记下它。
第3步:每当我们想保护一个连接时,我们必须更改rabbitmq.config或advanced.config来配置证书。
早期的高级.conf文件。

[
  {ssl, [{versions, ['tlsv1.3', 'tlsv1.2','tlsv1.1']}]},
  {rabbit, [
     {ssl_listeners, [5671]},
     {auth_mechanisms, ['PLAIN', 'AMQPLAIN', 'EXTERNAL']},
     {ssl_options, [{cacertfile, "/Users/global/Documents/tls-gen/basic/result/ca_certificate.pem"},
                    {certfile,   "/Users/global/Documents/tls-gen/basic/result/server_certificate.pem"},
                    {keyfile,    "/Users/global/Documents/tls-gen/basic/result/server_del1-lmc-n72765.local_key.pem"},
                    {verify,     verify_peer},
                    {password,  "1234"},
                    {fail_if_no_peer_cert, true}]}
   ]}
].

现在我更改为

[
  {ssl, [{versions, ['tlsv1.3', 'tlsv1.2','tlsv1.1']}]},
  {rabbit, [
     {ssl_listeners, [5671]},
     {auth_mechanisms, ['PLAIN', 'AMQPLAIN', 'EXTERNAL']},
     {ssl_options, [{cacertfile, "/opt/homebrew/etc/rabbitmq/testca/cacert.pem"},
                    {certfile,   "/opt/homebrew/etc/rabbitmq/server/cert.pem"},
                    {keyfile,    "/opt/homebrew/etc/rabbitmq/server/key.pem"},
                    {verify,     verify_peer},
                    {password,  "1234"},
                    {fail_if_no_peer_cert, true}]}
   ]}
].

我将在博客中介绍rabbitMq SSL配置。

相关问题