当前位置: 首页 > 知识库问答 >
问题:

使用证书身份验证进行任何连接尝试时RabbitMQ SSL握手失败

戚云
2023-03-14

我目前正在尝试迁移一些Java组件,以通过SSL客户端证书而不是PLAIN方法执行RabbitMQ连接身份验证,但是,几天后,我仍然在努力,因为所有java组件连接尝试都会遇到握手错误。在尝试使用SSL证书时查看RabbitMQ:握手错误,或者在使用SpringAMQP时查看RabbitMQ SSL给握手失败,不幸的是没有为我使用任何结果。

我试图使其工作的环境是一个运行UbuntuLTS14.04的“继承的”VirtualBox虚拟机,它几乎代表了我想要部署到的环境。

rabbitmqctl报告的输出如下:

Status of node 'rabbit@developer-VirtualBox' ...
[{pid,23352},
 {running_applications,
     [{rabbitmq_management,"RabbitMQ Management Console","3.4.2"},
      {rabbitmq_web_dispatch,"RabbitMQ Web Dispatcher","3.4.2"},
      {webmachine,"webmachine","1.10.3-rmq3.4.2-gite9359c7"},
      {mochiweb,"MochiMedia Web Server","2.7.0-rmq3.4.2-git680dba8"},
      {rabbitmq_management_agent,"RabbitMQ Management Agent","3.4.2"},
      {rabbit,"RabbitMQ","3.4.2"},
      {ssl,"Erlang/OTP SSL application","5.3.2"},
      {public_key,"Public key infrastructure","0.21"},
      {crypto,"CRYPTO version 2","3.2"},
      {asn1,"The Erlang ASN1 compiler version 2.0.4","2.0.4"},
      {os_mon,"CPO  CXC 138 46","2.2.14"},
      {inets,"INETS  CXC 138 49","5.9.7"},
      {rabbitmq_auth_mechanism_ssl,
          "RabbitMQ SSL authentication (SASL EXTERNAL)","3.4.2"},
      {amqp_client,"RabbitMQ AMQP Client","3.4.2"},
      {xmerl,"XML parser","1.3.5"},
      {mnesia,"MNESIA  CXC 138 12","4.11"},
      {sasl,"SASL  CXC 138 11","2.3.4"},
      {stdlib,"ERTS  CXC 138 10","1.19.4"},
      {kernel,"ERTS  CXC 138 10","2.16.4"}]},
 {os,{unix,linux}},
 {erlang_version,
     "Erlang R16B03 (erts-5.10.4) [source] [64-bit] [async-threads:30] [kernel-poll:true]\n"},
 {memory,
     [{total,42662672},
      {connection_readers,0},
      {connection_writers,0},
      {connection_channels,0},
      {connection_other,5264},
      {queue_procs,2632},
      {queue_slave_procs,0},
      {plugins,411368},
      {other_proc,14374616},
      {mnesia,59360},
      {mgmt_db,124224},
      {msg_index,34312},
      {other_ets,1135040},
      {binary,42680},
      {code,21795549},
      {atom,793505},
      {other_system,3884122}]},
 {alarms,[]},
 {listeners,[{clustering,25672,"::"},{amqp,5672,"::"},{'amqp/ssl',5671,"::"}]},
 {vm_memory_high_watermark,0.4},
 {vm_memory_limit,1658211532},
 {disk_free_limit,50000000},
 {disk_free,43703377920},
 {file_descriptors,
     [{total_limit,924},{total_used,4},{sockets_limit,829},{sockets_used,2}]},
 {processes,[{limit,1048576},{used,191}]},
 {run_queue,0},
 {uptime,12}]

Cluster status of node 'rabbit@developer-VirtualBox' ...
[{nodes,[{disc,['rabbit@developer-VirtualBox']}]},
 {running_nodes,['rabbit@developer-VirtualBox']},
 {cluster_name,<<"rabbit@developer-VirtualBox">>},
 {partitions,[]}]

Application environment of node 'rabbit@developer-VirtualBox' ...
[{amqp_client,[{prefer_ipv6,false},{ssl_options,[]}]},
 {asn1,[]},
 {crypto,[]},
 {inets,[]},
 {kernel,
     [{error_logger,tty},
      {inet_default_connect_options,[{nodelay,true}]},
      {inet_dist_listen_max,25672},
      {inet_dist_listen_min,25672}]},
 {mnesia,[{dir,"/var/lib/rabbitmq/mnesia/rabbit@developer-VirtualBox"}]},
 {mochiweb,[]},
 {os_mon,
     [{start_cpu_sup,false},
      {start_disksup,false},
      {start_memsup,false},
      {start_os_sup,false}]},
 {public_key,[]},
 {rabbit,
     [{auth_backends,[rabbit_auth_backend_internal]},
      {auth_mechanisms,['EXTERNAL']},
      {backing_queue_module,rabbit_variable_queue},
      {channel_max,0},
      {cluster_keepalive_interval,10000},
      {cluster_nodes,{[],disc}},
      {cluster_partition_handling,ignore},
      {collect_statistics,fine},
      {collect_statistics_interval,5000},
      {default_permissions,[<<".*">>,<<".*">>,<<".*">>]},
      {default_user,<<"guest">>},
      {default_user_tags,[administrator]},
      {default_vhost,<<"/">>},
      {delegate_count,16},
      {disk_free_limit,50000000},
      {enabled_plugins_file,"/etc/rabbitmq/enabled_plugins"},
      {error_logger,
          {file,"/var/log/rabbitmq/rabbit@developer-VirtualBox.log"}},
      {frame_max,131072},
      {halt_on_upgrade_failure,true},
      {handshake_timeout,10000},
      {heartbeat,580},
      {hipe_compile,false},
      {hipe_modules,
          [rabbit_reader,rabbit_channel,gen_server2,rabbit_exchange,
           rabbit_command_assembler,rabbit_framing_amqp_0_9_1,rabbit_basic,
           rabbit_event,lists,queue,priority_queue,rabbit_router,rabbit_trace,
           rabbit_misc,rabbit_binary_parser,rabbit_exchange_type_direct,
           rabbit_guid,rabbit_net,rabbit_amqqueue_process,
           rabbit_variable_queue,rabbit_binary_generator,rabbit_writer,
           delegate,gb_sets,lqueue,sets,orddict,rabbit_amqqueue,
           rabbit_limiter,gb_trees,rabbit_queue_index,
           rabbit_exchange_decorator,gen,dict,ordsets,file_handle_cache,
           rabbit_msg_store,array,rabbit_msg_store_ets_index,rabbit_msg_file,
           rabbit_exchange_type_fanout,rabbit_exchange_type_topic,mnesia,
           mnesia_lib,rpc,mnesia_tm,qlc,sofs,proplists,credit_flow,pmon,
           ssl_connection,tls_connection,ssl_record,tls_record,gen_fsm,ssl]},
      {log_levels,[{connection,info}]},
      {loopback_users,[<<"guest">>]},
      {mnesia_table_loading_timeout,30000},
      {msg_store_file_size_limit,16777216},
      {msg_store_index_module,rabbit_msg_store_ets_index},
      {plugins_dir,
          "/usr/lib/rabbitmq/lib/rabbitmq_server-3.4.2/sbin/../plugins"},
      {plugins_expand_dir,
          "/var/lib/rabbitmq/mnesia/rabbit@developer-VirtualBox-plugins-expand"},
      {queue_index_max_journal_entries,65536},
      {reverse_dns_lookups,false},
      {sasl_error_logger,
          {file,"/var/log/rabbitmq/rabbit@developer-VirtualBox-sasl.log"}},
      {server_properties,[]},
      {ssl_allow_poodle_attack,false},
      {ssl_apps,[asn1,crypto,public_key,ssl]},
      {ssl_cert_login_from,distinguished_name},
      {ssl_handshake_timeout,5000},
      {ssl_listeners,[5671]},
      {ssl_options,
          [{cacertfile,"/home/developer/rabbitmqcert/devcafiles/cacert.pem"},
           {certfile,"/home/developer/rabbitmqcert/rabbitmq.public.pem"},
           {keyfile,"/home/developer/rabbitmqcert/rabbitmq.private.pem"},
           {verify,verify_peer},
           {ssl_cert_login_from,organization},
           {fail_if_no_peer_cert,true}]},
      {tcp_listen_options,
          [binary,
           {packet,raw},
           {reuseaddr,true},
           {backlog,128},
           {nodelay,true},
           {linger,{true,0}},
           {exit_on_close,false}]},
      {tcp_listeners,[5672]},
      {trace_vhosts,[]},
      {vm_memory_high_watermark,0.4},
      {vm_memory_high_watermark_paging_ratio,0.5}]},
 {rabbitmq_auth_mechanism_ssl,[{name_from,distinguished_name}]},
 {rabbitmq_management,
     [{http_log_dir,none},
      {listener,[{port,15672}]},
      {load_definitions,none},
      {rates_mode,basic},
      {sample_retention_policies,
          [{global,[{605,5},{3660,60},{29400,600},{86400,1800}]},
           {basic,[{605,5},{3600,60}]},
           {detailed,[{10,5}]}]}]},
 {rabbitmq_management_agent,[]},
 {rabbitmq_web_dispatch,[]},
 {sasl,[{errlog_type,error},{sasl_error_logger,false}]},
 {ssl,
     [{protocol_version,['tlsv1.2','tlsv1.1',tlsv1,sslv3]},
      {versions,['tlsv1.2','tlsv1.1']}]},
 {stdlib,[]},
 {webmachine,[{error_handler,rabbit_webmachine_error_handler}]},
 {xmerl,[]}]

Connections:

Channels:

Queues on /:

Exchanges on /:
name    type    durable auto_delete internal    arguments   policy
    direct  true    false   false   []  
amq.direct  direct  true    false   false   []  
amq.fanout  fanout  true    false   false   []  
amq.headers headers true    false   false   []  
amq.match   headers true    false   false   []  
amq.rabbitmq.log    topic   true    false   true    []  
amq.rabbitmq.trace  topic   true    false   true    []  
amq.topic   topic   true    false   false   []  

Bindings on /:

Consumers on /:

Permissions on /:
user    configure   write   read
O=dev,CN=rules  .*  .*  .*
guest   .*  .*  .*

Policies on /:

Parameters on /:

通过它,我可以看到:

  • _rabbitmq_auth_mechanism_ssl_插件处于活动状态
  • 我正在监听端口5671上的SSL连接
  • 唯一被接受的认证机制是EXTERNAL
  • 我只接受TLS v1.1和TLS v1.2
  • 有一个用户_O=dev,CN=rules_定义,匹配客户端证书中的主题。该用户没有关联的密码(使用_sudoRabbitmqctlclear_password"O=dev,CN=规则"清除_管理屏幕反映了这一点)
  • CA证书文件从_ /home/developer/rabbitmqcert/devcafiles/cacert.pem_读取。这对应于为开发目的创建的CA,其中使用的所有公钥(服务器和客户端都一样)都由它签名

为了简单(和理智),我尝试使用以下Java代码连接到RabbitMQ实例:

package com.rabbitmq.sample;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.DefaultSaslConfig;
import com.rabbitmq.client.QueueingConsumer;

public class CertificateAuthenticatedRabbitMQClientExample {

    private static final String CLIENT_CERTIFICATE_PASSWORD = "MySecretPassword";
    private static final String QUEUE_USED = "sampleQueue";
    public static void main(String[] args) throws UnrecoverableKeyException, NoSuchAlgorithmException, KeyStoreException, IOException, CertificateException, KeyManagementException, InterruptedException {
        SSLContext sslContext = SSLContext.getInstance("TLSv1.2");
        KeyManager[] clientKeyManagerList = null;
        try(FileInputStream clientCertificateInputStream = new FileInputStream(new File("/home/developer/rabbitmqcert/ruleprocessing.password.p12"))) {
            KeyStore clientKeStore = KeyStore.getInstance("PKCS12");                                        //Create a clean KeyStore
            clientKeStore.load(clientCertificateInputStream, CLIENT_CERTIFICATE_PASSWORD.toCharArray());    //Load the client's certificate into the keystore
            KeyManagerFactory clientSSLKeyManagerFactory = KeyManagerFactory.getInstance("SunX509");
            clientSSLKeyManagerFactory.init(clientKeStore, CLIENT_CERTIFICATE_PASSWORD.toCharArray());
            clientKeyManagerList = clientSSLKeyManagerFactory.getKeyManagers();                             //Get list of key managers (in essence, only the keystore with the client certificate)
        }
        TrustManager[] clientTrustManagerList = {
          new X509TrustManager() {
              //Dummy trust store that trusts any server you connect to.
              //For demo purposes only
              @Override
              public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {}
              @Override
              public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {}
              @Override
              public X509Certificate[] getAcceptedIssuers() { return null;}
          }
        };
        sslContext.init(clientKeyManagerList, clientTrustManagerList, null);        //Initialize SSL context with the key and trust managers we've created/loaded before

        ConnectionFactory rabbitMqConnectionFactory = new ConnectionFactory();      //Create factory
        rabbitMqConnectionFactory.setHost("localhost");
        rabbitMqConnectionFactory.setPort(5671);
        rabbitMqConnectionFactory.setSaslConfig(DefaultSaslConfig.EXTERNAL);        //Set authentication method as SSL auth
        rabbitMqConnectionFactory.useSslProtocol(sslContext);                       //Set the created SSL context as the one to use
        Connection rabbitMqOutboundConnection = null;
        Channel rabbitMqOutboundChannel = null;
        try {
            rabbitMqOutboundConnection = rabbitMqConnectionFactory.newConnection();
            rabbitMqOutboundChannel = rabbitMqOutboundConnection.createChannel();
            rabbitMqOutboundChannel.queueDeclare(QUEUE_USED, false, false, false, null);
            rabbitMqOutboundChannel.basicPublish("", QUEUE_USED, null, "This is a sample message".getBytes());
            System.out.println("Message successfully sent to queue");
        }finally{
            if(rabbitMqOutboundChannel != null) {
                rabbitMqOutboundChannel.close();
            }
            if(rabbitMqOutboundConnection != null) {
                rabbitMqOutboundConnection.close();
            }
        }
        Connection rabbitMqInboundConnection = null;
        Channel rabbitMqInboundChannel = null;
        try {
            rabbitMqInboundConnection = rabbitMqConnectionFactory.newConnection();
            rabbitMqInboundChannel = rabbitMqInboundConnection.createChannel();
            rabbitMqInboundChannel.queueDeclare(QUEUE_USED, false, false, false, null);
            QueueingConsumer rabbitMqQueueConsumer = new QueueingConsumer(rabbitMqInboundChannel);
            rabbitMqInboundChannel.basicConsume(QUEUE_USED, true, rabbitMqQueueConsumer);
            QueueingConsumer.Delivery deliveryResult = rabbitMqQueueConsumer.nextDelivery();
            System.out.println("Message read from the queue: " + new String(deliveryResult.getBody()));
        }finally{
            if(rabbitMqInboundChannel != null) {
                rabbitMqInboundChannel.close();
            }
            if(rabbitMqInboundConnection != null) {
                rabbitMqInboundConnection.close();
            }
        }
    }

}

我,但是,总是迎接一个异常线程"main"java.net.SocketExc0019:破碎的管道错误执行和,看着RabbitMQ服务器日志,我看到:

=INFO REPORT==== 29-Dec-2014::15:55:30 ===
accepting AMQP connection <0.644.0> (127.0.0.1:35299 -> 127.0.0.1:5671)

=ERROR REPORT==== 29-Dec-2014::15:55:30 ===
SSL: certify: ssl_handshake.erl:1343:Fatal error: handshake failure

根据我在互联网和这里看到的,我试图将验证值更改为verify_none但是,当这样做时,我会得到以下结果:

=INFO REPORT==== 29-Dec-2014::14:51:13 ===
accepting AMQP connection <0.311.0> (127.0.0.1:35271 -> 127.0.0.1:5671)

=ERROR REPORT==== 29-Dec-2014::14:51:17 ===
closing AMQP connection <0.311.0> (127.0.0.1:35271 -> 127.0.0.1:5671):
{handshake_error,starting,0,
                 {amqp_error,access_refused,
                             "EXTERNAL login refused: no peer certificate",
                             'connection.start_ok'}}

根据SSL疑难解答页面下给出的建议,我已尝试执行到服务器的s_客户端连接,根据verify的值再次执行不同的结果。如果将verify设置为verify_peer,则会得到以下结果:

developer@developer-VirtualBox:~/rabbitmqcert$ openssl s_client -tls1_2 -connect localhost:5671 -cert ruleprocessing.public.pem -key ruleprocessing.private.pem -CAfile devcafiles/cacert.pem 
CONNECTED(00000003)
depth=1 CN = RabbitMQCA
verify return:1
depth=0 CN = rabbitmq, O = dev
verify return:1
139797055162016:error:14094410:SSL routines:SSL3_READ_BYTES:sslv3 alert handshake failure:s3_pkt.c:1260:SSL alert number 40
139797055162016:error:1409E0E5:SSL routines:SSL3_WRITE_BYTES:ssl handshake failure:s3_pkt.c:596:
---
Certificate chain
 0 s:/CN=rabbitmq/O=dev
   i:/CN=RabbitMQCA
 1 s:/CN=RabbitMQCA
   i:/CN=RabbitMQCA
---
Server certificate
-----BEGIN CERTIFICATE-----
<<OMMITED>>
-----END CERTIFICATE-----
subject=/CN=rabbitmq/O=dev
issuer=/CN=RabbitMQCA
---
Acceptable client certificate CA names
/CN=RabbitMQCA
---
SSL handshake has read 1646 bytes and written 2103 bytes
---
New, TLSv1/SSLv3, Cipher is AES256-SHA256
Server public key is 2048 bit
Secure Renegotiation IS NOT supported
Compression: NONE
Expansion: NONE
SSL-Session:
    Protocol  : TLSv1.2
    Cipher    : AES256-SHA256
    Session-ID: FC972B9A5D3EC359DC0467C8F02410E3AD66DA151C4411C0D5892115A439431A
    Session-ID-ctx: 
    Master-Key: E4FE793C71692852F6F3C4E9C5CB17774D8A50511338EF2E75691DC0DC2119F56611FC959C12429BBAFD46EC760ED713
    Key-Arg   : None
    PSK identity: None
    PSK identity hint: None
    SRP username: None
    Start Time: 1419871438
    Timeout   : 7200 (sec)
    Verify return code: 0 (ok)
---

如您所见,握手错误在开始时发生,但随后似乎会恢复。

如果将verify设置为verify_none,则会得到以下结果:

CONNECTED(00000003)
depth=1 CN = RabbitMQCA
verify return:1
depth=0 CN = rabbitmq, O = dev
verify return:1
---
Certificate chain
 0 s:/CN=rabbitmq/O=dev
   i:/CN=RabbitMQCA
 1 s:/CN=RabbitMQCA
   i:/CN=RabbitMQCA
---
Server certificate
-----BEGIN CERTIFICATE-----
<<OMMITED>>
-----END CERTIFICATE-----
subject=/CN=rabbitmq/O=dev
issuer=/CN=RabbitMQCA
---
No client certificate CA names sent
---
SSL handshake has read 1666 bytes and written 663 bytes
---
New, TLSv1/SSLv3, Cipher is AES256-SHA256
Server public key is 2048 bit
Secure Renegotiation IS NOT supported
Compression: NONE
Expansion: NONE
SSL-Session:
    Protocol  : TLSv1.2
    Cipher    : AES256-SHA256
    Session-ID: C4156551790BA116DC38A981728A71768D0B53AAEBEE969A4DA150746E5373FB
    Session-ID-ctx: 
    Master-Key: 3470DD0C0247B94EA784C3CEF94888C160205E9F06C14869B564A00AF5E4F7FAF5B4FC977E290B80DBCD140133F75AC0
    Key-Arg   : None
    PSK identity: None
    PSK identity hint: None
    SRP username: None
    Start Time: 1419871570
    Timeout   : 7200 (sec)
    Verify return code: 0 (ok)
---

这一次,握手错误不会在开始时发生。

顺便说一句,因为我不太确定我得到的虚拟机的“清洁度”,我实际上尝试过创建一个新的虚拟机(相同的Ubuntu版本),安装RabbitMQ(相同的版本),以几乎相同的方式配置它(唯一改变的是证书位置)并且运行相同的客户端代码(证书路径已修改)。最后的结果是成功的。不幸的是,我现在不能做太多关于让这个虚拟机用作开发虚拟机的事情。

TL;博士将运行在Ubuntu VM上的RabbitMQ服务器配置为使用证书身份验证接受来自Java客户端的SSL连接后,所有连接尝试都会失败,如果verify=verify\u peer,则握手失败;如果verify=verify\u none,则外部登录被拒绝:如果verify=verify\u none,则无对等证书

共有1个答案

怀飞扬
2023-03-14

问题与客户端证书的签名方式有关。它们是使用服务器ca_扩展而不是客户端ca_扩展进行签名的。

 类似资料:
  • 我一直在尝试使用Firebase Auth执行电话身份验证方法,我已确保遵循所有步骤,添加我的包名称,使用添加SHA Key keytool -list -v -keystore “%USERPROFILE%.android\debug.keystore” -alias androiddebugkey -storepass android -keypass android 然后添加所有的依赖项,并

  • 问题内容: 我需要导入证书,以便向Spring Boot应用程序中的外部服务发出http请求。 我该如何设置Spring Boot来做到这一点? 那里有很多信息,但我发现所有这些都令人困惑。似乎我可能只需要创建类似“ truststore.jks”密钥库的内容并导入正确的证书,然后将一些条目添加到我的application.properties中即可。 问题答案: 打开您的终端或 回答所有问题。在

  • 当使用Firebase Auth进行身份验证时,我想自动输入通过SMS接收的代码。我能够接收短信并手动完成身份验证过程,但当我使用SmsRetriever时,应用程序崩溃,然后显示底部工作表对话框。这是Logcat中显示的所有内容: [SmsRetrieverHelper]SMS校验码请求失败:未知状态代码:17010 null 用户输入其电话号码的代码片段: 这是片段中的代码,用户必须在其中输入

  • 我正在尝试使用urllib3连接到网页。代码如下所示。 如果我们假设url是需要使用用户名和密码进行身份验证的某个网页,那么我是否使用正确的代码进行身份验证? 我使用urllib2做这件事很舒服,但使用urllib3做不到同样的事情。 非常感谢

  • jwt不应该仅仅用于认证用户吗?我读到过可以在里面存储非敏感的东西,比如用户ID。将权限级别之类的东西存储在令牌中可以吗?这样我可以避免数据库调用。

  • 问题内容: 如何使用node.js连接到mongodb? 我有node-mongodb-native驱动程序。 显然有0个文档。 是这样吗? 用户名和密码放在哪里? 另外,我该如何插入? 谢谢。 问题答案: 根据来源: 连接后: