RabbitMQ DotNet客户端无法连接到SSL

时间:2016-05-27 16:13:40

标签: .net ssl mono rabbitmq haproxy

我们正在努力使PoC显示用不同语言编写的应用程序可以通过RabbitMQ代理在一个组织中进行通信。我们运行香草RabbitMQ码头图像 rabbitmq:3.6.1-management 和vanilla haproxy docker图像 haproxy:1.6.5 执行SSL:

frontend amqp_front
    bind *:5672 tcp-ut 5s
    mode tcp
    timeout client 60s
    timeout client-fin 1s
    no option clitcpka
    default_backend amqp_back

frontend amqp_front_ssl
    bind *:5671 tcp-ut 5s ssl crt /etc/certs/haproxy/rmq.pem ca-file /etc/certs/haproxy/root.crt verify required
    mode tcp
    timeout client 60s
    timeout client-fin 1s
    no option clitcpka
    acl client ssl_c_s_dn(CN) -m str cli
    tcp-request content reject if !client
    default_backend amqp_back

RabbitMQ配置是:

[
  {rabbit,
    [
      { tcp_listeners, [ 5672 ] },
      { ssl_listeners, [ ] },
      {default_pass, <<"pwd">>},
      {default_user, <<"usr">>},
      {default_vhost, <<"default">>},
      {loopback_users, []}
    ]
  },
  { rabbitmq_management, [
      { listener, [
        { port, 15672 },
        { ssl, false }
        ]
      }
    ]
  }
].

我们在 Go &amp;中编写了一个简单的代码 Node.js ,它们都加载root.crt,cli.crt&amp; cli.key并成功连接到SSL端口5671并使用。

尝试使用RabbitMQ.Client.dll(版本3.6.0,3.6.1,3.6.2)在.Net中编写相同的简单代码失败了:

X509Store store = new X509Store (StoreName.Root, StoreLocation.LocalMachine);
store.Open (OpenFlags.ReadOnly);

var factory = new ConnectionFactory ();
factory.Ssl.Enabled = true;
factory.Ssl.ServerName = "rmq";
factory.Ssl.Certs = store.Certificates;
factory.Ssl.CertPassphrase = "";
factory.HostName = "localhost";
factory.Port = 5671;
factory.UserName = "usr";
factory.Password = "pwd";
factory.VirtualHost = "default";

var conn = factory.CreateConnection ()

发生的事情是.Net客户端忽略端口5671忽略上面的设置,它只是转到5672.如果5672打开 - 连接到它,如果5672关闭 - 连接被拒绝失败。

Go和Node.js中的代码证明我的SSL设置有效。 .Net客户端的错误表明SSL内容甚至没有机会跳入。

我在debian jessie&amp;单声道。

我错过了一些明显的东西吗?

2 个答案:

答案 0 :(得分:2)

这是RabbitMQ .net客户端3.6.2库在使用SSL时不遵守指定端口的问题。

它已被修复,并且在3.6.3发布时可用(它们与服务器同步发布,因此不知道何时发布)。

您的选择是: -

  • 使用旧版本的.net客户端
  • 从最新源
  • 构建.net客户端
  • 如果可以,请使用标准端口
  • 等待3.6.3发布

答案 1 :(得分:0)

我从Masstransit Net Core Client连接到docker rabbitmq容器时遇到类似的问题。以下是我有效的配置,可能会有用:

一些注意事项: Masstransit:5.1.5,Net Core版本:2.2

Docker-compose:

...
  bus_rabbitmq:
    image: rabbitmq:3-management
    hostname: docker-host
    environment:
      RABBITMQ_DEFAULT_VHOST: "databus"
      RABBITMQ_SSL_CACERTFILE: "/app/certs/dev/myCA.pem"
      RABBITMQ_SSL_CERTFILE: "/app/certs/dev/rabbitmq/rabbit-server.crt"
      RABBITMQ_SSL_FAIL_IF_NO_PEER_CERT: "false"
      RABBITMQ_SSL_KEYFILE: "/app/certs/dev/rabbitmq/rabbit-server.key"
      RABBITMQ_SSL_VERIFY: "verify_peer"
      RABBITMQ_MANAGEMENT_SSL_CACERTFILE: "/app/certs/dev/myCA.pem"
      RABBITMQ_MANAGEMENT_SSL_CERTFILE: "/app/certs/dev/rabbitmq/rabbit-server.crt"
      RABBITMQ_MANAGEMENT_SSL_FAIL_IF_NO_PEER_CERT: "false"
      RABBITMQ_MANAGEMENT_SSL_VERIFY: "verify_peer"
      RABBITMQ_MANAGEMENT_SSL_KEYFILE: "/app/certs/dev/rabbitmq/rabbit-server.key"
    ports:
      - "15672:15672"
      - "15671:15671"
      - "5672:5672"
      - "5671:5671"
    volumes:
    - ./certs:/app/certs
    networks:
      - local_network
...

客户端配置:

...
var rabbitCredentials = CredentialsService.RetrieveRabbitMqCredentials();

builder.Register(c =>
    {
        return Bus.Factory.CreateUsingRabbitMq(sbc =>
        {
            sbc.Host(rabbitCredentials.RabbitConnectionString, 5671, rabbitCredentials.RabbitVHost, h =>
            {
                var certData = CertsService.RetrieveCertificateInfo(ServiceType.RabbitMq);

                h.Username(rabbitCredentials.UserName);
                h.Password(rabbitCredentials.Password);
                h.Heartbeat(10);
                h.UseSsl(s =>
                {
                    s.Protocol = SslProtocols.Tls12;
                    s.Certificate = X509Certificate.CreateFromCertFile(certData.Path);
                    s.AllowPolicyErrors(SslPolicyErrors.RemoteCertificateNameMismatch);
                    s.UseCertificateAsAuthenticationIdentity = false;
                });
            });

            sbc.ReceiveEndpoint("data_queue", ec =>
            {
                // loading consumers
                ec.LoadFrom(c);

                // loading saga state machines
                //ec.LoadStateMachineSagas(c);
            });
        });
    })
    .As<IBusControl>()
    .As<IPublishEndpoint>()
    .SingleInstance();
...

我需要使用:

  

AllowPolicyErrors(SslPolicyErrors.RemoteCertificateNameMismatch)

为避免我的证书中的服务器名称不匹配。